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.


small fixes
[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 #ifndef DEBUG_SHADOW_PAGING
32 #undef PrintDebug
33 #define PrintDebug(fmt, args...)
34 #endif
35
36
37 /*** 
38  ***  There be dragons
39  ***/
40
41
42 struct guest_table {
43   addr_t cr3;
44   struct list_head link;
45 };
46
47
48 struct backptr {
49   addr_t ptr;
50   struct list_head link;
51 };
52
53
54 struct shadow_page_data {
55   addr_t ptr;
56   addr_t guest_addr; 
57
58   struct list_head backptrs;
59   struct list_head guest_tables;
60 };
61
62
63
64
65 DEFINE_HASHTABLE_INSERT(add_cr3_to_cache, addr_t, struct hashtable *);
66 DEFINE_HASHTABLE_SEARCH(find_cr3_in_cache, addr_t, struct hashtable *);
67 DEFINE_HASHTABLE_REMOVE(del_cr3_from_cache, addr_t, struct hashtable *, 0);
68
69
70 DEFINE_HASHTABLE_INSERT(add_pte_map, addr_t, addr_t);
71 DEFINE_HASHTABLE_SEARCH(find_pte_map, addr_t, addr_t);
72 DEFINE_HASHTABLE_REMOVE(del_pte_map, addr_t, addr_t, 0);
73
74
75
76 static uint_t pte_hash_fn(addr_t key) {
77   return hash_long(key, 32);
78 }
79
80 static int pte_equals(addr_t key1, addr_t key2) {
81   return (key1 == key2);
82 }
83
84 static uint_t cr3_hash_fn(addr_t key) {
85   return hash_long(key, 32);
86 }
87
88 static int cr3_equals(addr_t key1, addr_t key2) {
89   return (key1 == key2);
90 }
91
92
93
94 static int activate_shadow_pt_32(struct guest_info * info);
95 static int activate_shadow_pt_32pae(struct guest_info * info);
96 static int activate_shadow_pt_64(struct guest_info * info);
97
98
99 static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code);
100 static int handle_shadow_pagefault_32pae(struct guest_info * info, addr_t fault_addr, pf_error_t error_code);
101 static int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code);
102
103
104 static int cache_page_tables_32(struct guest_info * info, addr_t pde);
105 static int cache_page_tables_64(struct guest_info * info, addr_t pde);
106
107 int v3_init_shadow_page_state(struct guest_info * info) {
108   struct shadow_page_state * state = &(info->shdw_pg_state);
109   
110   state->guest_cr3 = 0;
111   state->guest_cr0 = 0;
112
113   state->cr3_cache = create_hashtable(0, &cr3_hash_fn, &cr3_equals);
114
115   state->cached_cr3 = 0;
116   state->cached_ptes = NULL;
117
118   return 0;
119 }
120
121
122
123
124
125 int v3_cache_page_tables(struct guest_info * info, addr_t cr3) {
126   switch(v3_get_cpu_mode(info)) {
127   case PROTECTED:
128     return cache_page_tables_32(info, CR3_TO_PDE32_PA(cr3));
129   default:
130     return -1;
131   }
132 }
133
134 static int cache_page_tables_32(struct guest_info * info, addr_t pde) {
135   struct shadow_page_state * state = &(info->shdw_pg_state);
136   addr_t pde_host_addr;
137   pde32_t * tmp_pde;
138   struct hashtable * pte_cache = NULL;
139   int i = 0;
140
141   if (pde == state->cached_cr3) {
142     return 1;
143   }
144
145   if (state->cached_ptes != NULL) {
146     hashtable_destroy(state->cached_ptes, 0, 0);
147     state->cached_ptes = NULL;
148   }
149
150   state->cached_cr3 = pde;
151
152   pte_cache = create_hashtable(0, &pte_hash_fn, &pte_equals);
153   state->cached_ptes = pte_cache;
154
155   if (guest_pa_to_host_va(info, pde, &pde_host_addr) == -1) {
156     PrintError("Could not lookup host address of guest PDE\n");
157     return -1;
158   }
159
160   tmp_pde = (pde32_t *)pde_host_addr;
161
162   add_pte_map(pte_cache, pde, pde_host_addr);
163
164
165   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
166     if ((tmp_pde[i].present) && (tmp_pde[i].large_page == 0)) {
167       addr_t pte_host_addr;
168
169       if (guest_pa_to_host_va(info, (addr_t)(BASE_TO_PAGE_ADDR(tmp_pde[i].pt_base_addr)), &pte_host_addr) == -1) {
170         PrintError("Could not lookup host address of guest PDE\n");
171         return -1;
172       }
173
174       add_pte_map(pte_cache, (addr_t)(BASE_TO_PAGE_ADDR(tmp_pde[i].pt_base_addr)), pte_host_addr); 
175     }
176   }
177
178   return 0;
179
180 }
181
182
183 static int cache_page_tables_64(struct guest_info * info, addr_t pde) {
184   return -1;
185 }
186
187
188 int v3_replace_shdw_page32(struct guest_info * info, addr_t location, pte32_t * new_page, pte32_t * old_page) {
189   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
190   pde32_t * shadow_pde =  (pde32_t *)&(shadow_pd[PDE32_INDEX(location)]);
191
192   if (shadow_pde->large_page == 0) {
193     pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr);
194     pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(location)]);
195
196     //if (shadow_pte->present == 1) {
197     *(uint_t *)old_page = *(uint_t *)shadow_pte;
198     //}
199
200     *(uint_t *)shadow_pte = *(uint_t *)new_page;
201
202   } else {
203     // currently unhandled
204     PrintError("Replacing large shadow pages not implemented\n");
205     return -1;
206   }
207   
208   return 0;
209 }
210
211
212
213
214
215 // We assume that shdw_pg_state.guest_cr3 is pointing to the page tables we want to activate
216 // We also assume that the CPU mode has not changed during this page table transition
217 static int activate_shadow_pt_32(struct guest_info * info) {
218   struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
219   struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
220   int cached = 0;
221   
222   // Check if shadow page tables are in the cache
223   cached = cache_page_tables_32(info, CR3_TO_PDE32_PA(*(addr_t *)guest_cr3));
224   
225   if (cached == -1) {
226     PrintError("CR3 Cache failed\n");
227     return -1;
228   } else if (cached == 0) {
229     addr_t shadow_pt;
230     
231     PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
232     delete_page_tables_32(CR3_TO_PDE32_VA(*(uint_t*)shadow_cr3));
233     
234     shadow_pt = v3_create_new_shadow_pt();
235     
236     shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PAGE_BASE_ADDR(shadow_pt));
237     PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
238   } else {
239     PrintDebug("Reusing cached shadow Page table\n");
240   }
241   
242   shadow_cr3->pwt = guest_cr3->pwt;
243   shadow_cr3->pcd = guest_cr3->pcd;
244   
245   return 0;
246 }
247
248 static int activate_shadow_pt_32pae(struct guest_info * info) {
249   PrintError("Activating 32 bit PAE page tables not implemented\n");
250   return -1;
251 }
252
253 static int activate_shadow_pt_64_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) {
254   PrintDebug("CB: Page: %p->%p (host_ptr=%p), Type: %s\n", (void *)vaddr, (void *)page_pa, (void *)page_ptr, v3_page_type_to_str(type));
255   return 0;
256 }
257
258
259 static int activate_shadow_pt_64(struct guest_info * info) {
260   //  struct cr3_64 * shadow_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
261   struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
262   int cached = 0;
263   
264   v3_walk_guest_pt_64(info, info->shdw_pg_state.guest_cr3, activate_shadow_pt_64_cb, NULL);
265
266   
267
268   return -1;
269
270
271   // Check if shadow page tables are in the cache
272   cached = cache_page_tables_64(info, CR3_TO_PDE32_PA(*(addr_t *)guest_cr3));
273               /*  
274   if (cached == -1) {
275     PrintError("CR3 Cache failed\n");
276     return -1;
277   } else if (cached == 0) {
278     addr_t shadow_pt;
279     
280     PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
281     delete_page_tables_32(CR3_TO_PDE32_VA(*(uint_t*)shadow_cr3));
282     
283     shadow_pt = v3_create_new_shadow_pt();
284     
285     shadow_cr3->pml4t_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PAGE_BASE_ADDR(shadow_pt));
286     PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pml4t_base_addr );
287   } else {
288     PrintDebug("Reusing cached shadow Page table\n");
289   }
290   
291   shadow_cr3->pwt = guest_cr3->pwt;
292   shadow_cr3->pcd = guest_cr3->pcd;
293   
294   return 0;
295                       */
296 }
297
298
299 // Reads the guest CR3 register
300 // creates new shadow page tables
301 // updates the shadow CR3 register to point to the new pts
302 int v3_activate_shadow_pt(struct guest_info * info) {
303   switch (info->cpu_mode) {
304
305   case PROTECTED:
306     return activate_shadow_pt_32(info);
307   case PROTECTED_PAE:
308     return activate_shadow_pt_32pae(info);
309   case LONG:
310   case LONG_32_COMPAT:
311   case LONG_16_COMPAT:
312     return activate_shadow_pt_64(info);
313   default:
314     PrintError("Invalid CPU mode: %d\n", info->cpu_mode);
315     return -1;
316   }
317
318   return 0;
319 }
320
321
322 int v3_activate_passthrough_pt(struct guest_info * info) {
323   // For now... But we need to change this....
324   // As soon as shadow paging becomes active the passthrough tables are hosed
325   // So this will cause chaos if it is called at that time
326
327   info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
328   //PrintError("Activate Passthrough Page tables not implemented\n");
329   return 0;
330 }
331
332
333
334 int v3_handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
335   
336   if (info->mem_mode == PHYSICAL_MEM) {
337     // If paging is not turned on we need to handle the special cases
338
339 #ifdef DEBUG_SHADOW_PAGING
340     PrintHostPageTree(info->cpu_mode, fault_addr, info->ctrl_regs.cr3);
341     PrintGuestPageTree(info, fault_addr, info->shdw_pg_state.guest_cr3);
342 #endif
343
344     return handle_special_page_fault(info, fault_addr, fault_addr, error_code);
345   } else if (info->mem_mode == VIRTUAL_MEM) {
346
347     switch (info->cpu_mode) {
348     case PROTECTED:
349       return handle_shadow_pagefault_32(info, fault_addr, error_code);
350       break;
351     case PROTECTED_PAE:
352       return handle_shadow_pagefault_32pae(info, fault_addr, error_code);
353     case LONG:
354       return handle_shadow_pagefault_64(info, fault_addr, error_code);
355       break;
356     default:
357       PrintError("Unhandled CPU Mode\n");
358       return -1;
359     }
360   } else {
361     PrintError("Invalid Memory mode\n");
362     return -1;
363   }
364 }
365
366 addr_t v3_create_new_shadow_pt() {
367   void * host_pde = 0;
368
369   host_pde = V3_VAddr(V3_AllocPages(1));
370   memset(host_pde, 0, PAGE_SIZE);
371
372   return (addr_t)host_pde;
373 }
374
375
376 static void inject_guest_pf(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
377   info->ctrl_regs.cr2 = fault_addr;
378   v3_raise_exception_with_error(info, PF_EXCEPTION, *(uint_t *)&error_code);
379 }
380
381
382 static int is_guest_pf(pt_access_status_t guest_access, pt_access_status_t shadow_access) {
383   /* basically the reasoning is that there can be multiple reasons for a page fault:
384      If there is a permissions failure for a page present in the guest _BUT_ 
385      the reason for the fault was that the page is not present in the shadow, 
386      _THEN_ we have to map the shadow page in and reexecute, this will generate 
387      a permissions fault which is _THEN_ valid to send to the guest
388      _UNLESS_ both the guest and shadow have marked the page as not present
389
390      whew...
391   */
392   if (guest_access != PT_ACCESS_OK) {
393     // Guest Access Error
394     
395     if ((shadow_access != PT_ACCESS_NOT_PRESENT) &&
396         (guest_access != PT_ACCESS_NOT_PRESENT)) {
397       // aka (guest permission error)
398       return 1;
399     }
400
401     if ((shadow_access == PT_ACCESS_NOT_PRESENT) &&
402         (guest_access == PT_ACCESS_NOT_PRESENT)) {      
403       // Page tables completely blank, handle guest first
404       return 1;
405     }
406
407     // Otherwise we'll handle the guest fault later...?
408   }
409
410   return 0;
411 }
412
413
414
415
416 /* 
417  * *
418  * * 
419  * * 64 bit Page table fault handlers
420  * *
421  * *
422  */
423
424 static int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
425   pt_access_status_t guest_access;
426   pt_access_status_t shadow_access;
427   int ret; 
428   PrintDebug("64 bit shadow page fault\n");
429
430   ret = v3_check_guest_pt_32(info, info->shdw_pg_state.guest_cr3, fault_addr, error_code, &guest_access);
431
432   PrintDebug("Guest Access Check: %d (access=%d)\n", ret, guest_access);
433
434   ret = v3_check_host_pt_32(info->ctrl_regs.cr3, fault_addr, error_code, &shadow_access);
435
436   PrintDebug("Shadow Access Check: %d (access=%d)\n", ret, shadow_access);
437   
438
439   PrintError("64 bit shadow paging not implemented\n");
440   return -1;
441 }
442
443
444 /* 
445  * *
446  * * 
447  * * 32 bit PAE  Page table fault handlers
448  * *
449  * *
450  */
451
452 static int handle_shadow_pagefault_32pae(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
453   PrintError("32 bit PAE shadow paging not implemented\n");
454   return -1;
455 }
456
457
458
459
460
461
462
463 /* 
464  * *
465  * * 
466  * * 32 bit Page table fault handlers
467  * *
468  * *
469  */
470 static int handle_large_pagefault_32(struct guest_info * info, 
471                                     addr_t fault_addr, pf_error_t error_code, 
472                                      pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde);
473
474 static int handle_shadow_pte32_fault(struct guest_info * info, 
475                                      addr_t fault_addr, 
476                                      pf_error_t error_code,
477                                      pte32_t * shadow_pt, 
478                                      pte32_t * guest_pt);
479
480
481 static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
482   pde32_t * guest_pd = NULL;
483   pde32_t * shadow_pd = CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
484   addr_t guest_cr3 = CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3);
485   pt_access_status_t guest_pde_access;
486   pt_access_status_t shadow_pde_access;
487   pde32_t * guest_pde = NULL;
488   pde32_t * shadow_pde = (pde32_t *)&(shadow_pd[PDE32_INDEX(fault_addr)]);
489
490   PrintDebug("Shadow page fault handler: %p\n", (void*) fault_addr );
491
492   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
493     PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
494     return -1;
495   } 
496
497   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(fault_addr)]);
498
499
500   // Check the guest page permissions
501   guest_pde_access = v3_can_access_pde32(guest_pd, fault_addr, error_code);
502
503   // Check the shadow page permissions
504   shadow_pde_access = v3_can_access_pde32(shadow_pd, fault_addr, error_code);
505   
506   /* Was the page fault caused by the Guest's page tables? */
507   if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
508     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
509                *(uint_t *)&guest_pde_access, *(uint_t *)&error_code);
510     inject_guest_pf(info, fault_addr, error_code);
511     return 0;
512   }
513
514   
515   if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) 
516     {
517       pte32_t * shadow_pt =  (pte32_t *)v3_create_new_shadow_pt();
518
519       shadow_pde->present = 1;
520       shadow_pde->user_page = guest_pde->user_page;
521       //    shadow_pde->large_page = guest_pde->large_page;
522       shadow_pde->large_page = 0;
523       
524
525       // VMM Specific options
526       shadow_pde->write_through = 0;
527       shadow_pde->cache_disable = 0;
528       shadow_pde->global_page = 0;
529       //
530       
531       guest_pde->accessed = 1;
532       
533       shadow_pde->pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(shadow_pt));
534       
535       if (guest_pde->large_page == 0) {
536         shadow_pde->writable = guest_pde->writable;
537       } else {
538         // ??  What if guest pde is dirty a this point?
539         ((pde32_4MB_t *)guest_pde)->dirty = 0;
540         shadow_pde->writable = 0;
541       }
542     }
543   else if (shadow_pde_access == PT_ACCESS_OK) 
544     {
545       //
546       // PTE fault
547       //
548       pte32_t * shadow_pt = (pte32_t *)V3_VAddr( (void*)(addr_t) BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr) );
549
550       if (guest_pde->large_page == 0) {
551         pte32_t * guest_pt = NULL;
552         if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t*)&guest_pt) == -1) {
553           // Machine check the guest
554           PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
555           v3_raise_exception(info, MC_EXCEPTION);
556           return 0;
557         }
558         
559         if (handle_shadow_pte32_fault(info, fault_addr, error_code, shadow_pt, guest_pt)  == -1) {
560           PrintError("Error handling Page fault caused by PTE\n");
561           return -1;
562         }
563       } else if (guest_pde->large_page == 1) {
564         if (handle_large_pagefault_32(info, fault_addr, error_code, shadow_pt, (pde32_4MB_t *)guest_pde) == -1) {
565           PrintError("Error handling large pagefault\n");
566           return -1;
567         }
568       }
569     }
570   else if ((shadow_pde_access == PT_ACCESS_WRITE_ERROR) && 
571            (guest_pde->large_page == 1) && 
572            (((pde32_4MB_t *)guest_pde)->dirty == 0)) 
573     {
574       //
575       // Page Directory Entry marked read-only
576       // Its a large page and we need to update the dirty bit in the guest
577       //
578
579       PrintDebug("Large page write error... Setting dirty bit and returning\n");
580       ((pde32_4MB_t *)guest_pde)->dirty = 1;
581       shadow_pde->writable = guest_pde->writable;
582       return 0;
583       
584     } 
585   else if (shadow_pde_access == PT_ACCESS_USER_ERROR) 
586     {
587       //
588       // Page Directory Entry marked non-user
589       //      
590       PrintDebug("Shadow Paging User access error (shadow_pde_access=0x%x, guest_pde_access=0x%x)\n", 
591                  shadow_pde_access, guest_pde_access);
592       inject_guest_pf(info, fault_addr, error_code);
593       return 0;
594     }
595   else 
596     {
597       // inject page fault in guest
598       inject_guest_pf(info, fault_addr, error_code);
599       PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
600       PrintDebug("Manual Says to inject page fault into guest\n");
601 #ifdef DEBUG_SHADOW_PAGING
602       PrintDebug("Guest PDE: (access=%d)\n\t", guest_pde_access);
603       PrintPTEntry(PAGE_PD32, fault_addr, guest_pde);
604       PrintDebug("Shadow PDE: (access=%d)\n\t", shadow_pde_access);
605       PrintPTEntry(PAGE_PD32, fault_addr, shadow_pde);
606 #endif
607
608       return 0; 
609     }
610
611   PrintDebug("Returning end of PDE function (rip=%p)\n", (void *)(addr_t)(info->rip));
612   return 0;
613 }
614
615
616
617 /* The guest status checks have already been done,
618  * only special case shadow checks remain
619  */
620 static int handle_large_pagefault_32(struct guest_info * info, 
621                                     addr_t fault_addr, pf_error_t error_code, 
622                                     pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde) 
623 {
624   pt_access_status_t shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code);
625   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
626   
627   if (shadow_pte_access == PT_ACCESS_OK) {
628     // Inconsistent state...
629     // Guest Re-Entry will flush tables and everything should now workd
630     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
631     return 0;
632   }
633
634   
635   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
636     // Get the guest physical address of the fault
637     addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);
638     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
639  
640
641     if (host_page_type == HOST_REGION_INVALID) {
642       // Inject a machine check in the guest
643       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
644       v3_raise_exception(info, MC_EXCEPTION);
645       return 0;
646     }
647
648     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
649       struct shadow_page_state * state = &(info->shdw_pg_state);
650       addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
651
652       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
653
654       shadow_pte->present = 1;
655
656       /* We are assuming that the PDE entry has precedence
657        * so the Shadow PDE will mirror the guest PDE settings, 
658        * and we don't have to worry about them here
659        * Allow everything
660        */
661       shadow_pte->user_page = 1;
662
663       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) {
664         // Check if the entry is a page table...
665         PrintDebug("Marking page as Guest Page Table (large page)\n");
666         shadow_pte->vmm_info = PT32_GUEST_PT;
667         shadow_pte->writable = 0;
668       } else {
669         shadow_pte->writable = 1;
670       }
671
672
673       //set according to VMM policy
674       shadow_pte->write_through = 0;
675       shadow_pte->cache_disable = 0;
676       shadow_pte->global_page = 0;
677       //
678       
679     } else {
680       // Handle hooked pages as well as other special pages
681       if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
682         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
683         return -1;
684       }
685     }
686   } else if ((shadow_pte_access == PT_ACCESS_WRITE_ERROR) && 
687              (shadow_pte->vmm_info == PT32_GUEST_PT)) {
688
689     struct shadow_page_state * state = &(info->shdw_pg_state);
690     PrintDebug("Write operation on Guest PAge Table Page (large page)\n");
691     state->cached_cr3 = 0;
692     shadow_pte->writable = 1;
693
694   } else {
695     PrintError("Error in large page fault handler...\n");
696     PrintError("This case should have been handled at the top level handler\n");
697     return -1;
698   }
699
700   PrintDebug("Returning from large page fault handler\n");
701   return 0;
702 }
703
704
705
706
707 /* 
708  * We assume the the guest pte pointer has already been translated to a host virtual address
709  */
710 static int handle_shadow_pte32_fault(struct guest_info * info, 
711                                      addr_t fault_addr, 
712                                      pf_error_t error_code,
713                                      pte32_t * shadow_pt, 
714                                      pte32_t * guest_pt) {
715
716   pt_access_status_t guest_pte_access;
717   pt_access_status_t shadow_pte_access;
718   pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);;
719   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
720
721
722   // Check the guest page permissions
723   guest_pte_access = v3_can_access_pte32(guest_pt, fault_addr, error_code);
724
725   // Check the shadow page permissions
726   shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code);
727   
728 #ifdef DEBUG_SHADOW_PAGING
729   PrintDebug("Guest PTE: (access=%d)\n\t", guest_pte_access);
730   PrintPTEntry(PAGE_PT32, fault_addr, guest_pte);
731   PrintDebug("Shadow PTE: (access=%d)\n\t", shadow_pte_access);
732   PrintPTEntry(PAGE_PT32, fault_addr, shadow_pte);
733 #endif
734   
735   /* Was the page fault caused by the Guest's page tables? */
736   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
737     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
738                guest_pte_access, *(uint_t*)&error_code);    
739     inject_guest_pf(info, fault_addr, error_code);
740     return 0; 
741   }
742   
743   
744   if (shadow_pte_access == PT_ACCESS_OK) {
745     // Inconsistent state...
746     // Guest Re-Entry will flush page tables and everything should now work
747     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
748     return 0;
749   }
750
751
752   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
753
754     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
755
756     // Page Table Entry Not Present
757     PrintDebug("guest_pa =%p\n", (void *)guest_pa);
758
759     host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
760
761     if (host_page_type == HOST_REGION_INVALID) {
762       // Inject a machine check in the guest
763       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
764       v3_raise_exception(info, MC_EXCEPTION);
765       return 0;
766     }
767
768     // else...
769
770     if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) {
771       struct shadow_page_state * state = &(info->shdw_pg_state);
772       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
773       
774       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
775       
776       shadow_pte->present = guest_pte->present;
777       shadow_pte->user_page = guest_pte->user_page;
778       
779       //set according to VMM policy
780       shadow_pte->write_through = 0;
781       shadow_pte->cache_disable = 0;
782       shadow_pte->global_page = 0;
783       //
784       
785       guest_pte->accessed = 1;
786       
787       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) {
788         // Check if the entry is a page table...
789         PrintDebug("Marking page as Guest Page Table %d\n", shadow_pte->writable);
790         shadow_pte->vmm_info = PT32_GUEST_PT;
791       }
792
793       if (guest_pte->dirty == 1) {
794         shadow_pte->writable = guest_pte->writable;
795       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
796         shadow_pte->writable = guest_pte->writable;
797         guest_pte->dirty = 1;
798         
799         if (shadow_pte->vmm_info == PT32_GUEST_PT) {
800           // Well that was quick...
801           struct shadow_page_state * state = &(info->shdw_pg_state);
802           PrintDebug("Immediate Write operation on Guest PAge Table Page\n");
803           state->cached_cr3 = 0;
804         }
805
806       } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {  // was =
807         shadow_pte->writable = 0;
808       }
809
810
811
812     } else {
813       // Page fault handled by hook functions
814       if (handle_special_page_fault(info, fault_addr, guest_pa, error_code) == -1) {
815         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
816         return -1;
817       }
818     }
819
820   } else if ((shadow_pte_access == PT_ACCESS_WRITE_ERROR) &&
821              (guest_pte->dirty == 0)) {
822
823     PrintDebug("Shadow PTE Write Error\n");
824     guest_pte->dirty = 1;
825     shadow_pte->writable = guest_pte->writable;
826
827     if (shadow_pte->vmm_info == PT32_GUEST_PT) {
828       struct shadow_page_state * state = &(info->shdw_pg_state);
829       PrintDebug("Write operation on Guest PAge Table Page\n");
830       state->cached_cr3 = 0;
831     }
832     
833     return 0;
834
835   } else {
836     // Inject page fault into the guest 
837     inject_guest_pf(info, fault_addr, error_code);
838     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
839     PrintError("Manual Says to inject page fault into guest\n");
840     return -1;
841   }
842
843   PrintDebug("Returning end of function\n");
844   return 0;
845 }
846
847
848
849
850
851
852 /* Currently Does not work with Segmentation!!! */
853 int v3_handle_shadow_invlpg(struct guest_info * info)
854 {
855   if (info->mem_mode != VIRTUAL_MEM) {
856     // Paging must be turned on...
857     // should handle with some sort of fault I think
858     PrintError("ERROR: INVLPG called in non paged mode\n");
859     return -1;
860   }
861   
862   
863   if (info->cpu_mode != PROTECTED) {
864     PrintError("Unsupported CPU mode (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
865     return -1;
866   }
867   
868   uchar_t instr[15];
869   int index = 0;
870   
871   int ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
872   if (ret != 15) {
873     PrintError("Could not read instruction 0x%p (ret=%d)\n",  (void *)(addr_t)(info->rip), ret);
874     return -1;
875   }
876   
877   
878   /* Can INVLPG work with Segments?? */
879   while (is_prefix_byte(instr[index])) {
880     index++;
881   }
882     
883     
884   if( (instr[index + 0] != (uchar_t) 0x0f) ||  
885       (instr[index + 1] != (uchar_t) 0x01) ) {
886     PrintError("invalid Instruction Opcode\n");
887     PrintTraceMemDump(instr, 15);
888     return -1;
889   }
890   
891   addr_t first_operand;
892   addr_t second_operand;
893   addr_t guest_cr3 =  CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3);
894   
895   pde32_t * guest_pd = NULL;
896   
897   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
898     PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
899     return -1;
900   }
901   
902   index += 2;
903
904   v3_operand_type_t addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
905   
906   if (addr_type != MEM_OPERAND) {
907     PrintError("Invalid Operand type\n");
908     return -1;
909   }
910   
911   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
912   pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
913   pde32_t * guest_pde;
914   
915   //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
916   //PrintDebug("FirstOperand = %x\n", first_operand);
917   
918   PrintDebug("Invalidating page for %p\n", (void *)first_operand);
919   
920   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(first_operand)]);
921   
922   if (guest_pde->large_page == 1) {
923     shadow_pde->present = 0;
924     PrintDebug("Invalidating Large Page\n");
925   } else
926     if (shadow_pde->present == 1) {
927       pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr);
928       pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(first_operand)] );
929       
930 #ifdef DEBUG_SHADOW_PAGING
931       PrintDebug("Setting not present\n");
932       PrintPTEntry(PAGE_PT32, first_operand, shadow_pte);
933 #endif
934       
935       shadow_pte->present = 0;
936     }
937   
938   info->rip += index;
939   
940   return 0;
941 }
942
943