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.


Actually fixed page alignment computation to be correct, moved into vmm_mem.h for...
[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 static int handle_pde_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
275                                           pde64_t * shadow_pd, pde64_t * guest_pd) {
276     pt_access_status_t guest_pde_access;
277     pt_access_status_t shadow_pde_access;
278     pde64_t * guest_pde = (pde64_t *)&(guest_pd[PDE64_INDEX(fault_addr)]);
279     pde64_t * shadow_pde = (pde64_t *)&(shadow_pd[PDE64_INDEX(fault_addr)]);
280
281     PrintDebug("Handling PDE fault\n");
282  
283     // Check the guest page permissions
284     guest_pde_access = v3_can_access_pde64(guest_pd, fault_addr, error_code);
285
286     // Check the shadow page permissions
287     shadow_pde_access = v3_can_access_pde64(shadow_pd, fault_addr, error_code);
288   
289     /* Was the page fault caused by the Guest's page tables? */
290     if (v3_is_guest_pf(guest_pde_access, shadow_pde_access) == 1) {
291         PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", 
292                    *(uint_t *)&guest_pde_access, *(uint_t *)&error_code);
293         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
294             PrintError("Could not inject guest page fault\n");
295             return -1;
296         }
297         return 0;
298     }
299
300     if (shadow_pde_access == PT_ACCESS_USER_ERROR) {
301         //
302         // PDE Entry marked non-user
303         //      
304         PrintDebug("Shadow Paging User access error (shadow_pdpe_access=0x%x, guest_pdpe_access=0x%x)\n", 
305                    shadow_pde_access, guest_pde_access);
306         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
307             PrintError("Could not inject guest page fault\n");
308             return -1;
309         }
310         return 0;
311
312     } else if ((shadow_pde_access == PT_ACCESS_WRITE_ERROR) && 
313                (guest_pde->large_page == 1)) {
314
315         ((pde64_2MB_t *)guest_pde)->dirty = 1;
316         shadow_pde->writable = guest_pde->writable;
317
318         //PrintDebug("Returning due to large page Write Error\n");
319         //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
320
321         return 0;
322     } else if ((shadow_pde_access != PT_ACCESS_NOT_PRESENT) &&
323                (shadow_pde_access != PT_ACCESS_OK)) {
324         // inject page fault in guest
325         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
326             PrintError("Could not inject guest page fault\n");
327             return -1;
328         }
329         PrintDebug("Unknown Error occurred (shadow_pde_access=%d)\n", shadow_pde_access);
330         PrintDebug("Manual Says to inject page fault into guest\n");
331         return 0;
332     }
333
334     pte64_t * shadow_pt = NULL;
335     pte64_t * guest_pt = NULL;
336
337     // get the next shadow page level, allocate if not present
338     if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
339         // Check if  we can use large pages and the guest memory is properly aligned
340         // to potentially use a large page
341         if (info->use_large_pages && guest_pde->large_page) {
342             // Check underlying physical memory map to see if a large page is viable
343             addr_t guest_pa = BASE_TO_PAGE_ADDR_2MB(((pde64_2MB_t *)guest_pde)->page_base_addr);
344             addr_t host_pa;
345             if (v3_get_max_page_size(info, guest_pa, PAGE_SIZE_2MB) < PAGE_SIZE_2MB) {
346                 PrintDebug("Underlying physical memory map doesn't allow use of a large page.\n");
347                 // Fallthrough to small pages
348             } else if ((v3_gpa_to_hpa(info, guest_pa, &host_pa) != 0)
349                        || (v3_compute_page_alignment(host_pa) < PAGE_SIZE_2MB)) {
350                 PrintDebug("Host memory alignment doesn't allow use of a large page.\n");
351                 // Fallthrough to small pages
352             } else if (handle_2MB_shadow_pagefault_pde_64(info, fault_addr, error_code, shadow_pde_access,
353                                                        (pde64_2MB_t *)shadow_pde, (pde64_2MB_t *)guest_pde) == 0) {
354                 return 0;
355             } else {
356                 PrintError("Error handling large pagefault with large page\n");
357                 return -1;
358             }
359             // Fallthrough to handle the region with small pages
360         }
361
362         struct shadow_page_data * shdw_page = create_new_shadow_pt(info);
363         shadow_pt = (pte64_t *)V3_VAddr((void *)shdw_page->page_pa);
364
365         PrintDebug("Creating new shadow PT: %p\n", shadow_pt);
366
367         shadow_pde->present = 1;
368         shadow_pde->user_page = guest_pde->user_page;
369
370
371         if (guest_pde->large_page == 0) {
372             shadow_pde->writable = guest_pde->writable;
373         } else {
374             // This large page flag is temporary until we can get a working cache....
375             ((pde64_2MB_t *)guest_pde)->vmm_info = V3_LARGE_PG;
376
377             if (error_code.write) {
378                 shadow_pde->writable = guest_pde->writable;
379                 ((pde64_2MB_t *)guest_pde)->dirty = 1;  
380             } else {
381                 shadow_pde->writable = 0;
382                 ((pde64_2MB_t *)guest_pde)->dirty = 0;
383             }
384         }
385     
386         // VMM Specific options
387         shadow_pde->write_through = guest_pde->write_through;
388         shadow_pde->cache_disable = guest_pde->cache_disable;
389         shadow_pde->global_page = guest_pde->global_page;
390         //
391     
392         guest_pde->accessed = 1;
393     
394         shadow_pde->pt_base_addr = PAGE_BASE_ADDR(shdw_page->page_pa);
395     } else {
396         shadow_pt = (pte64_t *)V3_VAddr((void *)BASE_TO_PAGE_ADDR(shadow_pde->pt_base_addr));
397     }
398
399     // Continue processing at the next level
400     if (guest_pde->large_page == 0) {
401         if (v3_gpa_to_hva(info, BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr), (addr_t *)&guest_pt) == -1) {
402             // Machine check the guest
403             PrintError("Invalid Guest PTE Address: 0x%p\n", (void *)BASE_TO_PAGE_ADDR(guest_pde->pt_base_addr));
404             v3_raise_exception(info, MC_EXCEPTION);
405             return 0;
406         }
407     
408         if (handle_pte_shadow_pagefault_64(info, fault_addr, error_code, shadow_pt, guest_pt) == -1) {
409             PrintError("Error handling Page fault caused by PDE\n");
410             return -1;
411         }
412     } else {
413         if (handle_2MB_shadow_pagefault_pte_64(info, fault_addr, error_code, shadow_pt, (pde64_2MB_t *)guest_pde) == -1) {
414             PrintError("Error handling large pagefault with small page\n");
415             return -1;
416         } 
417     }
418
419     return 0;
420 }
421
422
423 static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault_addr, pf_error_t error_code,
424                                           pte64_t * shadow_pt, pte64_t * guest_pt) {
425     pt_access_status_t guest_pte_access;
426     pt_access_status_t shadow_pte_access;
427     pte64_t * guest_pte = (pte64_t *)&(guest_pt[PTE64_INDEX(fault_addr)]);;
428     pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
429     addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
430     //  struct shadow_page_state * state = &(info->shdw_pg_state);
431
432     PrintDebug("Handling PTE fault\n");
433
434     struct v3_mem_region * shdw_reg =  v3_get_mem_region(info->vm_info, info->cpu_id, guest_pa);
435
436
437
438     if (shdw_reg == NULL) {
439         // Inject a machine check in the guest
440         PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa);
441         v3_raise_exception(info, MC_EXCEPTION);
442         return 0;
443     }
444
445     // Check the guest page permissions
446     guest_pte_access = v3_can_access_pte64(guest_pt, fault_addr, error_code);
447
448     // Check the shadow page permissions
449     shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
450
451     /* Was the page fault caused by the Guest's page tables? */
452     if (v3_is_guest_pf(guest_pte_access, shadow_pte_access) == 1) {
453
454         PrintDebug("Access error injecting pf to guest (guest access error=%d) (pf error code=%d)\n", 
455                    guest_pte_access, *(uint_t*)&error_code);    
456
457         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
458             PrintError("Could not inject guest page fault\n");
459             return -1;
460         }
461
462         return 0; 
463     }
464
465  
466     if (shadow_pte_access == PT_ACCESS_OK) {
467         // Inconsistent state...
468         // Guest Re-Entry will flush page tables and everything should now work
469         PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
470         return 0;
471     }
472
473
474     if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
475         // Page Table Entry Not Present
476         PrintDebug("guest_pa =%p\n", (void *)guest_pa);
477
478         if ((shdw_reg->flags.alloced == 1) ||
479             (shdw_reg->flags.read == 1)) {
480             addr_t shadow_pa = 0;
481
482             if (v3_gpa_to_hpa(info, guest_pa, &shadow_pa) == -1) {
483                 PrintError("could not translate page fault address (%p)\n", (void *)guest_pa);
484                 return -1;
485             }
486
487             shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
488       
489             shadow_pte->present = guest_pte->present;
490             shadow_pte->user_page = guest_pte->user_page;
491       
492             //set according to VMM policy
493             shadow_pte->write_through = guest_pte->write_through;
494             shadow_pte->cache_disable = guest_pte->cache_disable;
495             shadow_pte->global_page = guest_pte->global_page;
496             //
497       
498             guest_pte->accessed = 1;
499       
500             if (guest_pte->dirty == 1) {
501                 shadow_pte->writable = guest_pte->writable;
502             } else if ((guest_pte->dirty == 0) && (error_code.write == 1)) {
503                 shadow_pte->writable = guest_pte->writable;
504                 guest_pte->dirty = 1;
505             } else if ((guest_pte->dirty == 0) && (error_code.write == 0)) {
506                 shadow_pte->writable = 0;
507             }
508
509
510             // Write hooks trump all, and are set Read Only
511             if (shdw_reg->flags.write == 0) {
512                 shadow_pte->writable = 0;
513             }
514
515         } else {
516             // Pass to unhandled call back
517             if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
518                 PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
519                 return -1;
520             }
521         }
522     } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
523         guest_pte->dirty = 1;
524
525
526         if (shdw_reg->flags.write == 1) {
527             PrintDebug("Shadow PTE Write Error\n");
528             shadow_pte->writable = guest_pte->writable;
529         } else {
530             if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
531                 PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
532                 return -1;
533             }
534         }
535
536
537
538         return 0;
539
540     } else {
541         // Inject page fault into the guest     
542         if (v3_inject_guest_pf(info, fault_addr, error_code) == -1) {
543             PrintError("Could not inject guest page fault\n");
544             return -1;
545         }
546         PrintError("PTE Page fault fell through... Not sure if this should ever happen\n");
547         PrintError("Manual Says to inject page fault into guest\n");
548         return -1;
549     }
550
551     return 0;
552 }
553
554
555 static int handle_2MB_shadow_pagefault_pde_64(struct guest_info * info, 
556                                               addr_t fault_addr, pf_error_t error_code, 
557                                               pt_access_status_t shadow_pde_access,
558                                               pde64_2MB_t * large_shadow_pde, pde64_2MB_t * large_guest_pde) 
559 {
560     addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
561     //  struct shadow_page_state * state = &(info->shdw_pg_state);
562
563     PrintDebug("Handling 2MB fault with large page (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
564     PrintDebug("LargeShadowPDE=%p, LargeGuestPDE=%p\n", large_shadow_pde, large_guest_pde);
565
566     struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
567  
568     if (shdw_reg == NULL) {
569         // Inject a machine check in the guest
570         PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
571         v3_raise_exception(info, MC_EXCEPTION);
572         return 0;
573     }
574
575     if (shadow_pde_access == PT_ACCESS_OK) {
576         // Inconsistent state...
577         // Guest Re-Entry will flush tables and everything should now workd
578         PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
579         //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
580         return 0;
581     }
582
583   
584     if (shadow_pde_access == PT_ACCESS_NOT_PRESENT) {
585         // Get the guest physical address of the fault
586
587         if ((shdw_reg->flags.alloced == 1) || 
588             (shdw_reg->flags.read == 1)) {
589             addr_t shadow_pa = 0;
590
591             if (v3_gpa_to_hpa(info, guest_fault_pa, &shadow_pa) == -1) {
592                 PrintError("could not translate page fault address (%p)\n", (void *)guest_fault_pa);
593                 return -1;
594             }
595
596             large_guest_pde->vmm_info = V3_LARGE_PG; /* For invalidations */
597             large_shadow_pde->page_base_addr = PAGE_BASE_ADDR_2MB(shadow_pa);
598             large_shadow_pde->large_page = 1;
599             large_shadow_pde->present = 1;
600             large_shadow_pde->user_page = 1;
601
602             if (shdw_reg->flags.write == 0) {
603                 large_shadow_pde->writable = 0;
604             } else {
605                 large_shadow_pde->writable = 1;
606             }
607
608             //set according to VMM policy
609             large_shadow_pde->write_through = large_guest_pde->write_through;
610             large_shadow_pde->cache_disable = large_guest_pde->cache_disable;
611             large_shadow_pde->global_page = large_guest_pde->global_page;
612             //
613       
614         } else {
615             if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
616                 PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
617                 return -1;
618             }
619         }
620     } else if (shadow_pde_access == PT_ACCESS_WRITE_ERROR) {
621         if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
622             PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
623             return -1;
624         }
625     } else {
626         PrintError("Error in large page fault handler...\n");
627         PrintError("This case should have been handled at the top level handler\n");
628         return -1;
629     }
630
631     //  PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
632     PrintDebug("Returning from large page->large page fault handler\n");
633     return 0;
634 }
635
636 static int handle_2MB_shadow_pagefault_pte_64(struct guest_info * info, 
637                                               addr_t fault_addr, pf_error_t error_code, 
638                                               pte64_t * shadow_pt, pde64_2MB_t * large_guest_pde) 
639 {
640     pt_access_status_t shadow_pte_access = v3_can_access_pte64(shadow_pt, fault_addr, error_code);
641     pte64_t * shadow_pte = (pte64_t *)&(shadow_pt[PTE64_INDEX(fault_addr)]);
642     addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_2MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_2MB(fault_addr);
643     //  struct shadow_page_state * state = &(info->shdw_pg_state);
644
645     PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code);
646     PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde);
647
648     struct v3_mem_region * shdw_reg = v3_get_mem_region(info->vm_info, info->cpu_id, guest_fault_pa);
649
650  
651     if (shdw_reg == NULL) {
652         // Inject a machine check in the guest
653         PrintError("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa);
654         v3_raise_exception(info, MC_EXCEPTION);
655         return 0;
656     }
657
658     if (shadow_pte_access == PT_ACCESS_OK) {
659         // Inconsistent state...
660         // Guest Re-Entry will flush tables and everything should now workd
661         PrintDebug("Inconsistent state... Guest re-entry should flush tlb\n");
662         //PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
663         return 0;
664     }
665
666   
667     if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
668         // Get the guest physical address of the fault
669
670         if ((shdw_reg->flags.alloced == 1) || 
671             (shdw_reg->flags.read == 1)) {
672             addr_t shadow_pa = 0;
673
674             if (v3_gpa_to_hpa(info, guest_fault_pa, &shadow_pa) == -1) {
675                 PrintError("could not translate page fault address (%p)\n", (void *)guest_fault_pa);
676                 return -1;
677             }
678
679             shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
680
681             shadow_pte->present = 1;
682
683             /* We are assuming that the PDE entry has precedence
684              * so the Shadow PDE will mirror the guest PDE settings, 
685              * and we don't have to worry about them here
686              * Allow everything
687              */
688             shadow_pte->user_page = 1;
689
690             if (shdw_reg->flags.write == 0) {
691                 shadow_pte->writable = 0;
692             } else {
693                 shadow_pte->writable = 1;
694             }
695
696             //set according to VMM policy
697             shadow_pte->write_through = large_guest_pde->write_through;
698             shadow_pte->cache_disable = large_guest_pde->cache_disable;
699             shadow_pte->global_page = large_guest_pde->global_page;
700             //
701       
702         } else {
703             if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
704                 PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
705                 return -1;
706             }
707         }
708     } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
709         if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
710             PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
711             return -1;
712         }
713     } else {
714         PrintError("Error in large page fault handler...\n");
715         PrintError("This case should have been handled at the top level handler\n");
716         return -1;
717     }
718
719     //  PrintHostPageTree(info, fault_addr, info->ctrl_regs.cr3);
720     PrintDebug("Returning from large page->small page fault handler\n");
721     return 0;
722 }
723
724
725
726
727 static int invalidation_cb_64(struct guest_info * info, page_type_t type, 
728                               addr_t vaddr, addr_t page_ptr, addr_t page_pa, 
729                               void * private_data) {
730
731     switch (type) {
732         case PAGE_PML464:
733             {    
734                 pml4e64_t * pml = (pml4e64_t *)page_ptr;
735
736                 if (pml[PML4E64_INDEX(vaddr)].present == 0) {
737                     return 1;
738                 }
739                 return 0;
740             }
741         case PAGE_PDP64:
742             {
743                 pdpe64_t * pdp = (pdpe64_t *)page_ptr;
744                 pdpe64_t * pdpe = &(pdp[PDPE64_INDEX(vaddr)]);
745
746                 if (pdpe->present == 0) {
747                     return 1;
748                 }
749      
750                 if (pdpe->vmm_info == V3_LARGE_PG) {
751                     PrintError("1 Gigabyte pages not supported\n");
752                     return -1;
753
754                     pdpe->present = 0;
755                     return 1;
756                 }
757
758                 return 0;
759             }
760         case PAGE_PD64:
761             {
762                 pde64_t * pd = (pde64_t *)page_ptr;
763                 pde64_t * pde = &(pd[PDE64_INDEX(vaddr)]);
764
765                 if (pde->present == 0) {
766                     return 1;
767                 }
768       
769                 if (pde->vmm_info == V3_LARGE_PG) {
770                     pde->present = 0;
771                     return 1;
772                 }
773
774                 return 0;
775             }
776         case PAGE_PT64:
777             {
778                 pte64_t * pt = (pte64_t *)page_ptr;
779
780                 pt[PTE64_INDEX(vaddr)].present = 0;
781
782                 return 1;
783             }
784         default:
785             PrintError("Invalid Page Type\n");
786             return -1;
787
788     }
789
790     // should not get here
791     PrintError("Should not get here....\n");
792     return -1;
793 }
794
795
796 static inline int handle_shadow_invlpg_64(struct guest_info * info, addr_t vaddr) {
797     PrintDebug("INVLPG64 - %p\n",(void*)vaddr);
798
799     int ret =  v3_drill_host_pt_64(info, info->ctrl_regs.cr3, vaddr, invalidation_cb_64, NULL);
800     if (ret == -1) {
801         PrintError("Page table drill returned error.... \n");
802         PrintHostPageTree(info, vaddr, info->ctrl_regs.cr3);
803     }
804
805     return (ret == -1) ? -1 : 0; 
806 }