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.


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