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.


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