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.


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