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.


10ed64115b43e477a6cd98e68f30f0619d0916e9
[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 = NULL;
174
175     if (!core || !core->vm_info) {
176         return -1;
177     }
178
179     impl = core->vm_info->shdw_impl.current_impl;
180
181     if (impl && impl->local_deinit(core) == -1) {
182         PrintError(core->vm_info, core, "Error deinitializing shadow paging state\n");
183         return -1;
184     }
185
186
187     return 0;
188 }
189
190
191
192 int v3_init_shdw_impl(struct v3_vm_info * vm) {
193     struct v3_shdw_impl_state * impl_state = &(vm->shdw_impl);
194     v3_cfg_tree_t * pg_cfg = v3_cfg_subtree(vm->cfg_data->cfg, "paging");
195     char * pg_mode = v3_cfg_val(pg_cfg, "mode");
196     char * pg_strat = v3_cfg_val(pg_cfg, "strategy");
197     struct v3_shdw_pg_impl * impl = NULL;
198    
199     PrintDebug(vm, VCORE_NONE, "Checking if shadow paging requested.\n");
200     if (pg_mode == NULL) { 
201         V3_Print(vm, VCORE_NONE, "No paging mode specified, assuming shadow with defaults\n");
202         pg_mode = "shadow";
203     } else {
204         if (strcasecmp(pg_mode, "nested") == 0) {
205             // this check is repeated here (compare to vmm_config's determine paging mode) since
206             // shadow paging initialization *precedes* per-core pre-config.
207             extern v3_cpu_arch_t v3_mach_type;
208             if ((v3_mach_type == V3_SVM_REV3_CPU) || 
209                 (v3_mach_type == V3_VMX_EPT_CPU) ||
210                 (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
211                 PrintDebug(vm, VCORE_NONE, "Nested paging specified on machine that supports it - not initializing shadow paging\n");
212                 return 0;
213             } else {
214                 V3_Print(vm, VCORE_NONE, "Nested paging specified but machine does not support it - falling back to shadow paging with defaults\n");
215                 pg_mode = "shadow";
216             }
217         } else if (strcasecmp(pg_mode, "shadow") != 0) { 
218             V3_Print(vm, VCORE_NONE, "Unknown paging mode '%s' specified - falling back to shadow paging with defaults\n",pg_mode);
219             pg_mode = "shadow";
220         }
221     }
222
223     if (pg_strat == NULL) {
224         pg_strat = (char *)default_strategy;
225     }
226         
227     V3_Print(vm, VCORE_NONE,"Initialization of Shadow Paging implementation\n");
228
229     impl = (struct v3_shdw_pg_impl *)v3_htable_search(master_shdw_pg_table, (addr_t)pg_strat);
230
231     if (impl == NULL) {
232         PrintError(vm, VCORE_NONE, "Could not find shadow paging impl (%s)\n", pg_strat);
233         return -1;
234     }
235
236     INIT_LIST_HEAD(&(impl_state->event_callback_list));
237    
238     impl_state->current_impl = impl;
239
240     if (impl->init(vm, pg_cfg) == -1) {
241         PrintError(vm, VCORE_NONE, "Could not initialize Shadow paging implemenation (%s)\n", impl->name);
242         return -1;
243     }
244
245
246
247     return 0;
248 }
249
250 int v3_deinit_shdw_impl(struct v3_vm_info * vm) {
251     struct v3_shdw_pg_impl * impl = vm->shdw_impl.current_impl;
252     struct event_callback *cb,*temp;
253
254     if (impl == NULL) {
255         // Shadow paging not implemented
256         return 0;
257     }
258
259     if (impl->deinit(vm) == -1) {
260         PrintError(vm, VCORE_NONE,"Error deinitializing shadow paging implementation\n");
261         return -1;
262     }
263
264     list_for_each_entry_safe(cb,
265                              temp,
266                              &(vm->shdw_impl.event_callback_list),
267                              node) {
268         list_del(&(cb->node));
269         V3_Free(cb);
270     }
271
272     return 0;
273 }
274
275
276 // Reads the guest CR3 register
277 // creates new shadow page tables
278 // updates the shadow CR3 register to point to the new pts
279 int v3_activate_shadow_pt(struct guest_info * core) {
280     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
281     struct v3_shdw_pg_impl * impl = state->current_impl;
282     
283     if (!have_callbacks(core)) { 
284         return impl->activate_shdw_pt(core);
285     } else {
286         int rc;
287         struct v3_shdw_pg_event event_pre={SHADOW_ACTIVATE,SHADOW_PREIMPL,0,{0,0,0,0,0,0}};
288         struct v3_shdw_pg_event event_post={SHADOW_ACTIVATE,SHADOW_POSTIMPL,0,{0,0,0,0,0,0}};
289         
290         dispatch_event(core,&event_pre);
291
292         rc =impl->activate_shdw_pt(core);
293
294         dispatch_event(core,&event_post);
295         
296         return rc;
297     }
298 }
299
300
301
302 // This must flush any caches
303 // and reset the cr3 value to the correct value
304 int v3_invalidate_shadow_pts(struct guest_info * core) {
305     struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
306     struct v3_shdw_pg_impl * impl = state->current_impl;
307
308     if (!have_callbacks(core)) { 
309         return impl->invalidate_shdw_pt(core);
310     } else {
311         int rc;
312         struct v3_shdw_pg_event event_pre={SHADOW_INVALIDATE,SHADOW_PREIMPL,0,{0,0,0,0,0,0}};
313         struct v3_shdw_pg_event event_post={SHADOW_INVALIDATE,SHADOW_POSTIMPL,0,{0,0,0,0,0,0}};
314         
315         dispatch_event(core,&event_pre);
316
317         rc = impl->invalidate_shdw_pt(core);
318
319         dispatch_event(core,&event_post);
320         
321         return rc;
322     }
323 }
324
325
326 int v3_handle_shadow_pagefault(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) 
327 {
328     int rc;
329    
330
331     if (have_callbacks(core)) { 
332         struct v3_shdw_pg_event event={SHADOW_PAGEFAULT,SHADOW_PREIMPL,fault_addr,error_code};
333         dispatch_event(core,&event);
334     }
335     
336     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) {
337         // If paging is not turned on we need to handle the special cases
338       rc = v3_handle_passthrough_pagefault(core, fault_addr, error_code,NULL,NULL);
339     } else if (v3_get_vm_mem_mode(core) == VIRTUAL_MEM) {
340         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
341         struct v3_shdw_pg_impl * impl = state->current_impl;
342         
343         rc = impl->handle_pagefault(core, fault_addr, error_code);
344     } else {
345         PrintError(core->vm_info, core, "Invalid Memory mode\n");
346         rc = -1;
347     }
348     
349     if (have_callbacks(core)) {
350         struct v3_shdw_pg_event event={SHADOW_PAGEFAULT,SHADOW_POSTIMPL,fault_addr,error_code};
351         dispatch_event(core,&event);
352     }
353     
354     return rc;
355 }
356
357
358 int v3_handle_shadow_invlpg(struct guest_info * core) {
359     uchar_t instr[15];
360     struct x86_instr dec_instr;
361     int ret = 0;
362     addr_t vaddr = 0;
363
364     if (v3_get_vm_mem_mode(core) != VIRTUAL_MEM) {
365         // Paging must be turned on...
366         // should handle with some sort of fault I think
367         PrintError(core->vm_info, core, "ERROR: INVLPG called in non paged mode\n");
368         return -1;
369     }
370
371     if (v3_get_vm_mem_mode(core) == PHYSICAL_MEM) { 
372         ret = v3_read_gpa_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
373     } else { 
374         ret = v3_read_gva_memory(core, get_addr_linear(core, core->rip, &(core->segments.cs)), 15, instr);
375     }
376
377     if (ret == -1) {
378         PrintError(core->vm_info, core, "Could not read instruction into buffer\n");
379         return -1;
380     }
381
382     if (v3_decode(core, (addr_t)instr, &dec_instr) == -1) {
383         PrintError(core->vm_info, core, "Decoding Error\n");
384         return -1;
385     }
386   
387     if ((dec_instr.op_type != V3_OP_INVLPG) || 
388         (dec_instr.num_operands != 1) ||
389         (dec_instr.dst_operand.type != MEM_OPERAND)) {
390         PrintError(core->vm_info, core, "Decoder Error: Not a valid INVLPG instruction...\n");
391         return -1;
392     }
393
394     vaddr = dec_instr.dst_operand.operand;
395
396     core->rip += dec_instr.instr_length;
397
398     {
399         struct v3_shdw_impl_state * state = &(core->vm_info->shdw_impl);
400         struct v3_shdw_pg_impl * impl = state->current_impl;
401         int rc;
402
403         if (have_callbacks(core)) { 
404             struct v3_shdw_pg_event event={SHADOW_INVLPG,SHADOW_PREIMPL,vaddr,{0,0,0,0,0,0}};
405             dispatch_event(core,&event);
406         }
407
408         rc=impl->handle_invlpg(core, vaddr);
409
410         if (have_callbacks(core)) { 
411             struct v3_shdw_pg_event event={SHADOW_INVLPG,SHADOW_POSTIMPL,vaddr,{0,0,0,0,0,0}};
412             dispatch_event(core,&event);
413         }
414
415         return rc;
416     }
417 }
418
419
420
421
422
423
424 int v3_inject_guest_pf(struct guest_info * core, addr_t fault_addr, pf_error_t error_code) {
425     core->ctrl_regs.cr2 = fault_addr;
426
427 #ifdef V3_CONFIG_SHADOW_PAGING_TELEMETRY
428     core->shdw_pg_state.guest_faults++;
429 #endif
430
431     return v3_raise_exception_with_error(core, PF_EXCEPTION, *(uint_t *)&error_code);
432 }
433
434
435 int v3_is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
436     /* basically the reasoning is that there can be multiple reasons for a page fault:
437        If there is a permissions failure for a page present in the guest _BUT_
438        the reason for the fault was that the page is not present in the shadow,
439        _THEN_ we have to map the shadow page in and reexecute, this will generate
440        a permissions fault which is _THEN_ valid to send to the guest
441        _UNLESS_ both the guest and shadow have marked the page as not present
442
443        whew...
444     */
445     if (guest_access != PT_ACCESS_OK) {
446         // Guest Access Error
447
448         if ((shadow_access != PT_ACCESS_NOT_PRESENT) &&
449             (guest_access != PT_ACCESS_NOT_PRESENT)) {
450             // aka (guest permission error)
451             return 1;
452         }
453
454         /*
455           if ((shadow_access == PT_ACCESS_NOT_PRESENT) &&
456           (guest_access == PT_ACCESS_NOT_PRESENT)) {
457           // Page tables completely blank, handle guest first
458           return 1;
459           }
460         */
461
462         if (guest_access == PT_ACCESS_NOT_PRESENT) {
463             // Page tables completely blank, handle guest first
464             return 1;
465         }
466         
467         // Otherwise we'll handle the guest fault later...?
468     }
469
470     return 0;
471 }
472
473
474 int v3_register_shadow_paging_event_callback(struct v3_vm_info *vm,
475                                              int (*callback)(struct guest_info *core, 
476                                                              struct v3_shdw_pg_event *event,
477                                                              void      *priv_data),
478                                              void *priv_data)
479 {
480     struct event_callback *ec = V3_Malloc(sizeof(struct event_callback));
481
482     if (!ec) { 
483         PrintError(vm, VCORE_NONE, "Unable to allocate for a shadow paging event callback\n");
484         return -1;
485     }
486     
487     ec->callback = callback;
488     ec->priv_data = priv_data;
489
490     list_add(&(ec->node),&(vm->shdw_impl.event_callback_list));
491
492     return 0;
493
494 }
495
496 int v3_unregister_shadow_paging_event_callback(struct v3_vm_info *vm,
497                                                int (*callback)(struct guest_info *core, 
498                                                                struct v3_shdw_pg_event *event,
499                                                                void      *priv_data),
500                                                void *priv_data)
501 {
502     struct event_callback *cb,*temp;
503
504     list_for_each_entry_safe(cb,
505                              temp,
506                              &(vm->shdw_impl.event_callback_list),
507                              node) {
508         if ((callback == cb->callback) && (priv_data == cb->priv_data)) { 
509             list_del(&(cb->node));
510             V3_Free(cb);
511             return 0;
512         }
513     }
514     
515     PrintError(vm, VCORE_NONE, "No callback found!\n");
516     
517     return -1;
518 }
519
520