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.


working instruction emulation
[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   addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);  
627
628   if (shadow_pte_access == PT_ACCESS_OK) {
629     // Inconsistent state...
630     // Guest Re-Entry will flush tables and everything should now workd
631     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
632     return 0;
633   }
634
635   
636   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
637     // Get the guest physical address of the fault
638     shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
639  
640
641     if (host_page_type == SHDW_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 == SHDW_REGION_ALLOCATED) || 
649         (host_page_type == SHDW_REGION_WRITE_HOOK)) {
650       struct shadow_page_state * state = &(info->shdw_pg_state);
651       addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
652
653       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
654
655       shadow_pte->present = 1;
656
657       /* We are assuming that the PDE entry has precedence
658        * so the Shadow PDE will mirror the guest PDE settings, 
659        * and we don't have to worry about them here
660        * Allow everything
661        */
662       shadow_pte->user_page = 1;
663
664       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) {
665         // Check if the entry is a page table...
666         PrintDebug("Marking page as Guest Page Table (large page)\n");
667         shadow_pte->vmm_info = PT32_GUEST_PT;
668         shadow_pte->writable = 0;
669       } else if (host_page_type == SHDW_REGION_WRITE_HOOK) {
670         shadow_pte->writable = 0;
671       } else {
672         shadow_pte->writable = 1;
673       }
674
675       //set according to VMM policy
676       shadow_pte->write_through = 0;
677       shadow_pte->cache_disable = 0;
678       shadow_pte->global_page = 0;
679       //
680       
681     } else {
682       // Handle hooked pages as well as other special pages
683       //      if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
684       struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
685
686       if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
687         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
688         return -1;
689       }
690     }
691   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
692     shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
693
694     if (host_page_type == SHDW_REGION_WRITE_HOOK) {
695       struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
696
697       if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
698         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
699         return -1;
700       }
701     } else if (shadow_pte->vmm_info == PT32_GUEST_PT) {
702       struct shadow_page_state * state = &(info->shdw_pg_state);
703       PrintDebug("Write operation on Guest PAge Table Page (large page)\n");
704       state->cached_cr3 = 0;
705       shadow_pte->writable = 1;
706     }
707
708   } else {
709     PrintError("Error in large page fault handler...\n");
710     PrintError("This case should have been handled at the top level handler\n");
711     return -1;
712   }
713
714   PrintDebug("Returning from large page fault handler\n");
715   return 0;
716 }
717
718
719
720
721 /* 
722  * We assume the the guest pte pointer has already been translated to a host virtual address
723  */
724 static int handle_shadow_pte32_fault(struct guest_info * info, 
725                                      addr_t fault_addr, 
726                                      pf_error_t error_code,
727                                      pte32_t * shadow_pt, 
728                                      pte32_t * guest_pt) {
729
730   pt_access_status_t guest_pte_access;
731   pt_access_status_t shadow_pte_access;
732   pte32_t * guest_pte = (pte32_t *)&(guest_pt[PTE32_INDEX(fault_addr)]);;
733   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
734   addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
735
736
737   // Check the guest page permissions
738   guest_pte_access = v3_can_access_pte32(guest_pt, fault_addr, error_code);
739
740   // Check the shadow page permissions
741   shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code);
742   
743 #ifdef DEBUG_SHADOW_PAGING
744   PrintDebug("Guest PTE: (access=%d)\n\t", guest_pte_access);
745   PrintPTEntry(PAGE_PT32, fault_addr, guest_pte);
746   PrintDebug("Shadow PTE: (access=%d)\n\t", shadow_pte_access);
747   PrintPTEntry(PAGE_PT32, fault_addr, shadow_pte);
748 #endif
749   
750   /* Was the page fault caused by the Guest's page tables? */
751   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
752     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
753                guest_pte_access, *(uint_t*)&error_code);    
754     inject_guest_pf(info, fault_addr, error_code);
755     return 0; 
756   }
757   
758   
759   if (shadow_pte_access == PT_ACCESS_OK) {
760     // Inconsistent state...
761     // Guest Re-Entry will flush page tables and everything should now work
762     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
763     return 0;
764   }
765
766
767   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
768
769
770     // Page Table Entry Not Present
771     PrintDebug("guest_pa =%p\n", (void *)guest_pa);
772
773     shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
774
775     if (host_page_type == SHDW_REGION_INVALID) {
776       // Inject a machine check in the guest
777       PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
778       v3_raise_exception(info, MC_EXCEPTION);
779       return 0;
780     }
781
782     // else...
783
784     if ((host_page_type == SHDW_REGION_ALLOCATED) ||
785         (host_page_type == SHDW_REGION_WRITE_HOOK)) {
786       struct shadow_page_state * state = &(info->shdw_pg_state);
787       addr_t shadow_pa = get_shadow_addr(info, guest_pa);
788       
789       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
790       
791       shadow_pte->present = guest_pte->present;
792       shadow_pte->user_page = guest_pte->user_page;
793       
794       //set according to VMM policy
795       shadow_pte->write_through = 0;
796       shadow_pte->cache_disable = 0;
797       shadow_pte->global_page = 0;
798       //
799       
800       guest_pte->accessed = 1;
801       
802       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) {
803         // Check if the entry is a page table...
804         PrintDebug("Marking page as Guest Page Table %d\n", shadow_pte->writable);
805         shadow_pte->vmm_info = PT32_GUEST_PT;
806       }
807
808       if (host_page_type == SHDW_REGION_WRITE_HOOK) {
809         shadow_pte->writable = 0;
810       } else if (guest_pte->dirty == 1) {
811         shadow_pte->writable = guest_pte->writable;
812       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
813         shadow_pte->writable = guest_pte->writable;
814         guest_pte->dirty = 1;
815         
816         if (shadow_pte->vmm_info == PT32_GUEST_PT) {
817           // Well that was quick...
818           struct shadow_page_state * state = &(info->shdw_pg_state);
819           PrintDebug("Immediate Write operation on Guest PAge Table Page\n");
820           state->cached_cr3 = 0;
821         }
822
823       } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {  // was =
824         shadow_pte->writable = 0;
825       }
826
827     } else {
828       // Page fault handled by hook functions
829       struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
830
831       if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
832         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
833         return -1;
834       }
835     }
836     /*
837   } else if ((shadow_pte_access == PT_ACCESS_WRITE_ERROR) &&
838              (guest_pte->dirty == 0)) {
839     */
840   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
841     guest_pte->dirty = 1;
842
843     shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
844
845     if (host_page_type == SHDW_REGION_WRITE_HOOK) {
846       struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
847
848       if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
849         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
850         return -1;
851       }
852     } else {
853       PrintDebug("Shadow PTE Write Error\n");
854       shadow_pte->writable = guest_pte->writable;
855     }
856
857     if (shadow_pte->vmm_info == PT32_GUEST_PT) {
858       struct shadow_page_state * state = &(info->shdw_pg_state);
859       PrintDebug("Write operation on Guest PAge Table Page\n");
860       state->cached_cr3 = 0;
861     }
862
863     return 0;
864
865   } else {
866     // Inject page fault into the guest 
867     inject_guest_pf(info, fault_addr, error_code);
868     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
869     PrintError("Manual Says to inject page fault into guest\n");
870     return -1;
871   }
872
873   PrintDebug("Returning end of function\n");
874   return 0;
875 }
876
877
878
879
880
881
882 /* Currently Does not work with Segmentation!!! */
883 int v3_handle_shadow_invlpg(struct guest_info * info)
884 {
885   if (info->mem_mode != VIRTUAL_MEM) {
886     // Paging must be turned on...
887     // should handle with some sort of fault I think
888     PrintError("ERROR: INVLPG called in non paged mode\n");
889     return -1;
890   }
891   
892   
893   if (info->cpu_mode != PROTECTED) {
894     PrintError("Unsupported CPU mode (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
895     return -1;
896   }
897   
898   uchar_t instr[15];
899   int index = 0;
900   
901   int ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
902   if (ret != 15) {
903     PrintError("Could not read instruction 0x%p (ret=%d)\n",  (void *)(addr_t)(info->rip), ret);
904     return -1;
905   }
906   
907   
908   /* Can INVLPG work with Segments?? */
909   while (is_prefix_byte(instr[index])) {
910     index++;
911   }
912     
913     
914   if( (instr[index + 0] != (uchar_t) 0x0f) ||  
915       (instr[index + 1] != (uchar_t) 0x01) ) {
916     PrintError("invalid Instruction Opcode\n");
917     PrintTraceMemDump(instr, 15);
918     return -1;
919   }
920   
921   addr_t first_operand;
922   addr_t second_operand;
923   addr_t guest_cr3 =  CR3_TO_PDE32_PA(info->shdw_pg_state.guest_cr3);
924   
925   pde32_t * guest_pd = NULL;
926   
927   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pd) == -1) {
928     PrintError("Invalid Guest PDE Address: 0x%p\n",  (void *)guest_cr3);
929     return -1;
930   }
931   
932   index += 2;
933
934   v3_operand_type_t addr_type = decode_operands32(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32);
935   
936   if (addr_type != MEM_OPERAND) {
937     PrintError("Invalid Operand type\n");
938     return -1;
939   }
940   
941   pde32_t * shadow_pd = (pde32_t *)CR3_TO_PDE32_VA(info->ctrl_regs.cr3);
942   pde32_t * shadow_pde = (pde32_t *)&shadow_pd[PDE32_INDEX(first_operand)];
943   pde32_t * guest_pde;
944   
945   //PrintDebug("PDE Index=%d\n", PDE32_INDEX(first_operand));
946   //PrintDebug("FirstOperand = %x\n", first_operand);
947   
948   PrintDebug("Invalidating page for %p\n", (void *)first_operand);
949   
950   guest_pde = (pde32_t *)&(guest_pd[PDE32_INDEX(first_operand)]);
951   
952   if (guest_pde->large_page == 1) {
953     shadow_pde->present = 0;
954     PrintDebug("Invalidating Large Page\n");
955   } else
956     if (shadow_pde->present == 1) {
957       pte32_t * shadow_pt = (pte32_t *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr);
958       pte32_t * shadow_pte = (pte32_t *) V3_VAddr( (void*) &shadow_pt[PTE32_INDEX(first_operand)] );
959       
960 #ifdef DEBUG_SHADOW_PAGING
961       PrintDebug("Setting not present\n");
962       PrintPTEntry(PAGE_PT32, first_operand, shadow_pte);
963 #endif
964       
965       shadow_pte->present = 0;
966     }
967   
968   info->rip += index;
969   
970   return 0;
971 }
972
973