Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Generalization of constraints on page allocation and implementation/use
[palacios.git] / palacios / src / palacios / mmu / vmm_shdw_pg_tlb.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  * Author: Chunxiao Diao <chunxiaodiao2012@u.northwestern.edu> 
16  *
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22 #include <palacios/vmm_shadow_paging.h>
23 #include <palacios/vmm_ctrl_regs.h>
24
25 #include <palacios/vm_guest.h>
26 #include <palacios/vm_guest_mem.h>
27
28
29 #ifndef V3_CONFIG_DEBUG_SHDW_PG_VTLB
30 #undef PrintDebug
31 #define PrintDebug(fmt, ...)
32 #endif
33
34
35 struct shadow_page_data {
36     v3_reg_t cr3;
37     addr_t page_pa;
38   
39     struct list_head page_list_node;
40 };
41
42
43 struct vtlb_local_state {
44  
45     struct list_head page_list;
46
47 };
48
49
50 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
51
52
53 #include "vmm_shdw_pg_tlb_32.h"
54 #include "vmm_shdw_pg_tlb_32pae.h"
55 #include "vmm_shdw_pg_tlb_64.h"
56
57
58
59 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
60     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
61     struct vtlb_local_state * impl_state = (struct vtlb_local_state *)(state->local_impl_data);
62     v3_reg_t cur_cr3 = core->ctrl_regs.cr3;
63     struct shadow_page_data * page_tail = NULL;
64     addr_t shdw_page = 0;
65
66     if (!list_empty(&(impl_state->page_list))) {
67         page_tail = list_tail_entry(&(impl_state->page_list), struct shadow_page_data, page_list_node);
68
69
70         if (page_tail->cr3 != cur_cr3) {
71             PrintDebug(core->vm_info, core, "Reusing old shadow Page: %p (cur_CR3=%p)(page_cr3=%p) \n",
72                        (void *)(addr_t)page_tail->page_pa, 
73                        (void *)(addr_t)cur_cr3, 
74                        (void *)(addr_t)(page_tail->cr3));
75
76             list_move(&(page_tail->page_list_node), &(impl_state->page_list));
77
78             memset(V3_VAddr((void *)(page_tail->page_pa)), 0, PAGE_SIZE_4KB);
79
80
81             return page_tail;
82         }
83     }
84
85     // else  
86
87     page_tail = (struct shadow_page_data *)V3_Malloc(sizeof(struct shadow_page_data));
88
89     if (!page_tail) {
90         PrintError(core->vm_info, core, "Cannot allocate\n");
91         return NULL;
92     }
93
94     page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,0,0);
95
96     if (!page_tail->page_pa) {
97         PrintError(core->vm_info, core, "Cannot allocate page\n");
98         return NULL;
99     }
100
101     PrintDebug(core->vm_info, core, "Allocating new shadow Page: %p (cur_cr3=%p)\n", 
102                (void *)(addr_t)page_tail->page_pa, 
103                (void *)(addr_t)cur_cr3);
104
105     page_tail->cr3 = cur_cr3;
106     list_add(&(page_tail->page_list_node), &(impl_state->page_list));
107
108     shdw_page = (addr_t)V3_VAddr((void *)(page_tail->page_pa));
109     memset((void *)shdw_page, 0, PAGE_SIZE_4KB);
110
111     return page_tail;
112 }
113
114
115
116 static int vtlb_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
117
118     V3_Print(vm, VCORE_NONE, "VTLB initialization\n");
119     return 0;
120 }
121
122 static int vtlb_deinit(struct v3_vm_info * vm) {
123     return 0;
124 }
125
126 static int vtlb_local_init(struct guest_info * core) {
127     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
128     struct vtlb_local_state * vtlb_state = NULL;
129
130     V3_Print(core->vm_info, core, "VTLB local initialization\n");
131
132     vtlb_state = (struct vtlb_local_state *)V3_Malloc(sizeof(struct vtlb_local_state));
133
134     if (!vtlb_state) {
135         PrintError(core->vm_info, core, "Cannot allocate\n");
136         return -1;
137     }
138
139     INIT_LIST_HEAD(&(vtlb_state->page_list));
140
141     state->local_impl_data = vtlb_state;
142
143     return 0;
144 }
145
146
147 static int vtlb_local_deinit(struct guest_info * core) {
148     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
149     struct vtlb_local_state * vtlb_state = state->local_impl_data;
150
151     struct shadow_page_data * shdw_pg = NULL;
152     struct shadow_page_data * tmp = NULL;
153
154     // free page list...
155     list_for_each_entry_safe(shdw_pg, tmp, &(vtlb_state->page_list), page_list_node) {
156         list_del(&(shdw_pg->page_list_node));
157         V3_FreePages((void *)shdw_pg->page_pa, 1);
158         V3_Free(shdw_pg);
159     }
160
161
162     V3_Free(vtlb_state);
163
164     return 0;
165 }
166
167
168 static int vtlb_activate_shdw_pt(struct guest_info * core) {
169     switch (v3_get_vm_cpu_mode(core)) {
170
171         case PROTECTED:
172             return activate_shadow_pt_32(core);
173             break;
174         case PROTECTED_PAE:
175             return activate_shadow_pt_32pae(core);
176             break;
177         case LONG:
178         case LONG_32_COMPAT:
179         case LONG_16_COMPAT:
180             return activate_shadow_pt_64(core);
181             break;
182         default:
183             PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
184             return -1;
185             break;
186     }
187
188     return 0;
189 }
190
191 static int vtlb_invalidate_shdw_pt(struct guest_info * core) {
192     return vtlb_activate_shdw_pt(core);
193 }
194
195
196 static int vtlb_handle_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
197   
198         switch (v3_get_vm_cpu_mode(core)) {
199             case PROTECTED:
200                 return handle_shadow_pagefault_32(core, fault_addr, error_code);
201                 break;
202             case PROTECTED_PAE:
203                 return handle_shadow_pagefault_32pae(core, fault_addr, error_code);
204             case LONG:
205             case LONG_32_COMPAT:
206             case LONG_16_COMPAT:
207                 return handle_shadow_pagefault_64(core, fault_addr, error_code);
208                 break;
209             default:
210                 PrintError(core->vm_info, core, "Unhandled CPU Mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
211                 return -1;
212         }
213 }
214
215
216 static int vtlb_handle_invlpg(struct guest_info * core, addr_t vaddr) {
217
218     switch (v3_get_vm_cpu_mode(core)) {
219         case PROTECTED:
220             return handle_shadow_invlpg_32(core, vaddr);
221             break;
222         case PROTECTED_PAE:
223             return handle_shadow_invlpg_32pae(core, vaddr);
224             break;
225         case LONG:
226         case LONG_32_COMPAT:
227         case LONG_16_COMPAT:
228             return handle_shadow_invlpg_64(core, vaddr);
229             break;
230         default:
231             PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
232             return -1;
233             break;
234     }
235 }
236
237 static struct v3_shdw_pg_impl vtlb_impl =  {
238     .name = "VTLB",
239     .init = vtlb_init,
240     .deinit = vtlb_deinit,
241     .local_init = vtlb_local_init,
242     .local_deinit = vtlb_local_deinit,
243     .handle_pagefault = vtlb_handle_pf,
244     .handle_invlpg = vtlb_handle_invlpg,
245     .activate_shdw_pt = vtlb_activate_shdw_pt,
246     .invalidate_shdw_pt = vtlb_invalidate_shdw_pt
247 };
248
249
250
251
252
253 register_shdw_pg_impl(&vtlb_impl);