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.


f0dcd315a72ea069b750bcfaf987eae35480287b
[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 }