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.


a33d0caa020ba1775b4d4cdb18df5687e34db325
[palacios.git] / palacios / src / palacios / vmm_shadow_paging_64.h
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 static inline int activate_shadow_pt_64(struct guest_info * info) {
22   struct cr3_64 * shadow_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
23   struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
24   struct shadow_page_data * shadow_pt = create_new_shadow_pt(info);
25   addr_t shadow_pt_addr = shadow_pt->page_pa;
26
27   // Because this is a new CR3 load the allocated page is the new CR3 value
28   shadow_pt->cr3 = shadow_pt->page_pa;
29
30   PrintDebug("Top level Shadow page pa=%p\n", (void *)shadow_pt_addr);
31
32   shadow_cr3->pml4t_base_addr = PAGE_BASE_ADDR_4KB(shadow_pt_addr);
33   PrintDebug("Creating new 64 bit shadow page table %p\n", (void *)BASE_TO_PAGE_ADDR(shadow_cr3->pml4t_base_addr));
34
35   
36   shadow_cr3->pwt = guest_cr3->pwt;
37   shadow_cr3->pcd = guest_cr3->pcd;
38
39   return 0;
40 }
41
42
43
44
45
46
47 /* 
48  * *
49  * * 
50  * * 64 bit Page table fault handlers
51  * *
52  * *
53  */
54
55 static int handle_2MB_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
56                                           pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde);
57
58 static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
59                                           pte64_t * shadow_pt, pte64_t * guest_pt);
60
61 static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
62                                           pde64_t * shadow_pd, pde64_t * guest_pd);
63
64 static int handle_pdpe_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
65                                            pdpe64_t * shadow_pdp, pdpe64_t * guest_pdp);
66
67
68 static inline int handle_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) {
69   pml4e64_t * guest_pml = NULL;
70   pml4e64_t * shadow_pml = CR3_TO_PML4E64_VA(info->ctrl_regs.cr3);
71   addr_t guest_cr3 = CR3_TO_PML4E64_PA(info->shdw_pg_state.guest_cr3);
72   pt_access_status_t guest_pml4e_access;
73   pt_access_status_t shadow_pml4e_access;
74   pml4e64_t * guest_pml4e = NULL;
75   pml4e64_t * shadow_pml4e = (pml4e64_t *)&(shadow_pml[PML4E64_INDEX(fault_addr)]);
76
77   PrintDebug("64 bit Shadow page fault handler: %p\n", (void *)fault_addr);
78   PrintDebug("Handling PML fault\n");
79
80   if (guest_pa_to_host_va(info, guest_cr3, (addr_t*)&guest_pml) == -1) {
81     PrintError("Invalid Guest PML4E Address: 0x%p\n",  (void *)guest_cr3);
82     return -1;
83   } 
84
85   guest_pml4e = (pml4e64_t *)&(guest_pml[PML4E64_INDEX(fault_addr)]);
86
87   PrintDebug("Checking Guest %p\n", (void *)guest_pml);
88   // Check the guest page permissions
89   guest_pml4e_access = v3_can_access_pml4e64(guest_pml, fault_addr, error_code);
90
91   PrintDebug("Checking shadow %p\n", (void *)shadow_pml);
92   // Check the shadow page permissions
93   shadow_pml4e_access = v3_can_access_pml4e64(shadow_pml, fault_addr, error_code);
94   
95   /* Was the page fault caused by the Guest's page tables? */
96   if (is_guest_pf(guest_pml4e_access, shadow_pml4e_access) == 1) {
97     PrintDebug("Injecting PML4E pf to guest: (guest access error=%d) (pf error code=%d)\n", 
98                *(uint_t *)&guest_pml4e_access, *(uint_t *)&error_code);
99     inject_guest_pf(info, fault_addr, error_code);
100     return 0;
101   }
102
103   if (shadow_pml4e_access == PT_ACCESS_USER_ERROR) {
104     //
105     // PML4 Entry marked non-user
106     //      
107     PrintDebug("Shadow Paging User access error (shadow_pml4e_access=0x%x, guest_pml4e_access=0x%x)\n", 
108                shadow_pml4e_access, guest_pml4e_access);
109     inject_guest_pf(info, fault_addr, error_code);
110     return 0;
111   } else if ((shadow_pml4e_access != PT_ACCESS_NOT_PRESENT) &&
112              (shadow_pml4e_access != PT_ACCESS_OK)) {
113     // inject page fault in guest
114     inject_guest_pf(info, fault_addr, error_code);
115     PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pml4e_access);
116     PrintDebug("Manual Says to inject page fault into guest\n");
117     return 0;
118   }
119
120
121   pdpe64_t * shadow_pdp = NULL;
122   pdpe64_t * guest_pdp = NULL;
123
124   // Get the next shadow page level, allocate if not present
125
126   if (shadow_pml4e_access == PT_ACCESS_NOT_PRESENT) {
127     struct shadow_page_data * shdw_page =  create_new_shadow_pt(info);
128     shadow_pdp = (pdpe64_t *)V3_VAddr((void *)shdw_page->page_pa);
129
130
131     shadow_pml4e->present = 1;
132     shadow_pml4e->user_page = guest_pml4e->user_page;
133     shadow_pml4e->writable = guest_pml4e->writable;
134     
135     // VMM Specific options
136     shadow_pml4e->write_through = 0;
137     shadow_pml4e->cache_disable = 0;
138     //
139     
140     guest_pml4e->accessed = 1;
141     
142     shadow_pml4e->pdp_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
143   } else {
144     shadow_pdp = (pdpe64_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pml4e->pdp_base_addr));
145   }
146
147   // Continue processing at the next level
148
149   if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr), (addr_t *)&guest_pdp) == -1) {
150     // Machine check the guest
151     PrintDebug("Invalid Guest PDP Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pml4e->pdp_base_addr));
152     v3_raise_exception(info, MC_EXCEPTION);
153     return 0;
154   }
155   
156   if (handle_pdpe_shadow_pagefault_64(info, fault_addr, error_code, shadow_pdp, guest_pdp) == -1) {
157     PrintError("Error handling Page fault caused by PDPE\n");
158     return -1;
159   }
160
161   return 0;
162 }
163
164
165
166 // For now we are not going to handle 1 Gigabyte pages
167 static int handle_pdpe_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
168                                            pdpe64_t * shadow_pdp, pdpe64_t * guest_pdp) {
169   pt_access_status_t guest_pdpe_access;
170   pt_access_status_t shadow_pdpe_access;
171   pdpe64_t * guest_pdpe = (pdpe64_t *)&(guest_pdp[PDPE64_INDEX(fault_addr)]);
172   pdpe64_t * shadow_pdpe = (pdpe64_t *)&(shadow_pdp[PDPE64_INDEX(fault_addr)]);
173  
174   PrintDebug("Handling PDP fault\n");
175
176   if (fault_addr==0) { 
177     PrintDebug("Guest Page Tree for guest virtual address zero fault\n");
178     PrintGuestPageTree(info,fault_addr,(addr_t)(info->shdw_pg_state.guest_cr3));
179     PrintDebug("Host Page Tree for guest virtual address zero fault\n");
180     PrintHostPageTree(info,fault_addr,(addr_t)(info->ctrl_regs.cr3));
181   }
182
183   // Check the guest page permissions
184   guest_pdpe_access = v3_can_access_pdpe64(guest_pdp, fault_addr, error_code);
185
186   // Check the shadow page permissions
187   shadow_pdpe_access = v3_can_access_pdpe64(shadow_pdp, fault_addr, error_code);
188   
189   /* Was the page fault caused by the Guest's page tables? */
190   if (is_guest_pf(guest_pdpe_access, shadow_pdpe_access) == 1) {
191     PrintDebug("Injecting PDPE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
192                *(uint_t *)&guest_pdpe_access, *(uint_t *)&error_code);
193     inject_guest_pf(info, fault_addr, error_code);
194     return 0;
195   }
196
197   if (shadow_pdpe_access == PT_ACCESS_USER_ERROR) {
198     //
199     // PML4 Entry marked non-user
200     //      
201     PrintDebug("Shadow Paging User access error (shadow_pdpe_access=0x%x, guest_pdpe_access=0x%x)\n", 
202                shadow_pdpe_access, guest_pdpe_access);
203     inject_guest_pf(info, fault_addr, error_code);
204     return 0;
205   } else if ((shadow_pdpe_access != PT_ACCESS_NOT_PRESENT) &&
206              (shadow_pdpe_access != PT_ACCESS_OK)) {
207     // inject page fault in guest
208     inject_guest_pf(info, fault_addr, error_code);
209     PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pdpe_access);
210     PrintDebug("Manual Says to inject page fault into guest\n");
211     return 0;
212   }
213
214
215   pde64_t * shadow_pd = NULL;
216   pde64_t * guest_pd = NULL;
217
218   // Get the next shadow page level, allocate if not present
219
220   if (shadow_pdpe_access == PT_ACCESS_NOT_PRESENT) {
221     struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
222     shadow_pd = (pde64_t *)V3_VAddr((void *)shdw_page->page_pa);
223
224
225     shadow_pdpe->present = 1;
226     shadow_pdpe->user_page = guest_pdpe->user_page;
227     shadow_pdpe->writable = guest_pdpe->writable;
228     
229     // VMM Specific options
230     shadow_pdpe->write_through = 0;
231     shadow_pdpe->cache_disable = 0;
232     //
233     
234     guest_pdpe->accessed = 1;
235     
236     shadow_pdpe->pd_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
237   } else {
238     shadow_pd = (pde64_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pdpe->pd_base_addr));
239   }
240
241   // Continue processing at the next level
242
243   if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr), (addr_t *)&guest_pd) == -1) {
244     // Machine check the guest
245     PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
246     v3_raise_exception(info, MC_EXCEPTION);
247     return 0;
248   }
249   
250   if (handle_pde_shadow_pagefault_64(info, fault_addr, error_code, shadow_pd, guest_pd) == -1) {
251     PrintError("Error handling Page fault caused by PDE\n");
252     return -1;
253   }
254
255   return 0;
256 }
257
258
259 static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
260                                           pde64_t * shadow_pd, pde64_t * guest_pd) {
261   pt_access_status_t guest_pde_access;
262   pt_access_status_t shadow_pde_access;
263   pde64_t * guest_pde = (pde64_t *)&(guest_pd[PDE64_INDEX(fault_addr)]);
264   pde64_t * shadow_pde = (pde64_t *)&(shadow_pd[PDE64_INDEX(fault_addr)]);
265
266   PrintDebug("Handling PDE fault\n");
267  
268   // Check the guest page permissions
269   guest_pde_access = v3_can_access_pde64(guest_pd, fault_addr, error_code);
270
271   // Check the shadow page permissions
272   shadow_pde_access = v3_can_access_pde64(shadow_pd, fault_addr, error_code);
273   
274   /* Was the page fault caused by the Guest's page tables? */
275   if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
276     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
277                *(uint_t *)&guest_pde_access, *(uint_t *)&error_code);
278     inject_guest_pf(info, fault_addr, error_code);
279     return 0;
280   }
281
282   if (shadow_pde_access == PT_ACCESS_USER_ERROR) {
283     //
284     // PDE Entry marked non-user
285     //      
286     PrintDebug("Shadow Paging User access error (shadow_pdpe_access=0x%x, guest_pdpe_access=0x%x)\n", 
287                shadow_pde_access, guest_pde_access);
288     inject_guest_pf(info, fault_addr, error_code);
289     return 0;
290
291   } else if ((shadow_pde_access == PT_ACCESS_WRITE_ERROR) && 
292              (guest_pde->large_page == 1)) {
293
294     ((pde64_2MB_t *)guest_pde)->dirty = 1;
295     shadow_pde->writable = guest_pde->writable;
296
297     //PrintDebug("Returning due to large page Write Error\n");
298     //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
299
300     return 0;
301   } else if ((shadow_pde_access != PT_ACCESS_NOT_PRESENT) &&
302              (shadow_pde_access != PT_ACCESS_OK)) {
303     // inject page fault in guest
304     inject_guest_pf(info, fault_addr, error_code);
305     PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
306     PrintDebug("Manual Says to inject page fault into guest\n");
307     return 0;
308   }
309
310
311   pte64_t * shadow_pt = NULL;
312   pte64_t * guest_pt = NULL;
313
314   // Get the next shadow page level, allocate if not present
315
316   if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
317     struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
318     shadow_pt = (pte64_t *)V3_VAddr((void *)shdw_page->page_pa);
319
320     PrintDebug("Creating new shadow PT: %p\n", shadow_pt);
321
322     shadow_pde->present = 1;
323     shadow_pde->user_page = guest_pde->user_page;
324
325
326     if (guest_pde->large_page == 0) {
327       shadow_pde->writable = guest_pde->writable;
328     } else {
329       // This large page flag is temporary until we can get a working cache....
330       ((pde64_2MB_t *)guest_pde)->vmm_info = V3_LARGE_PG;
331
332       if (error_code.write) {
333         shadow_pde->writable = guest_pde->writable;
334         ((pde64_2MB_t *)guest_pde)->dirty = 1;  
335       } else {
336         shadow_pde->writable = 0;
337         ((pde64_2MB_t *)guest_pde)->dirty = 0;
338       }
339     }
340     
341     // VMM Specific options
342     shadow_pde->write_through = 0;
343     shadow_pde->cache_disable = 0;
344     shadow_pde->global_page = 0;
345     //
346     
347     guest_pde->accessed = 1;
348     
349     shadow_pde->pt_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
350   } else {
351     shadow_pt = (pte64_t *)V3_VAddr((void *)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr));
352   }
353
354   // Continue processing at the next level
355   if (guest_pde->large_page == 0) {
356     if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t *)&guest_pt) == -1) {
357       // Machine check the guest
358       PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
359       v3_raise_exception(info, MC_EXCEPTION);
360       return 0;
361     }
362     
363     if (handle_pte_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, guest_pt) == -1) {
364       PrintError("Error handling Page fault caused by PDE\n");
365       return -1;
366     }
367   } else {
368     if (handle_2MB_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, (pde64_2MB_t *)guest_pde) == -1) {
369       PrintError("Error handling large pagefault\n");
370       return -1;
371     } 
372   }
373
374   return 0;
375 }
376
377
378 static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
379                                           pte64_t * shadow_pt, pte64_t * guest_pt) {
380   pt_access_status_t guest_pte_access;
381   pt_access_status_t shadow_pte_access;
382   pte64_t * guest_pte = (pte64_t *)&(guest_pt[PTE64_INDEX(fault_addr)]);;
383   pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
384   addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
385   //  struct shadow_page_state * state = &(info->shdw_pg_state);
386
387   PrintDebug("Handling PTE fault\n");
388
389   struct v3_shadow_region * shdw_reg =  v3_get_shadow_region(info, guest_pa);
390
391
392
393   if ((shdw_reg == NULL) || 
394       (shdw_reg->host_type == SHDW_REGION_INVALID)) {
395     // Inject a machine check in the guest
396     PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
397     v3_raise_exception(info, MC_EXCEPTION);
398     return 0;
399   }
400
401   // Check the guest page permissions
402   guest_pte_access = v3_can_access_pte64(guest_pt, fault_addr, error_code);
403
404   // Check the shadow page permissions
405   shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
406
407   /* Was the page fault caused by the Guest's page tables? */
408   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
409     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
410                guest_pte_access, *(uint_t*)&error_code);    
411     inject_guest_pf(info, fault_addr, error_code);
412     return 0; 
413   }
414
415  
416   if (shadow_pte_access == PT_ACCESS_OK) {
417     // Inconsistent state...
418     // Guest Re-Entry will flush page tables and everything should now work
419     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
420     return 0;
421   }
422
423
424   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
425     // Page Table Entry Not Present
426     PrintDebug("guest_pa =%p\n", (void *)guest_pa);
427
428     if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) ||
429         (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
430       addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa);
431       
432       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
433       
434       shadow_pte->present = guest_pte->present;
435       shadow_pte->user_page = guest_pte->user_page;
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       guest_pte->accessed = 1;
444       
445       if (guest_pte->dirty == 1) {
446         shadow_pte->writable = guest_pte->writable;
447       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
448         shadow_pte->writable = guest_pte->writable;
449         guest_pte->dirty = 1;
450       } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {
451         shadow_pte->writable = 0;
452       }
453
454       // dirty flag has been set, check if its in the cache
455 /*       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { */
456 /*      if (error_code.write == 1) { */
457 /*        state->cached_cr3 = 0; */
458 /*        shadow_pte->writable = guest_pte->writable; */
459 /*      } else { */
460 /*        shadow_pte->writable = 0; */
461 /*      } */
462 /*       } */
463
464       // Write hooks trump all, and are set Read Only
465       if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
466         shadow_pte->writable = 0;
467       }
468
469     } else {
470       // Page fault handled by hook functions
471
472       if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
473         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
474         return -1;
475       }
476     }
477   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
478     guest_pte->dirty = 1;
479
480     if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
481       if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
482         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
483         return -1;
484       }
485     } else {
486       PrintDebug("Shadow PTE Write Error\n");
487       shadow_pte->writable = guest_pte->writable;
488     }
489
490 /*     if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { */
491 /*       struct shadow_page_state * state = &(info->shdw_pg_state); */
492 /*       PrintDebug("Write operation on Guest PAge Table Page\n"); */
493 /*       state->cached_cr3 = 0; */
494 /*     } */
495
496     return 0;
497
498   } else {
499     // Inject page fault into the guest 
500     inject_guest_pf(info, fault_addr, error_code);
501     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
502     PrintError("Manual Says to inject page fault into guest\n");
503     return -1;
504   }
505
506   return 0;
507 }
508
509
510
511 static int handle_2MB_shadow_pagefault_64(struct guest_info * info, 
512                                           addr_t fault_addr, pf_error_t error_code, 
513                                           pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde) 
514 {
515   pt_access_status_t shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
516   pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
517   addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
518   //  struct shadow_page_state * state = &(info->shdw_pg_state);
519
520   PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
521   PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
522
523   struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_fault_pa);
524
525  
526   if ((shdw_reg == NULL) || 
527       (shdw_reg->host_type == SHDW_REGION_INVALID)) {
528     // Inject a machine check in the guest
529     PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
530     v3_raise_exception(info, MC_EXCEPTION);
531     return -1;
532   }
533
534   if (shadow_pte_access == PT_ACCESS_OK) {
535     // Inconsistent state...
536     // Guest Re-Entry will flush tables and everything should now workd
537     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
538     //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
539     return 0;
540   }
541
542   
543   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
544     // Get the guest physical address of the fault
545
546     if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || 
547         (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
548       addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa);
549
550       PrintDebug("Shadow PA=%p, ShadowPTE=%p\n", (void *)shadow_pa, (void *)shadow_pte);
551
552       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
553       PrintDebug("Test1\n");
554
555       shadow_pte->present = 1;
556
557       /* We are assuming that the PDE entry has precedence
558        * so the Shadow PDE will mirror the guest PDE settings, 
559        * and we don't have to worry about them here
560        * Allow everything
561        */
562       shadow_pte->user_page = 1;
563
564
565
566 /*       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { */
567 /*      // Check if the entry is a page table... */
568 /*      PrintDebug("Marking page as Guest Page Table (large page)\n"); */
569 /*      shadow_pte->writable = 0; */
570 /*       } else */ if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
571         shadow_pte->writable = 0;
572       } else {
573         shadow_pte->writable = 1;
574       }
575
576       //set according to VMM policy
577       shadow_pte->write_through = 0;
578       shadow_pte->cache_disable = 0;
579       shadow_pte->global_page = 0;
580       //
581       
582     } else {
583       // Handle hooked pages as well as other special pages
584       //      if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
585
586       if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
587         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
588         return -1;
589       }
590     }
591   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
592
593     if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
594
595       if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
596         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
597         return -1;
598       }
599     }
600
601
602 /*     if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { */
603 /*       struct shadow_page_state * state = &(info->shdw_pg_state); */
604 /*       PrintDebug("Write operation on Guest PAge Table Page (large page)\n"); */
605 /*       state->cached_cr3 = 0; */
606 /*       shadow_pte->writable = 1; */
607 /*     } */
608
609   } else {
610     PrintError("Error in large page fault handler...\n");
611     PrintError("This case should have been handled at the top level handler\n");
612     return -1;
613   }
614
615   //  PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
616   PrintDebug("Returning from large page fault handler\n");
617   return 0;
618 }
619
620
621
622
623 static int invalidation_cb_64(struct guest_info * info, page_type_t type, 
624                               addr_t vaddr, addr_t page_ptr, addr_t page_pa, 
625                               void * private_data) {
626
627   switch (type) {
628   case PAGE_PML464:
629     {    
630       pml4e64_t * pml = (pml4e64_t *)page_ptr;
631
632       if (pml[PML4E64_INDEX(vaddr)].present == 0) {
633         return 1;
634       }
635       return 0;
636     }
637   case PAGE_PDP64:
638     {
639       pdpe64_t * pdp = (pdpe64_t *)page_ptr;
640       pdpe64_t * pdpe = &(pdp[PDPE64_INDEX(vaddr)]);
641
642       if (pdpe->present == 0) {
643         return 1;
644       }
645      
646       if (pdpe->vmm_info == V3_LARGE_PG) {
647         PrintError("1 Gigabyte pages not supported\n");
648         return -1;
649
650         pdpe->present = 0;
651         return 1;
652       }
653
654       return 0;
655     }
656   case PAGE_PD64:
657     {
658       pde64_t * pd = (pde64_t *)page_ptr;
659       pde64_t * pde = &(pd[PDE64_INDEX(vaddr)]);
660
661       if (pde->present == 0) {
662         return 1;
663       }
664       
665       if (pde->vmm_info == V3_LARGE_PG) {
666         pde->present = 0;
667         return 1;
668       }
669
670       return 0;
671     }
672   case PAGE_PT64:
673     {
674       pte64_t * pt = (pte64_t *)page_ptr;
675
676       pt[PTE64_INDEX(vaddr)].present = 0;
677
678       return 1;
679     }
680   default:
681     PrintError("Invalid Page Type\n");
682     return -1;
683
684   }
685
686   // should not get here
687   PrintError("Should not get here....\n");
688   return -1;
689 }
690
691
692 static inline int handle_shadow_invlpg_64(struct guest_info * info, addr_t vaddr) {
693   PrintDebug("INVLPG64 - %p\n",(void*)vaddr);
694
695   int ret =  v3_drill_host_pt_64(info, info->ctrl_regs.cr3, vaddr, invalidation_cb_64, NULL);
696   if (ret == -1) {
697     PrintError("Page table drill returned error.... \n");
698     PrintHostPageTree(info, vaddr, info->ctrl_regs.cr3);
699   }
700
701   return (ret == -1) ? -1 : 0; 
702 }