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.


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