Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


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