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.


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