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.


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