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.


added license
[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   // Check the guest page permissions
177   guest_pdpe_access = v3_can_access_pdpe64(guest_pdp, fault_addr, error_code);
178
179   // Check the shadow page permissions
180   shadow_pdpe_access = v3_can_access_pdpe64(shadow_pdp, fault_addr, error_code);
181   
182   /* Was the page fault caused by the Guest's page tables? */
183   if (is_guest_pf(guest_pdpe_access, shadow_pdpe_access) == 1) {
184     PrintDebug("Injecting PDPE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
185                *(uint_t *)&guest_pdpe_access, *(uint_t *)&error_code);
186     inject_guest_pf(info, fault_addr, error_code);
187     return 0;
188   }
189
190   if (shadow_pdpe_access == PT_ACCESS_USER_ERROR) {
191     //
192     // PML4 Entry marked non-user
193     //      
194     PrintDebug("Shadow Paging User access error (shadow_pdpe_access=0x%x, guest_pdpe_access=0x%x)\n", 
195                shadow_pdpe_access, guest_pdpe_access);
196     inject_guest_pf(info, fault_addr, error_code);
197     return 0;
198   } else if ((shadow_pdpe_access != PT_ACCESS_NOT_PRESENT) &&
199              (shadow_pdpe_access != PT_ACCESS_OK)) {
200     // inject page fault in guest
201     inject_guest_pf(info, fault_addr, error_code);
202     PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pdpe_access);
203     PrintDebug("Manual Says to inject page fault into guest\n");
204     return 0;
205   }
206
207
208   pde64_t * shadow_pd = NULL;
209   pde64_t * guest_pd = NULL;
210
211   // Get the next shadow page level, allocate if not present
212
213   if (shadow_pdpe_access == PT_ACCESS_NOT_PRESENT) {
214     struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
215     shadow_pd = (pde64_t *)V3_VAddr((void *)shdw_page->page_pa);
216
217
218     shadow_pdpe->present = 1;
219     shadow_pdpe->user_page = guest_pdpe->user_page;
220     shadow_pdpe->writable = guest_pdpe->writable;
221     
222     // VMM Specific options
223     shadow_pdpe->write_through = 0;
224     shadow_pdpe->cache_disable = 0;
225     //
226     
227     guest_pdpe->accessed = 1;
228     
229     shadow_pdpe->pd_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
230   } else {
231     shadow_pd = (pde64_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(shadow_pdpe->pd_base_addr));
232   }
233
234   // Continue processing at the next level
235
236   if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr), (addr_t *)&guest_pd) == -1) {
237     // Machine check the guest
238     PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pdpe->pd_base_addr));
239     v3_raise_exception(info, MC_EXCEPTION);
240     return 0;
241   }
242   
243   if (handle_pde_shadow_pagefault_64(info, fault_addr, error_code, shadow_pd, guest_pd) == -1) {
244     PrintError("Error handling Page fault caused by PDE\n");
245     return -1;
246   }
247
248   return 0;
249 }
250
251
252 static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
253                                           pde64_t * shadow_pd, pde64_t * guest_pd) {
254   pt_access_status_t guest_pde_access;
255   pt_access_status_t shadow_pde_access;
256   pde64_t * guest_pde = (pde64_t *)&(guest_pd[PDE64_INDEX(fault_addr)]);
257   pde64_t * shadow_pde = (pde64_t *)&(shadow_pd[PDE64_INDEX(fault_addr)]);
258
259   PrintDebug("Handling PDE fault\n");
260  
261   // Check the guest page permissions
262   guest_pde_access = v3_can_access_pde64(guest_pd, fault_addr, error_code);
263
264   // Check the shadow page permissions
265   shadow_pde_access = v3_can_access_pde64(shadow_pd, fault_addr, error_code);
266   
267   /* Was the page fault caused by the Guest's page tables? */
268   if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
269     PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
270                *(uint_t *)&guest_pde_access, *(uint_t *)&error_code);
271     inject_guest_pf(info, fault_addr, error_code);
272     return 0;
273   }
274
275   if (shadow_pde_access == PT_ACCESS_USER_ERROR) {
276     //
277     // PDE Entry marked non-user
278     //      
279     PrintDebug("Shadow Paging User access error (shadow_pdpe_access=0x%x, guest_pdpe_access=0x%x)\n", 
280                shadow_pde_access, guest_pde_access);
281     inject_guest_pf(info, fault_addr, error_code);
282     return 0;
283
284   } else if ((shadow_pde_access == PT_ACCESS_WRITE_ERROR) && 
285              (guest_pde->large_page == 1)) {
286
287     ((pde64_2MB_t *)guest_pde)->dirty = 1;
288     shadow_pde->writable = guest_pde->writable;
289
290     //PrintDebug("Returning due to large page Write Error\n");
291     //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
292
293     return 0;
294   } else if ((shadow_pde_access != PT_ACCESS_NOT_PRESENT) &&
295              (shadow_pde_access != PT_ACCESS_OK)) {
296     // inject page fault in guest
297     inject_guest_pf(info, fault_addr, error_code);
298     PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
299     PrintDebug("Manual Says to inject page fault into guest\n");
300     return 0;
301   }
302
303
304   pte64_t * shadow_pt = NULL;
305   pte64_t * guest_pt = NULL;
306
307   // Get the next shadow page level, allocate if not present
308
309   if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
310     struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
311     shadow_pt = (pte64_t *)V3_VAddr((void *)shdw_page->page_pa);
312
313     PrintDebug("Creating new shadow PT: %p\n", shadow_pt);
314
315     shadow_pde->present = 1;
316     shadow_pde->user_page = guest_pde->user_page;
317
318
319     if (guest_pde->large_page == 0) {
320       shadow_pde->writable = guest_pde->writable;
321     } else {
322       // This large page flag is temporary until we can get a working cache....
323       ((pde64_2MB_t *)guest_pde)->vmm_info = V3_LARGE_PG;
324
325       if (error_code.write) {
326         shadow_pde->writable = guest_pde->writable;
327         ((pde64_2MB_t *)guest_pde)->dirty = 1;  
328       } else {
329         shadow_pde->writable = 0;
330         ((pde64_2MB_t *)guest_pde)->dirty = 0;
331       }
332     }
333     
334     // VMM Specific options
335     shadow_pde->write_through = 0;
336     shadow_pde->cache_disable = 0;
337     shadow_pde->global_page = 0;
338     //
339     
340     guest_pde->accessed = 1;
341     
342     shadow_pde->pt_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
343   } else {
344     shadow_pt = (pte64_t *)V3_VAddr((void *)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr));
345   }
346
347   // Continue processing at the next level
348   if (guest_pde->large_page == 0) {
349     if (guest_pa_to_host_va(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t *)&guest_pt) == -1) {
350       // Machine check the guest
351       PrintDebug("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
352       v3_raise_exception(info, MC_EXCEPTION);
353       return 0;
354     }
355     
356     if (handle_pte_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, guest_pt) == -1) {
357       PrintError("Error handling Page fault caused by PDE\n");
358       return -1;
359     }
360   } else {
361     if (handle_2MB_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, (pde64_2MB_t *)guest_pde) == -1) {
362       PrintError("Error handling large pagefault\n");
363       return -1;
364     } 
365   }
366
367   return 0;
368 }
369
370
371 static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
372                                           pte64_t * shadow_pt, pte64_t * guest_pt) {
373   pt_access_status_t guest_pte_access;
374   pt_access_status_t shadow_pte_access;
375   pte64_t * guest_pte = (pte64_t *)&(guest_pt[PTE64_INDEX(fault_addr)]);;
376   pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
377   addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
378   //  struct shadow_page_state * state = &(info->shdw_pg_state);
379
380   PrintDebug("Handling PTE fault\n");
381
382   struct v3_shadow_region * shdw_reg =  v3_get_shadow_region(info, guest_pa);
383
384
385
386   if ((shdw_reg == NULL) || 
387       (shdw_reg->host_type == SHDW_REGION_INVALID)) {
388     // Inject a machine check in the guest
389     PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
390     v3_raise_exception(info, MC_EXCEPTION);
391     return 0;
392   }
393
394   // Check the guest page permissions
395   guest_pte_access = v3_can_access_pte64(guest_pt, fault_addr, error_code);
396
397   // Check the shadow page permissions
398   shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
399
400   /* Was the page fault caused by the Guest's page tables? */
401   if (is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
402     PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
403                guest_pte_access, *(uint_t*)&error_code);    
404     inject_guest_pf(info, fault_addr, error_code);
405     return 0; 
406   }
407
408  
409   if (shadow_pte_access == PT_ACCESS_OK) {
410     // Inconsistent state...
411     // Guest Re-Entry will flush page tables and everything should now work
412     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
413     return 0;
414   }
415
416
417   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
418     // Page Table Entry Not Present
419     PrintDebug("guest_pa =%p\n", (void *)guest_pa);
420
421     if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) ||
422         (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
423       addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa);
424       
425       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
426       
427       shadow_pte->present = guest_pte->present;
428       shadow_pte->user_page = guest_pte->user_page;
429       
430       //set according to VMM policy
431       shadow_pte->write_through = 0;
432       shadow_pte->cache_disable = 0;
433       shadow_pte->global_page = 0;
434       //
435       
436       guest_pte->accessed = 1;
437       
438       if (guest_pte->dirty == 1) {
439         shadow_pte->writable = guest_pte->writable;
440       } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
441         shadow_pte->writable = guest_pte->writable;
442         guest_pte->dirty = 1;
443       } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {
444         shadow_pte->writable = 0;
445       }
446
447       // dirty flag has been set, check if its in the cache
448 /*       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { */
449 /*      if (error_code.write == 1) { */
450 /*        state->cached_cr3 = 0; */
451 /*        shadow_pte->writable = guest_pte->writable; */
452 /*      } else { */
453 /*        shadow_pte->writable = 0; */
454 /*      } */
455 /*       } */
456
457       // Write hooks trump all, and are set Read Only
458       if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
459         shadow_pte->writable = 0;
460       }
461
462     } else {
463       // Page fault handled by hook functions
464
465       if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
466         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
467         return -1;
468       }
469     }
470   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
471     guest_pte->dirty = 1;
472
473     if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
474       if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
475         PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
476         return -1;
477       }
478     } else {
479       PrintDebug("Shadow PTE Write Error\n");
480       shadow_pte->writable = guest_pte->writable;
481     }
482
483 /*     if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_pa)) != NULL) { */
484 /*       struct shadow_page_state * state = &(info->shdw_pg_state); */
485 /*       PrintDebug("Write operation on Guest PAge Table Page\n"); */
486 /*       state->cached_cr3 = 0; */
487 /*     } */
488
489     return 0;
490
491   } else {
492     // Inject page fault into the guest 
493     inject_guest_pf(info, fault_addr, error_code);
494     PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
495     PrintError("Manual Says to inject page fault into guest\n");
496     return -1;
497   }
498
499   return 0;
500 }
501
502
503
504 static int handle_2MB_shadow_pagefault_64(struct guest_info * info, 
505                                           addr_t fault_addr, pf_error_t error_code, 
506                                           pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde) 
507 {
508   pt_access_status_t shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
509   pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
510   addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
511   //  struct shadow_page_state * state = &(info->shdw_pg_state);
512
513   PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
514   PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
515
516   struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_fault_pa);
517
518  
519   if ((shdw_reg == NULL) || 
520       (shdw_reg->host_type == SHDW_REGION_INVALID)) {
521     // Inject a machine check in the guest
522     PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
523     v3_raise_exception(info, MC_EXCEPTION);
524     return -1;
525   }
526
527   if (shadow_pte_access == PT_ACCESS_OK) {
528     // Inconsistent state...
529     // Guest Re-Entry will flush tables and everything should now workd
530     PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
531     //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
532     return 0;
533   }
534
535   
536   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
537     // Get the guest physical address of the fault
538
539     if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || 
540         (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
541       addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa);
542
543       PrintDebug("Shadow PA=%p, ShadowPTE=%p\n", (void *)shadow_pa, (void *)shadow_pte);
544
545       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
546       PrintDebug("Test1\n");
547
548       shadow_pte->present = 1;
549
550       /* We are assuming that the PDE entry has precedence
551        * so the Shadow PDE will mirror the guest PDE settings, 
552        * and we don't have to worry about them here
553        * Allow everything
554        */
555       shadow_pte->user_page = 1;
556
557
558
559 /*       if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { */
560 /*      // Check if the entry is a page table... */
561 /*      PrintDebug("Marking page as Guest Page Table (large page)\n"); */
562 /*      shadow_pte->writable = 0; */
563 /*       } else */ if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
564         shadow_pte->writable = 0;
565       } else {
566         shadow_pte->writable = 1;
567       }
568
569       //set according to VMM policy
570       shadow_pte->write_through = 0;
571       shadow_pte->cache_disable = 0;
572       shadow_pte->global_page = 0;
573       //
574       
575     } else {
576       // Handle hooked pages as well as other special pages
577       //      if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
578
579       if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
580         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
581         return -1;
582       }
583     }
584   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
585
586     if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
587
588       if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
589         PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
590         return -1;
591       }
592     }
593
594
595 /*     if (find_pte_map(state->cached_ptes, PAGE_ADDR(guest_fault_pa)) != NULL) { */
596 /*       struct shadow_page_state * state = &(info->shdw_pg_state); */
597 /*       PrintDebug("Write operation on Guest PAge Table Page (large page)\n"); */
598 /*       state->cached_cr3 = 0; */
599 /*       shadow_pte->writable = 1; */
600 /*     } */
601
602   } else {
603     PrintError("Error in large page fault handler...\n");
604     PrintError("This case should have been handled at the top level handler\n");
605     return -1;
606   }
607
608   //  PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
609   PrintDebug("Returning from large page fault handler\n");
610   return 0;
611 }
612
613
614
615
616 static int invalidation_cb_64(struct guest_info * info, page_type_t type, 
617                               addr_t vaddr, addr_t page_ptr, addr_t page_pa, 
618                               void * private_data) {
619
620   switch (type) {
621   case PAGE_PML464:
622     {    
623       pml4e64_t * pml = (pml4e64_t *)page_ptr;
624
625       if (pml[PML4E64_INDEX(vaddr)].present == 0) {
626         return 1;
627       }
628       return 0;
629     }
630   case PAGE_PDP64:
631     {
632       pdpe64_t * pdp = (pdpe64_t *)page_ptr;
633       pdpe64_t * pdpe = &(pdp[PDPE64_INDEX(vaddr)]);
634
635       if (pdpe->present == 0) {
636         return 1;
637       }
638      
639       if (pdpe->vmm_info == V3_LARGE_PG) {
640         PrintError("1 Gigabyte pages not supported\n");
641         return -1;
642
643         pdpe->present = 0;
644         return 1;
645       }
646
647       return 0;
648     }
649   case PAGE_PD64:
650     {
651       pde64_t * pd = (pde64_t *)page_ptr;
652       pde64_t * pde = &(pd[PDE64_INDEX(vaddr)]);
653
654       if (pde->present == 0) {
655         return 1;
656       }
657       
658       if (pde->vmm_info == V3_LARGE_PG) {
659         pde->present = 0;
660         return 1;
661       }
662
663       return 0;
664     }
665   case PAGE_PT64:
666     {
667       pte64_t * pt = (pte64_t *)page_ptr;
668
669       pt[PTE64_INDEX(vaddr)].present = 0;
670
671       return 1;
672     }
673   default:
674     PrintError("Invalid Page Type\n");
675     return -1;
676
677   }
678
679   // should not get here
680   PrintError("Should not get here....\n");
681   return -1;
682 }
683
684
685 static inline int handle_shadow_invlpg_64(struct guest_info * info, addr_t vaddr) {
686   int ret =  v3_drill_host_pt_64(info, info->ctrl_regs.cr3, vaddr, invalidation_cb_64, NULL);
687   if (ret == -1) {
688     PrintError("Page table drill returned error.... \n");
689     PrintHostPageTree(info, vaddr, info->ctrl_regs.cr3);
690   }
691
692   return (ret == -1) ? -1 : 0; 
693 }