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.


memory lookup refactorization
[palacios.git] / palacios / src / palacios / mmu / vmm_shdw_pg_tlb_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 (v3_gpa_to_hva(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 (v3_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 (v3_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 (v3_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 (v3_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 (v3_gpa_to_hva(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 (v3_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 (v3_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 (v3_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 (v3_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 (v3_gpa_to_hva(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 (v3_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 (v3_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 (v3_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 (v3_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 (v3_gpa_to_hva(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_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, 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 (v3_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 (v3_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->flags.alloced == 1) ||
456             (shdw_reg->flags.read == 1)) {
457             addr_t shadow_pa = 0;
458
459             if (v3_gpa_to_hpa(info, guest_pa, &shadow_pa) == -1) {
460                 PrintError("could not translate page fault address (%p)\n", (void *)guest_pa);
461                 return -1;
462             }
463
464             shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
465       
466             shadow_pte->present = guest_pte->present;
467             shadow_pte->user_page = guest_pte->user_page;
468       
469             //set according to VMM policy
470             shadow_pte->write_through = guest_pte->write_through;
471             shadow_pte->cache_disable = guest_pte->cache_disable;
472             shadow_pte->global_page = guest_pte->global_page;
473             //
474       
475             guest_pte->accessed = 1;
476       
477             if (guest_pte->dirty == 1) {
478                 shadow_pte->writable = guest_pte->writable;
479             } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
480                 shadow_pte->writable = guest_pte->writable;
481                 guest_pte->dirty = 1;
482             } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {
483                 shadow_pte->writable = 0;
484             }
485
486
487             // Write hooks trump all, and are set Read Only
488             if (shdw_reg->flags.write == 0) {
489                 shadow_pte->writable = 0;
490             }
491
492         } else {
493             // Pass to unhandled call back
494
495             if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
496                 PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
497                 return -1;
498             }
499         }
500     } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
501         guest_pte->dirty = 1;
502
503
504         if (shdw_reg->flags.write == 1) {
505             PrintDebug("Shadow PTE Write Error\n");
506             shadow_pte->writable = guest_pte->writable;
507         } else {
508             if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
509                 PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
510                 return -1;
511             }
512         }
513
514
515
516         return 0;
517
518     } else {
519         // Inject page fault into the guest     
520         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
521             PrintError("Could not inject guest page fault\n");
522             return -1;
523         }
524         PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
525         PrintError("Manual Says to inject page fault into guest\n");
526         return -1;
527     }
528
529     return 0;
530 }
531
532
533
534 static int handle_2MB_shadow_pagefault_64(struct guest_info * info, 
535                                           addr_t fault_addr, pf_error_t error_code, 
536                                           pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde) 
537 {
538     pt_access_status_t shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
539     pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
540     addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
541     //  struct shadow_page_state * state = &(info->shdw_pg_state);
542
543     PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
544     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
545
546     struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
547
548  
549     if (shdw_reg == NULL) {
550         // Inject a machine check in the guest
551         PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
552         v3_raise_exception(info, MC_EXCEPTION);
553         return 0;
554     }
555
556     if (shadow_pte_access == PT_ACCESS_OK) {
557         // Inconsistent state...
558         // Guest Re-Entry will flush tables and everything should now workd
559         PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
560         //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
561         return 0;
562     }
563
564   
565     if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
566         // Get the guest physical address of the fault
567
568         if ((shdw_reg->flags.alloced == 1) || 
569             (shdw_reg->flags.read == 1)) {
570             addr_t shadow_pa = 0;
571
572             if (v3_gpa_to_hpa(info, guest_fault_pa, &shadow_pa) == -1) {
573                 PrintError("could not translate page fault address (%p)\n", (void *)guest_fault_pa);
574                 return -1;
575             }
576
577             shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
578
579             shadow_pte->present = 1;
580
581             /* We are assuming that the PDE entry has precedence
582              * so the Shadow PDE will mirror the guest PDE settings, 
583              * and we don't have to worry about them here
584              * Allow everything
585              */
586             shadow_pte->user_page = 1;
587
588             if (shdw_reg->flags.write == 0) {
589                 shadow_pte->writable = 0;
590             } else {
591                 shadow_pte->writable = 1;
592             }
593
594             //set according to VMM policy
595             shadow_pte->write_through = large_guest_pde->write_through;
596             shadow_pte->cache_disable = large_guest_pde->cache_disable;
597             shadow_pte->global_page = large_guest_pde->global_page;
598             //
599       
600         } else {
601             if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
602                 PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
603                 return -1;
604             }
605         }
606     } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
607         if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
608             PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
609             return -1;
610         }
611     } else {
612         PrintError("Error in large page fault handler...\n");
613         PrintError("This case should have been handled at the top level handler\n");
614         return -1;
615     }
616
617     //  PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
618     PrintDebug("Returning from large page fault handler\n");
619     return 0;
620 }
621
622
623
624
625 static int invalidation_cb_64(struct guest_info * info, page_type_t type, 
626                               addr_t vaddr, addr_t page_ptr, addr_t page_pa, 
627                               void * private_data) {
628
629     switch (type) {
630         case PAGE_PML464:
631             {    
632                 pml4e64_t * pml = (pml4e64_t *)page_ptr;
633
634                 if (pml[PML4E64_INDEX(vaddr)].present == 0) {
635                     return 1;
636                 }
637                 return 0;
638             }
639         case PAGE_PDP64:
640             {
641                 pdpe64_t * pdp = (pdpe64_t *)page_ptr;
642                 pdpe64_t * pdpe = &(pdp[PDPE64_INDEX(vaddr)]);
643
644                 if (pdpe->present == 0) {
645                     return 1;
646                 }
647      
648                 if (pdpe->vmm_info == V3_LARGE_PG) {
649                     PrintError("1 Gigabyte pages not supported\n");
650                     return -1;
651
652                     pdpe->present = 0;
653                     return 1;
654                 }
655
656                 return 0;
657             }
658         case PAGE_PD64:
659             {
660                 pde64_t * pd = (pde64_t *)page_ptr;
661                 pde64_t * pde = &(pd[PDE64_INDEX(vaddr)]);
662
663                 if (pde->present == 0) {
664                     return 1;
665                 }
666       
667                 if (pde->vmm_info == V3_LARGE_PG) {
668                     pde->present = 0;
669                     return 1;
670                 }
671
672                 return 0;
673             }
674         case PAGE_PT64:
675             {
676                 pte64_t * pt = (pte64_t *)page_ptr;
677
678                 pt[PTE64_INDEX(vaddr)].present = 0;
679
680                 return 1;
681             }
682         default:
683             PrintError("Invalid Page Type\n");
684             return -1;
685
686     }
687
688     // should not get here
689     PrintError("Should not get here....\n");
690     return -1;
691 }
692
693
694 static inline int handle_shadow_invlpg_64(struct guest_info * info, addr_t vaddr) {
695     PrintDebug("INVLPG64 - %p\n",(void*)vaddr);
696
697     int ret =  v3_drill_host_pt_64(info, info->ctrl_regs.cr3, vaddr, invalidation_cb_64, NULL);
698     if (ret == -1) {
699         PrintError("Page table drill returned error.... \n");
700         PrintHostPageTree(info, vaddr, info->ctrl_regs.cr3);
701     }
702
703     return (ret == -1) ? -1 : 0; 
704 }