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.


cosmetic changes
[palacios.git] / palacios / src / palacios / vmm_shadow_paging.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
21 #include <palacios/vmm_shadow_paging.h>
22
23
24 #include <palacios/vmm.h>
25 #include <palacios/vm_guest_mem.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmm_ctrl_regs.h>
28
29 #include <palacios/vmm_hashtable.h>
30
31 #include <palacios/vmm_direct_paging.h>
32
33
34
35
36 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
37 #include <palacios/vmm_telemetry.h>
38 #endif
39
40 #ifdef CONFIG_SYMBIOTIC_SWAP
41 #include <palacios/vmm_sym_swap.h>
42 #endif
43
44 #ifndef CONFIG_DEBUG_SHADOW_PAGING
45 #undef PrintDebug
46 #define PrintDebug(fmt, args...)
47 #endif
48
49
50 static const char default_strategy[] = "VTLB";
51
52
53 static struct hashtable * master_shdw_pg_table = NULL;
54
55 static uint_t shdw_pg_hash_fn(addr_t key) {
56     char * name = (char *)key;
57     return v3_hash_buffer((uint8_t *)name, strlen(name));
58 }
59
60 static int shdw_pg_eq_fn(addr_t key1, addr_t key2) {
61     char * name1 = (char *)key1;
62     char * name2 = (char *)key2;
63
64     return (strcmp(name1, name2) == 0);
65 }
66
67
68 int V3_init_shdw_paging() {
69     extern struct v3_shdw_pg_impl * __start__v3_shdw_pg_impls[];
70     extern struct v3_shdw_pg_impl * __stop__v3_shdw_pg_impls[];
71     struct v3_shdw_pg_impl ** tmp_impl = __start__v3_shdw_pg_impls;
72     int i = 0;
73
74     master_shdw_pg_table = v3_create_htable(0, shdw_pg_hash_fn, shdw_pg_eq_fn);
75
76
77     while (tmp_impl != __stop__v3_shdw_pg_impls) {
78         V3_Print("Registering Shadow Paging Impl (%s)\n", (*tmp_impl)->name);
79
80         if (v3_htable_search(master_shdw_pg_table, (addr_t)((*tmp_impl)->name))) {
81             PrintError("Multiple instances of shadow paging impl (%s)\n", (*tmp_impl)->name);
82             return -1;
83         }
84
85         if (v3_htable_insert(master_shdw_pg_table, 
86                              (addr_t)((*tmp_impl)->name),
87                              (addr_t)(*tmp_impl)) == 0) {
88             PrintError("Could not register shadow paging impl (%s)\n", (*tmp_impl)->name);
89             return -1;
90         }
91
92         tmp_impl = &(__start__v3_shdw_pg_impls[++i]);
93     }
94
95     return 0;
96 }
97
98 int V3_deinit_shdw_paging() {
99     v3_free_htable(master_shdw_pg_table, 0, 0);
100     return 0;
101 }
102
103
104
105 /*** 
106  ***  There be dragons
107  ***/
108
109
110 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
111 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
112     int i = 0;
113     for (i = 0; i < vm->num_cores; i++) {
114         struct guest_info * core = &(vm->cores[i]);
115
116         V3_Print("%s Guest Page faults: %d\n", hdr, core->shdw_pg_state.guest_faults);
117     }
118 }
119 #endif
120
121
122
123 int v3_init_shdw_pg_state(struct guest_info * core) {
124     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
125     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
126   
127
128     state->guest_cr3 = 0;
129     state->guest_cr0 = 0;
130     state->guest_efer.value = 0x0LL;
131
132
133     if (impl->local_init(core) == -1) {
134         PrintError("Error in Shadow paging local initialization (%s)\n", impl->name);
135         return -1;
136     }
137
138
139 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
140     v3_add_telemetry_cb(core->vm_info, telemetry_cb, NULL);
141 #endif
142   
143     return 0;
144 }
145
146
147 int v3_deinit_shdw_pg_state(struct guest_info * core) {
148     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
149
150     if (impl->local_deinit(core) == -1) {
151         PrintError("Error deinitializing shadow paging state\n");
152         return -1;
153     }
154
155 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
156     v3_remove_telemetry_cb(core->vm_info, telemetry_cb, NULL);
157 #endif
158
159     return 0;
160 }
161
162
163
164 int v3_init_shdw_impl(struct v3_vm_info * vm) {
165     struct v3_shdw_impl_state * impl_state = &(vm->shdw_impl);
166     v3_cfg_tree_t * pg_cfg = v3_cfg_subtree(vm->cfg_data->cfg, "paging");
167     char * pg_mode = v3_cfg_val(pg_cfg, "mode");
168     char * pg_strat = v3_cfg_val(pg_cfg, "strategy");
169     struct v3_shdw_pg_impl * impl = NULL;
170    
171     PrintDebug("Checking if shadow paging requested.\n");
172     if ((pg_mode != NULL) && (strcasecmp(pg_mode, "nested") == 0)) {
173         PrintDebug("Nested paging specified - not initializing shadow paging.\n");
174         return 0;
175     }
176
177     if (pg_strat == NULL) {
178         pg_strat = (char *)default_strategy;
179     }
180         
181     V3_Print("Initialization of Shadow Paging implementation\n");
182
183     impl = (struct v3_shdw_pg_impl *)v3_htable_search(master_shdw_pg_table, (addr_t)pg_strat);
184
185     if (impl == NULL) {
186         PrintError("Could not find shadow paging impl (%s)\n", pg_strat);
187         return -1;
188     }
189    
190     impl_state->current_impl = impl;
191
192     if (impl->init(vm, pg_cfg) == -1) {
193         PrintError("Could not initialize Shadow paging implemenation (%s)\n", impl->name);
194         return -1;
195     }
196
197     return 0;
198 }
199
200 int v3_deinit_shdw_impl(struct v3_vm_info * vm) {
201     struct v3_shdw_pg_impl * impl = vm->shdw_impl.current_impl;
202
203     if (impl->deinit(vm) == -1) {
204         PrintError("Error deinitializing shadow paging implementation\n");
205         return -1;
206     }
207
208     return 0;
209 }
210
211
212 // Reads the guest CR3 register
213 // creates new shadow page tables
214 // updates the shadow CR3 register to point to the new pts
215 int v3_activate_shadow_pt(struct guest_info * core) {
216     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
217     struct v3_shdw_pg_impl * impl = state->current_impl;
218     return impl->activate_shdw_pt(core);
219 }
220
221
222
223 // This must flush any caches
224 // and reset the cr3 value to the correct value
225 int v3_invalidate_shadow_pts(struct guest_info * core) {
226     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
227     struct v3_shdw_pg_impl * impl = state->current_impl;
228     return impl->invalidate_shdw_pt(core);
229 }
230
231
232 int v3_handle_shadow_pagefault(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
233   
234     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) {
235         // If paging is not turned on we need to handle the special cases
236         return v3_handle_passthrough_pagefault(core, fault_addr, error_code);
237     } else if (v3_get_vm_mem_mode(core) == VIRTUAL_MEM) {
238         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
239         struct v3_shdw_pg_impl * impl = state->current_impl;
240
241         return impl->handle_pagefault(core, fault_addr, error_code);
242     } else {
243         PrintError("Invalid Memory mode\n");
244         return -1;
245     }
246 }
247
248
249 int v3_handle_shadow_invlpg(struct guest_info * core) {
250     uchar_t instr[15];
251     struct x86_instr dec_instr;
252     int ret = 0;
253     addr_t vaddr = 0;
254
255     if (v3_get_vm_mem_mode(core) != VIRTUAL_MEM) {
256         // Paging must be turned on...
257         // should handle with some sort of fault I think
258         PrintError("ERROR: INVLPG called in non paged mode\n");
259         return -1;
260     }
261
262     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) { 
263         ret = v3_read_gpa_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
264     } else { 
265         ret = v3_read_gva_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
266     }
267
268     if (ret == -1) {
269         PrintError("Could not read instruction into buffer\n");
270         return -1;
271     }
272
273     if (v3_decode(core, (addr_t)instr, &dec_instr) == -1) {
274         PrintError("Decoding Error\n");
275         return -1;
276     }
277   
278     if ((dec_instr.op_type != V3_OP_INVLPG) || 
279         (dec_instr.num_operands != 1) ||
280         (dec_instr.dst_operand.type != MEM_OPERAND)) {
281         PrintError("Decoder Error: Not a valid INVLPG instruction...\n");
282         return -1;
283     }
284
285     vaddr = dec_instr.dst_operand.operand;
286
287     core->rip += dec_instr.instr_length;
288
289     {
290         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
291         struct v3_shdw_pg_impl * impl = state->current_impl;
292
293         return impl->handle_invlpg(core, vaddr);
294     }
295 }
296
297
298
299
300
301
302 int v3_inject_guest_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
303     core->ctrl_regs.cr2 = fault_addr;
304
305 #ifdef CONFIG_SHADOW_PAGING_TELEMETRY
306     core->shdw_pg_state.guest_faults++;
307 #endif
308
309     return v3_raise_exception_with_error(core, PF_EXCEPTION, *(uint_t *)&error_code);
310 }
311
312
313 int v3_is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
314     /* basically the reasoning is that there can be multiple reasons for a page fault:
315        If there is a permissions failure for a page present in the guest _BUT_
316        the reason for the fault was that the page is not present in the shadow,
317        _THEN_ we have to map the shadow page in and reexecute, this will generate
318        a permissions fault which is _THEN_ valid to send to the guest
319        _UNLESS_ both the guest and shadow have marked the page as not present
320
321        whew...
322     */
323     if (guest_access != PT_ACCESS_OK) {
324         // Guest Access Error
325
326         if ((shadow_access != PT_ACCESS_NOT_PRESENT) &&
327             (guest_access != PT_ACCESS_NOT_PRESENT)) {
328             // aka (guest permission error)
329             return 1;
330         }
331
332         /*
333           if ((shadow_access == PT_ACCESS_NOT_PRESENT) &&
334           (guest_access == PT_ACCESS_NOT_PRESENT)) {
335           // Page tables completely blank, handle guest first
336           return 1;
337           }
338         */
339
340         if (guest_access == PT_ACCESS_NOT_PRESENT) {
341             // Page tables completely blank, handle guest first
342             return 1;
343         }
344         
345         // Otherwise we'll handle the guest fault later...?
346     }
347
348     return 0;
349 }
350
351