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.


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