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.


Fallback to shadow paging if nested not supported or no paging mode specified
[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 V3_CONFIG_SHADOW_PAGING_TELEMETRY
37 #include <palacios/vmm_telemetry.h>
38 #endif
39
40 #ifdef V3_CONFIG_SYMBIOTIC_SWAP
41 #include <palacios/vmm_sym_swap.h>
42 #endif
43
44 #ifndef V3_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
56 struct event_callback {
57     int (*callback)(struct guest_info *core, struct v3_shdw_pg_event *event, void *priv_data);
58     void *priv_data;
59
60     struct list_head node;
61 };
62
63 static uint_t shdw_pg_hash_fn(addr_t key) {
64     char * name = (char *)key;
65     return v3_hash_buffer((uint8_t *)name, strlen(name));
66 }
67
68 static int shdw_pg_eq_fn(addr_t key1, addr_t key2) {
69     char * name1 = (char *)key1;
70     char * name2 = (char *)key2;
71
72     return (strcmp(name1, name2) == 0);
73 }
74
75 static int have_callbacks(struct guest_info *core)
76 {
77     return !list_empty(&(core->vm_info->shdw_impl.event_callback_list));
78 }
79
80 static void dispatch_event(struct guest_info *core, struct v3_shdw_pg_event *event)
81 {
82     struct event_callback *cb,*temp;
83     
84     list_for_each_entry_safe(cb,
85                              temp,
86                              &(core->vm_info->shdw_impl.event_callback_list),
87                              node) {
88         cb->callback(core,event,cb->priv_data);
89     }
90 }
91
92
93 int V3_init_shdw_paging() {
94     extern struct v3_shdw_pg_impl * __start__v3_shdw_pg_impls[];
95     extern struct v3_shdw_pg_impl * __stop__v3_shdw_pg_impls[];
96     struct v3_shdw_pg_impl ** tmp_impl = __start__v3_shdw_pg_impls;
97     int i = 0;
98
99     master_shdw_pg_table = v3_create_htable(0, shdw_pg_hash_fn, shdw_pg_eq_fn);
100
101
102     while (tmp_impl != __stop__v3_shdw_pg_impls) {
103         V3_Print(VM_NONE, VCORE_NONE, "Registering Shadow Paging Impl (%s)\n", (*tmp_impl)->name);
104
105         if (v3_htable_search(master_shdw_pg_table, (addr_t)((*tmp_impl)->name))) {
106             PrintError(VM_NONE, VCORE_NONE, "Multiple instances of shadow paging impl (%s)\n", (*tmp_impl)->name);
107             return -1;
108         }
109
110         if (v3_htable_insert(master_shdw_pg_table, 
111                              (addr_t)((*tmp_impl)->name),
112                              (addr_t)(*tmp_impl)) == 0) {
113             PrintError(VM_NONE, VCORE_NONE, "Could not register shadow paging impl (%s)\n", (*tmp_impl)->name);
114             return -1;
115         }
116
117         tmp_impl = &(__start__v3_shdw_pg_impls[++i]);
118     }
119
120     return 0;
121 }
122
123 int V3_deinit_shdw_paging() {
124     v3_free_htable(master_shdw_pg_table, 0, 0);
125     return 0;
126 }
127
128
129
130 /*** 
131  ***  There be dragons
132  ***/
133
134
135 #ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
136 static void telemetry_cb(struct v3_vm_info * vm, void * private_data, char * hdr) {
137     int i = 0;
138     for (i = 0; i < vm->num_cores; i++) {
139         struct guest_info * core = &(vm->cores[i]);
140
141         V3_Print(vm, core, "%s Guest Page faults: %d\n", hdr, core->shdw_pg_state.guest_faults);
142     }
143 }
144 #endif
145
146
147
148 int v3_init_shdw_pg_state(struct guest_info * core) {
149     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
150     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
151   
152
153     state->guest_cr3 = 0;
154     state->guest_cr0 = 0;
155     state->guest_efer.value = 0x0LL;
156
157     if (impl->local_init(core) == -1) {
158         PrintError(core->vm_info, core, "Error in Shadow paging local initialization (%s)\n", impl->name);
159         return -1;
160     }
161
162
163 #ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
164     v3_add_telemetry_cb(core->vm_info, telemetry_cb, NULL);
165 #endif
166   
167
168     return 0;
169 }
170
171
172 int v3_deinit_shdw_pg_state(struct guest_info * core) {
173     struct v3_shdw_pg_impl * impl = core->vm_info->shdw_impl.current_impl;
174
175     if (impl->local_deinit(core) == -1) {
176         PrintError(core->vm_info, core, "Error deinitializing shadow paging state\n");
177         return -1;
178     }
179
180
181     return 0;
182 }
183
184
185
186 int v3_init_shdw_impl(struct v3_vm_info * vm) {
187     struct v3_shdw_impl_state * impl_state = &(vm->shdw_impl);
188     v3_cfg_tree_t * pg_cfg = v3_cfg_subtree(vm->cfg_data->cfg, "paging");
189     char * pg_mode = v3_cfg_val(pg_cfg, "mode");
190     char * pg_strat = v3_cfg_val(pg_cfg, "strategy");
191     struct v3_shdw_pg_impl * impl = NULL;
192    
193     PrintDebug(vm, VCORE_NONE, "Checking if shadow paging requested.\n");
194     if (pg_mode == NULL) { 
195         V3_Print(vm, VCORE_NONE, "No paging mode specified, assuming shadow with defaults\n");
196         pg_mode = "shadow";
197     } else {
198         if (strcasecmp(pg_mode, "nested") == 0) {
199             // this check is repeated here (compare to vmm_config's determine paging mode) since
200             // shadow paging initialization *precedes* per-core pre-config.
201             extern v3_cpu_arch_t v3_mach_type;
202             if ((v3_mach_type == V3_SVM_REV3_CPU) || 
203                 (v3_mach_type == V3_VMX_EPT_CPU) ||
204                 (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
205                 PrintDebug(vm, VCORE_NONE, "Nested paging specified on machine that supports it - not initializing shadow paging\n");
206                 return 0;
207             } else {
208                 V3_Print(vm, VCORE_NONE, "Nested paging specified but machine does not support it - falling back to shadow paging with defaults\n");
209                 pg_mode = "shadow";
210             }
211         } else if (strcasecmp(pg_mode, "shadow") != 0) { 
212             V3_Print(vm, VCORE_NONE, "Unknown paging mode '%s' specified - falling back to shadow paging with defaults\n",pg_mode);
213             pg_mode = "shadow";
214         }
215     }
216
217     if (pg_strat == NULL) {
218         pg_strat = (char *)default_strategy;
219     }
220         
221     V3_Print(vm, VCORE_NONE,"Initialization of Shadow Paging implementation\n");
222
223     impl = (struct v3_shdw_pg_impl *)v3_htable_search(master_shdw_pg_table, (addr_t)pg_strat);
224
225     if (impl == NULL) {
226         PrintError(vm, VCORE_NONE, "Could not find shadow paging impl (%s)\n", pg_strat);
227         return -1;
228     }
229
230     INIT_LIST_HEAD(&(impl_state->event_callback_list));
231    
232     impl_state->current_impl = impl;
233
234     if (impl->init(vm, pg_cfg) == -1) {
235         PrintError(vm, VCORE_NONE, "Could not initialize Shadow paging implemenation (%s)\n", impl->name);
236         return -1;
237     }
238
239
240
241     return 0;
242 }
243
244 int v3_deinit_shdw_impl(struct v3_vm_info * vm) {
245     struct v3_shdw_pg_impl * impl = vm->shdw_impl.current_impl;
246     struct event_callback *cb,*temp;
247
248     if (impl == NULL) {
249         // Shadow paging not implemented
250         return 0;
251     }
252
253     if (impl->deinit(vm) == -1) {
254         PrintError(vm, VCORE_NONE,"Error deinitializing shadow paging implementation\n");
255         return -1;
256     }
257
258     list_for_each_entry_safe(cb,
259                              temp,
260                              &(vm->shdw_impl.event_callback_list),
261                              node) {
262         list_del(&(cb->node));
263         V3_Free(cb);
264     }
265
266     return 0;
267 }
268
269
270 // Reads the guest CR3 register
271 // creates new shadow page tables
272 // updates the shadow CR3 register to point to the new pts
273 int v3_activate_shadow_pt(struct guest_info * core) {
274     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
275     struct v3_shdw_pg_impl * impl = state->current_impl;
276     
277     if (!have_callbacks(core)) { 
278         return impl->activate_shdw_pt(core);
279     } else {
280         int rc;
281         struct v3_shdw_pg_event event_pre={SHADOW_ACTIVATE,SHADOW_PREIMPL,0,{0,0,0,0,0,0}};
282         struct v3_shdw_pg_event event_post={SHADOW_ACTIVATE,SHADOW_POSTIMPL,0,{0,0,0,0,0,0}};
283         
284         dispatch_event(core,&event_pre);
285
286         rc =impl->activate_shdw_pt(core);
287
288         dispatch_event(core,&event_post);
289         
290         return rc;
291     }
292 }
293
294
295
296 // This must flush any caches
297 // and reset the cr3 value to the correct value
298 int v3_invalidate_shadow_pts(struct guest_info * core) {
299     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
300     struct v3_shdw_pg_impl * impl = state->current_impl;
301
302     if (!have_callbacks(core)) { 
303         return impl->invalidate_shdw_pt(core);
304     } else {
305         int rc;
306         struct v3_shdw_pg_event event_pre={SHADOW_INVALIDATE,SHADOW_PREIMPL,0,{0,0,0,0,0,0}};
307         struct v3_shdw_pg_event event_post={SHADOW_INVALIDATE,SHADOW_POSTIMPL,0,{0,0,0,0,0,0}};
308         
309         dispatch_event(core,&event_pre);
310
311         rc = impl->invalidate_shdw_pt(core);
312
313         dispatch_event(core,&event_post);
314         
315         return rc;
316     }
317 }
318
319
320 int v3_handle_shadow_pagefault(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) 
321 {
322     int rc;
323    
324
325     if (have_callbacks(core)) { 
326         struct v3_shdw_pg_event event={SHADOW_PAGEFAULT,SHADOW_PREIMPL,fault_addr,error_code};
327         dispatch_event(core,&event);
328     }
329     
330     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) {
331         // If paging is not turned on we need to handle the special cases
332         rc = v3_handle_passthrough_pagefault(core, fault_addr, error_code);
333     } else if (v3_get_vm_mem_mode(core) == VIRTUAL_MEM) {
334         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
335         struct v3_shdw_pg_impl * impl = state->current_impl;
336         
337         rc = impl->handle_pagefault(core, fault_addr, error_code);
338     } else {
339         PrintError(core->vm_info, core, "Invalid Memory mode\n");
340         rc = -1;
341     }
342     
343     if (have_callbacks(core)) {
344         struct v3_shdw_pg_event event={SHADOW_PAGEFAULT,SHADOW_POSTIMPL,fault_addr,error_code};
345         dispatch_event(core,&event);
346     }
347     
348     return rc;
349 }
350
351
352 int v3_handle_shadow_invlpg(struct guest_info * core) {
353     uchar_t instr[15];
354     struct x86_instr dec_instr;
355     int ret = 0;
356     addr_t vaddr = 0;
357
358     if (v3_get_vm_mem_mode(core) != VIRTUAL_MEM) {
359         // Paging must be turned on...
360         // should handle with some sort of fault I think
361         PrintError(core->vm_info, core, "ERROR: INVLPG called in non paged mode\n");
362         return -1;
363     }
364
365     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) { 
366         ret = v3_read_gpa_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
367     } else { 
368         ret = v3_read_gva_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
369     }
370
371     if (ret == -1) {
372         PrintError(core->vm_info, core, "Could not read instruction into buffer\n");
373         return -1;
374     }
375
376     if (v3_decode(core, (addr_t)instr, &dec_instr) == -1) {
377         PrintError(core->vm_info, core, "Decoding Error\n");
378         return -1;
379     }
380   
381     if ((dec_instr.op_type != V3_OP_INVLPG) || 
382         (dec_instr.num_operands != 1) ||
383         (dec_instr.dst_operand.type != MEM_OPERAND)) {
384         PrintError(core->vm_info, core, "Decoder Error: Not a valid INVLPG instruction...\n");
385         return -1;
386     }
387
388     vaddr = dec_instr.dst_operand.operand;
389
390     core->rip += dec_instr.instr_length;
391
392     {
393         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
394         struct v3_shdw_pg_impl * impl = state->current_impl;
395         int rc;
396
397         if (have_callbacks(core)) { 
398             struct v3_shdw_pg_event event={SHADOW_INVLPG,SHADOW_PREIMPL,vaddr,{0,0,0,0,0,0}};
399             dispatch_event(core,&event);
400         }
401
402         rc=impl->handle_invlpg(core, vaddr);
403
404         if (have_callbacks(core)) { 
405             struct v3_shdw_pg_event event={SHADOW_INVLPG,SHADOW_POSTIMPL,vaddr,{0,0,0,0,0,0}};
406             dispatch_event(core,&event);
407         }
408
409         return rc;
410     }
411 }
412
413
414
415
416
417
418 int v3_inject_guest_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
419     core->ctrl_regs.cr2 = fault_addr;
420
421 #ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
422     core->shdw_pg_state.guest_faults++;
423 #endif
424
425     return v3_raise_exception_with_error(core, PF_EXCEPTION, *(uint_t *)&error_code);
426 }
427
428
429 int v3_is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
430     /* basically the reasoning is that there can be multiple reasons for a page fault:
431        If there is a permissions failure for a page present in the guest _BUT_
432        the reason for the fault was that the page is not present in the shadow,
433        _THEN_ we have to map the shadow page in and reexecute, this will generate
434        a permissions fault which is _THEN_ valid to send to the guest
435        _UNLESS_ both the guest and shadow have marked the page as not present
436
437        whew...
438     */
439     if (guest_access != PT_ACCESS_OK) {
440         // Guest Access Error
441
442         if ((shadow_access != PT_ACCESS_NOT_PRESENT) &&
443             (guest_access != PT_ACCESS_NOT_PRESENT)) {
444             // aka (guest permission error)
445             return 1;
446         }
447
448         /*
449           if ((shadow_access == PT_ACCESS_NOT_PRESENT) &&
450           (guest_access == PT_ACCESS_NOT_PRESENT)) {
451           // Page tables completely blank, handle guest first
452           return 1;
453           }
454         */
455
456         if (guest_access == PT_ACCESS_NOT_PRESENT) {
457             // Page tables completely blank, handle guest first
458             return 1;
459         }
460         
461         // Otherwise we'll handle the guest fault later...?
462     }
463
464     return 0;
465 }
466
467
468 int v3_register_shadow_paging_event_callback(struct v3_vm_info *vm,
469                                              int (*callback)(struct guest_info *core, 
470                                                              struct v3_shdw_pg_event *event,
471                                                              void      *priv_data),
472                                              void *priv_data)
473 {
474     struct event_callback *ec = V3_Malloc(sizeof(struct event_callback));
475
476     if (!ec) { 
477         PrintError(vm, VCORE_NONE, "Unable to allocate for a shadow paging event callback\n");
478         return -1;
479     }
480     
481     ec->callback = callback;
482     ec->priv_data = priv_data;
483
484     list_add(&(ec->node),&(vm->shdw_impl.event_callback_list));
485
486     return 0;
487
488 }
489
490 int v3_unregister_shadow_paging_event_callback(struct v3_vm_info *vm,
491                                                int (*callback)(struct guest_info *core, 
492                                                                struct v3_shdw_pg_event *event,
493                                                                void      *priv_data),
494                                                void *priv_data)
495 {
496     struct event_callback *cb,*temp;
497
498     list_for_each_entry_safe(cb,
499                              temp,
500                              &(vm->shdw_impl.event_callback_list),
501                              node) {
502         if ((callback == cb->callback) && (priv_data == cb->priv_data)) { 
503             list_del(&(cb->node));
504             V3_Free(cb);
505             return 0;
506         }
507     }
508     
509     PrintError(vm, VCORE_NONE, "No callback found!\n");
510     
511     return -1;
512 }
513
514