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