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.


f63ddf18a44c7bdc2ea43c83a8ef12b67ace9e50
[palacios.git] / palacios / src / palacios / vmm_paging.c
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 #include <palacios/vmm_paging.h>
21
22 #include <palacios/vmm.h>
23
24 #include <palacios/vm_guest_mem.h>
25
26
27
28 #define USE_VMM_PAGING_DEBUG
29 // All of the debug functions defined in vmm_paging.h are implemented in this file
30 #include "vmm_paging_debug.h"
31 #undef USE_VMM_PAGING_DEBUG
32
33
34 void delete_page_tables_32(pde32_t * pde) {
35   int i;
36
37   if (pde == NULL) { 
38     return;
39   }
40
41   for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
42     if (pde[i].present) {
43       // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
44       PrintDebug("PTE base addr %x \n", pde[i].pt_base_addr);
45       pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
46
47       PrintDebug("Deleting PTE %d (%p)\n", i, pte);
48       V3_FreePage(pte);
49     }
50   }
51
52   PrintDebug("Deleting PDE (%p)\n", pde);
53   V3_FreePage(V3_PAddr(pde));
54 }
55
56 void delete_page_tables_32PAE(pdpe32pae_t * pdpe) { 
57   PrintError("Unimplemented function\n");
58 }
59
60 void delete_page_tables_64(pml4e64_t * pml4) {
61   PrintError("Unimplemented function\n");
62 }
63
64
65 int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
66   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
67   pde32_t * guest_pde = 0;
68   addr_t guest_pte_pa = 0;
69
70   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
71     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
72                (void *)guest_pde_pa);
73     return -1;
74   }
75   
76   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
77   case PT_ENTRY_NOT_PRESENT:
78     *paddr = 0;  
79     return -1;
80   case PT_ENTRY_LARGE_PAGE:
81     *paddr = guest_pte_pa;
82     return 0;
83   case PT_ENTRY_PAGE:
84     {
85       pte32_t * guest_pte = NULL;
86
87       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
88         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
89                    (void *)guest_pte_pa);
90         return -1;
91       }
92
93       if (pte32_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
94         return -1;
95       }
96
97       return 0;
98     }
99   }
100
101   // should never get here
102   return -1;
103 }
104
105
106 int v3_translate_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
107   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
108   pdpe32pae_t * guest_pdpe = 0;
109   addr_t guest_pde_pa = 0;
110
111   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
112     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
113                (void *)guest_pdpe_pa);
114     return -1;
115   }
116
117   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
118     {
119     case PT_ENTRY_NOT_PRESENT:
120       *paddr = 0;
121       return -1;
122     case PT_ENTRY_PAGE:
123       {
124         pde32pae_t * guest_pde = NULL;
125         addr_t guest_pte_pa = 0;
126         
127         if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
128           PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
129                      (void *)guest_pde_pa);
130           return -1;
131         }
132         
133         switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
134           {
135           case PT_ENTRY_NOT_PRESENT:
136             *paddr = 0;
137             return -1;
138           case PT_ENTRY_LARGE_PAGE:
139             *paddr = guest_pte_pa;
140             return 0;
141           case PT_ENTRY_PAGE:
142             {
143               pte32pae_t * guest_pte = NULL;
144               
145               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
146                 PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
147                            (void *)guest_pte_pa);
148                 return -1;
149               }
150
151               if (pte32pae_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
152                 return -1;
153               }
154
155               return 0;
156             }
157           }
158       }
159     default:
160       return -1;
161     }
162
163   // should never get here
164   return -1;
165 }
166
167 int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) {
168   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
169   pml4e64_t * guest_pmle = 0;
170   addr_t guest_pdpe_pa = 0;
171
172   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
173     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
174                (void *)guest_pml4_pa);
175     return -1;
176   }
177   
178   switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
179   case PT_ENTRY_NOT_PRESENT:
180     *paddr = 0;
181     return -1;
182   case PT_ENTRY_PAGE:
183     {
184       pdpe64_t * guest_pdp = NULL;
185       addr_t guest_pde_pa = 0;
186
187       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
188         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
189                    (void *)guest_pdpe_pa);
190         return -1;
191       }
192
193       switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
194       case PT_ENTRY_NOT_PRESENT:
195         *paddr = 0;
196         return -1;
197       case PT_ENTRY_LARGE_PAGE:
198         *paddr = 0;
199         PrintError("1 Gigabyte Pages not supported\n");
200         return -1;
201       case PT_ENTRY_PAGE:
202         {
203           pde64_t * guest_pde = NULL;
204           addr_t guest_pte_pa = 0;
205
206           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
207             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
208                        (void *)guest_pde_pa);
209             return -1;
210           }
211
212           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
213           case PT_ENTRY_NOT_PRESENT:
214             *paddr = 0;
215             return -1;
216           case PT_ENTRY_LARGE_PAGE:
217             *paddr = guest_pte_pa;
218             return 0;
219           case PT_ENTRY_PAGE:
220             {
221               pte64_t * guest_pte = NULL;
222               
223               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
224                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
225                            (void *)guest_pte_pa);
226                 return -1;
227               }
228                 
229               if (pte64_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
230                 return -1;
231               }
232
233               return 0;
234             }
235           }
236         }
237       }
238     }
239   default:
240     return -1;
241   }
242
243   // should never get here
244   return -1;
245 }
246
247
248
249 int v3_translate_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
250   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
251   pte32_t * host_pte = 0;
252     
253   switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
254   case PT_ENTRY_NOT_PRESENT:
255     *paddr = 0;
256     return -1;
257   case PT_ENTRY_LARGE_PAGE:
258     *paddr = (addr_t)host_pte;
259     return 0;
260   case PT_ENTRY_PAGE:
261     if (pte32_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
262       return -1;
263     }
264     return 0;
265   }
266   
267   // should never get here
268   return -1;
269 }
270
271
272 int v3_translate_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
273   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
274   pde32pae_t * host_pde = NULL;
275   pte32pae_t * host_pte = NULL;
276
277   switch (pdpe32pae_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) {
278   case PT_ENTRY_NOT_PRESENT:
279     *paddr = 0;
280     return -1;
281   case PT_ENTRY_PAGE:
282     switch (pde32pae_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) {
283     case PT_ENTRY_NOT_PRESENT:
284       *paddr = 0;
285       return -1;
286     case PT_ENTRY_LARGE_PAGE:
287       *paddr = (addr_t)host_pte;
288       return 0;
289     case PT_ENTRY_PAGE:
290       if (pte32pae_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
291         return -1;
292       }
293       return 0;
294     }
295   default:
296     return -1;
297   }
298
299   // should never get here
300   return -1;
301 }
302
303
304 int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) {
305   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
306   pdpe64_t * host_pdpe = NULL;
307   pde64_t * host_pde = NULL;
308   pte64_t * host_pte = NULL;
309
310   switch(pml4e64_lookup(host_pmle, vaddr, (addr_t *)&host_pdpe)) {
311   case PT_ENTRY_NOT_PRESENT:
312     *paddr = 0;
313     return -1;
314   case PT_ENTRY_PAGE:
315     switch(pdpe64_lookup(V3_VAddr(host_pdpe), vaddr, (addr_t *)&host_pde)) {
316     case PT_ENTRY_NOT_PRESENT:
317       *paddr = 0;
318       return -1;
319     case PT_ENTRY_LARGE_PAGE:
320       *paddr = 0;
321       PrintError("1 Gigabyte Pages not supported\n");
322       return -1;
323     case PT_ENTRY_PAGE:
324       switch (pde64_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) {
325       case PT_ENTRY_NOT_PRESENT:
326         *paddr = 0;
327         return -1;
328       case PT_ENTRY_LARGE_PAGE:
329         *paddr = (addr_t)host_pte;
330         return 0;
331       case PT_ENTRY_PAGE:
332         if (pte64_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) {
333           return -1;
334         }
335         return 0;
336       }
337     }
338   default:
339     return -1;
340   }
341
342   // should never get here
343   return -1;
344 }
345
346
347
348
349
350 /*
351  * PAGE TABLE LOOKUP FUNCTIONS
352  *
353  *
354  * The value of entry is a return type:
355  * Page not present: *entry = 0
356  * Large Page: *entry = translated physical address (byte granularity)
357  * PTE entry: *entry is the address of the PTE Page
358  */
359
360 /**
361  * 
362  *  32 bit Page Table lookup functions
363  *
364  **/
365
366 pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) {
367   pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]);
368
369   if (!pde_entry->present) {
370     *entry = 0;
371     return PT_ENTRY_NOT_PRESENT;
372   } else if (pde_entry->large_page) {
373     pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
374
375     *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
376     *entry += PAGE_OFFSET_4MB(addr);
377
378     return PT_ENTRY_LARGE_PAGE;
379   } else {
380     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
381     return PT_ENTRY_PAGE;
382   }
383 }
384
385
386
387 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
388  */
389 pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) {
390   pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]);
391
392   if (!pte_entry->present) {
393     *entry = 0;
394     //    PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
395     return PT_ENTRY_NOT_PRESENT;
396   } else {
397     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
398     return PT_ENTRY_PAGE;
399   }
400
401 }
402
403
404
405 /**
406  * 
407  *  32 bit PAE Page Table lookup functions
408  *
409  **/
410 pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) {
411   pdpe32pae_t * pdpe_entry = &(pdp[PDPE32PAE_INDEX(addr)]);
412   
413   if (!pdpe_entry->present) {
414     *entry = 0;
415     return PT_ENTRY_NOT_PRESENT;
416   } else {
417     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
418     return PT_ENTRY_PAGE;
419   }
420 }
421
422 pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) {
423   pde32pae_t * pde_entry = &(pd[PDE32PAE_INDEX(addr)]);
424
425   if (!pde_entry->present) {
426     *entry = 0;
427     return PT_ENTRY_NOT_PRESENT;
428   } else if (pde_entry->large_page) {
429     pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry;
430
431     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
432     *entry += PAGE_OFFSET_2MB(addr);
433
434     return PT_ENTRY_LARGE_PAGE;
435   } else {
436     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
437     return PT_ENTRY_PAGE;
438   }
439 }
440
441 pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) {
442   pte32pae_t * pte_entry = &(pt[PTE32PAE_INDEX(addr)]);
443
444   if (!pte_entry->present) {
445     *entry = 0;
446     return PT_ENTRY_NOT_PRESENT;
447   } else {
448     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
449     return PT_ENTRY_PAGE;
450   }
451 }
452
453
454
455 /**
456  * 
457  *  64 bit Page Table lookup functions
458  *
459  **/
460 pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) {
461   pml4e64_t * pml_entry = &(pml[PML4E64_INDEX(addr)]);
462
463   if (!pml_entry->present) {
464     *entry = 0;
465     return PT_ENTRY_NOT_PRESENT;
466   } else {
467     *entry = BASE_TO_PAGE_ADDR(pml_entry->pdp_base_addr);
468     return PT_ENTRY_PAGE;
469   }
470 }
471
472 pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) {
473   pdpe64_t * pdpe_entry = &(pdp[PDPE64_INDEX(addr)]);
474   
475   if (!pdpe_entry->present) {
476     *entry = 0;
477     return PT_ENTRY_NOT_PRESENT;
478   } else if (pdpe_entry->large_page) {
479     PrintError("1 Gigabyte pages not supported\n");
480     V3_ASSERT(0);
481     return -1;
482   } else {
483     *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
484     return PT_ENTRY_PAGE;
485   }
486 }
487
488 pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) {
489   pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]);
490
491   if (!pde_entry->present) {
492     *entry = 0;
493     return PT_ENTRY_NOT_PRESENT;
494   } else if (pde_entry->large_page) {
495     pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
496
497     *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
498     *entry += PAGE_OFFSET_2MB(addr);
499
500     return PT_ENTRY_LARGE_PAGE;
501   } else {
502     *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
503     return PT_ENTRY_PAGE;
504   }
505 }
506
507 pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) {
508   pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]);
509
510   if (!pte_entry->present) {
511     *entry = 0;
512     return PT_ENTRY_NOT_PRESENT;
513   } else {
514     *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr);
515     return PT_ENTRY_PAGE;
516   }
517 }
518
519
520
521
522
523
524
525
526 /* 
527  *
528  * Page Table Access Checks
529  *
530  */
531
532
533
534
535
536
537 int v3_check_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
538   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
539   pte32_t * host_pte = 0;
540
541   int pt_level = 2;
542
543   // Check accessibility of PDE
544   *access_status = v3_can_access_pde32(host_pde, vaddr, access_type);
545   
546   if (*access_status != PT_ACCESS_OK) {
547     return pt_level;
548   } 
549
550   pt_level--;
551   
552   switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) {
553   case PT_ENTRY_LARGE_PAGE:
554     return 0;
555   case PT_ENTRY_PAGE:
556     *access_status = v3_can_access_pte32(V3_VAddr(host_pte), vaddr, access_type);
557     
558     if (*access_status != PT_ACCESS_OK) {
559       return pt_level;
560     }
561
562     return 0;
563   default: 
564     return -1;
565   }
566   
567   // should never get here
568   return -1;
569 }
570
571 int v3_check_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
572   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
573   pde32pae_t * host_pde = NULL;
574   pte32pae_t * host_pte = NULL;
575   int pt_level = 3;
576
577   *access_status = v3_can_access_pdpe32pae(host_pdpe, vaddr, access_type);
578
579   if (*access_status != PT_ACCESS_OK) {
580     return pt_level;
581   }
582
583   pt_level--;
584
585   switch (pdpe32pae_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) {
586   case PT_ENTRY_PAGE:
587     *access_status = v3_can_access_pde32pae(V3_VAddr(host_pde), vaddr, access_type);
588
589     if (*access_status != PT_ACCESS_OK) {
590       return pt_level;
591     }
592
593     pt_level--;
594
595     switch (pde32pae_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) {
596     case PT_ENTRY_LARGE_PAGE:
597       return 0;
598     case PT_ENTRY_PAGE:
599       *access_status = v3_can_access_pte32pae(V3_VAddr(host_pte), vaddr, access_type);
600
601       if (*access_status != PT_ACCESS_OK) {
602         return pt_level;
603       }
604
605       return 0;
606     default:
607       return -1;
608     }
609   default:
610     return -1;
611   }
612
613   // should never get here
614   return -1;
615 }
616
617
618
619 int v3_check_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) {
620   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
621   pdpe64_t * host_pdpe = NULL;
622   pde64_t * host_pde = NULL;
623   pte64_t * host_pte = NULL;
624   int pt_level = 4;
625
626
627   *access_status = v3_can_access_pml4e64(host_pmle, vaddr, access_type);
628
629   if (*access_status != PT_ACCESS_OK) {
630     return pt_level;
631   }
632
633   pt_level--;
634
635   switch(pml4e64_lookup(host_pmle, vaddr, (addr_t *)&host_pdpe)) {
636   case PT_ENTRY_PAGE:
637     *access_status = v3_can_access_pdpe64(V3_VAddr(host_pdpe), vaddr, access_type);
638
639     if (*access_status != PT_ACCESS_OK) {
640       return pt_level;
641     }
642
643     pt_level--;
644
645     switch(pdpe64_lookup(V3_VAddr(host_pdpe), vaddr, (addr_t *)&host_pde)) {
646     case PT_ENTRY_LARGE_PAGE:
647       return 0;
648     case PT_ENTRY_PAGE:
649       *access_status = v3_can_access_pde64(V3_VAddr(host_pde), vaddr, access_type);
650
651       if (*access_status != PT_ACCESS_OK) {
652         return pt_level;
653       }
654
655       pt_level--;
656
657       switch (pde64_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) {
658       case PT_ENTRY_LARGE_PAGE:
659         return 0;
660       case PT_ENTRY_PAGE:
661         *access_status = v3_can_access_pte64(V3_VAddr(host_pte), vaddr, access_type);
662
663         if (*access_status != PT_ACCESS_OK) {
664           return pt_level;
665         }
666
667         return 0;
668       default:
669         return -1;
670       }
671     default:
672       return -1;
673     }
674   default:
675     return -1;
676   }
677
678   // should never get here
679   return -1;
680 }
681
682
683
684
685
686 int v3_check_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
687                          pf_error_t access_type, pt_access_status_t * access_status) {
688   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
689   pde32_t * guest_pde = NULL;
690   addr_t guest_pte_pa = 0;
691   int pt_level = 2;
692
693   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
694     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
695                (void *)guest_pde_pa);
696     return -1;
697   }
698   
699
700   // Check accessibility of PDE
701   *access_status = v3_can_access_pde32(guest_pde, vaddr, access_type);
702   
703   if (*access_status != PT_ACCESS_OK) {
704     return pt_level;
705   } 
706
707   pt_level--;
708   
709   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
710   case PT_ENTRY_LARGE_PAGE:
711     return 0;
712   case PT_ENTRY_PAGE:
713     {
714       pte32_t * guest_pte = NULL;
715
716       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
717         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
718                    (void *)guest_pte_pa);
719         return -1;
720       }
721
722       *access_status = v3_can_access_pte32(guest_pte, vaddr, access_type);
723       
724       if (*access_status != PT_ACCESS_OK) {
725         return pt_level;
726       }
727       return 0;
728     }
729   default: 
730     return -1;
731   }
732   
733   // should never get here
734   return -1;
735 }
736
737
738
739
740
741 int v3_check_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
742                             pf_error_t access_type, pt_access_status_t * access_status) {
743   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
744   pdpe32pae_t * guest_pdpe = NULL;
745   addr_t guest_pde_pa = 0;
746   int pt_level = 3;
747
748   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
749     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
750                (void *)guest_pdpe_pa);
751     return -1;
752   }
753
754   *access_status = v3_can_access_pdpe32pae(guest_pdpe, vaddr, access_type);
755
756   if (*access_status != PT_ACCESS_OK) {
757     return pt_level;
758   }
759
760   pt_level--;
761
762   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) {
763   case PT_ENTRY_PAGE:
764     {
765       pde32pae_t * guest_pde = NULL;
766       addr_t guest_pte_pa = 0;
767         
768       if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
769         PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
770                    (void *)guest_pde_pa);
771         return -1;
772       }
773       
774       *access_status = v3_can_access_pde32pae(guest_pde, vaddr, access_type);
775       
776       if (*access_status != PT_ACCESS_OK) {
777         return pt_level;
778       }
779       
780       pt_level--;
781       
782       switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) {
783       case PT_ENTRY_LARGE_PAGE:
784         return 0;
785       case PT_ENTRY_PAGE:
786         {
787           pte32pae_t * guest_pte = NULL;
788
789           if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
790             PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
791                        (void *)guest_pte_pa);
792             return -1;
793           }
794
795           *access_status = v3_can_access_pte32pae(guest_pte, vaddr, access_type);
796         
797           if (*access_status != PT_ACCESS_OK) {
798             return pt_level;
799           }
800         
801           return 0;
802         }
803       default:
804         return -1;
805       }
806     }
807   default:
808     return -1;
809   }
810
811   // should never get here
812   return -1;
813 }
814
815
816   pte64_t * guest_pte = NULL;
817
818 int v3_check_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
819                          pf_error_t access_type, pt_access_status_t * access_status) {
820   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
821   pml4e64_t * guest_pmle = NULL; 
822   addr_t guest_pdpe_pa = 0;
823   int pt_level = 4;
824
825   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
826     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
827                (void *)guest_pml4_pa);
828     return -1;
829   }
830
831   *access_status = v3_can_access_pml4e64(guest_pmle, vaddr, access_type);
832
833   if (*access_status != PT_ACCESS_OK) {
834     return pt_level;
835   }
836
837   pt_level--;
838
839   switch(pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
840   case PT_ENTRY_PAGE:
841     {
842       pdpe64_t * guest_pdp = NULL;
843       addr_t guest_pde_pa = 0;
844
845       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
846         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
847                    (void *)guest_pdpe_pa);
848         return -1;
849       }
850
851       *access_status = v3_can_access_pdpe64(guest_pdp, vaddr, access_type);
852       
853       if (*access_status != PT_ACCESS_OK) {
854         return pt_level;
855       }
856       
857       pt_level--;
858       
859       switch(pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
860       case PT_ENTRY_LARGE_PAGE:
861         return 0;
862       case PT_ENTRY_PAGE:
863         {
864           pde64_t * guest_pde = NULL;
865           addr_t guest_pte_pa = 0;
866           
867           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
868             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
869                        (void *)guest_pde_pa);
870             return -1;
871           }
872
873           *access_status = v3_can_access_pde64(guest_pde, vaddr, access_type);
874           
875           if (*access_status != PT_ACCESS_OK) {
876             return pt_level;
877           }
878           
879           pt_level--;
880           
881           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
882           case PT_ENTRY_LARGE_PAGE:
883             return 0;
884           case PT_ENTRY_PAGE:
885             {
886               pte64_t * guest_pte = NULL;
887               
888               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
889                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
890                            (void *)guest_pte_pa);
891                 return -1;
892               }
893
894               *access_status = v3_can_access_pte64(guest_pte, vaddr, access_type);
895               
896               if (*access_status != PT_ACCESS_OK) {
897                 return pt_level;
898               }
899               
900               return 0;
901             }
902           default:
903             return -1;
904           }
905         }
906       default:
907         return -1;
908       }
909     }
910   default:
911     return -1;
912   }
913
914   // should never get here
915   return -1;
916 }
917
918
919
920
921
922 static pt_access_status_t can_access_pt_entry(gen_pt_t * pt, pf_error_t access_type) {
923   if (pt->present == 0) {
924     return PT_ACCESS_NOT_PRESENT;
925   } else if ((pt->writable == 0) && (access_type.write == 1)) {
926     return PT_ACCESS_WRITE_ERROR;
927   } else if ((pt->user_page == 0) && (access_type.user == 1)) {
928     // Check CR0.WP?
929     return PT_ACCESS_USER_ERROR;
930   }
931
932   return PT_ACCESS_OK;
933 }
934
935
936
937 /*
938  *   32 bit access checks
939  */
940 pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
941   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
942   return can_access_pt_entry(entry, access_type);
943 }
944
945 pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
946   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32_INDEX(addr)];
947   return can_access_pt_entry(entry, access_type);
948 }
949
950
951 /*
952  *  32 bit PAE access checks
953  */
954 pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type) {
955   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE32PAE_INDEX(addr)];
956   return can_access_pt_entry(entry, access_type);
957 }
958
959 pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type) {
960   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32PAE_INDEX(addr)];
961   return can_access_pt_entry(entry, access_type);
962 }
963
964 pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type) {
965   gen_pt_t * entry = (gen_pt_t *)&pte[PTE32PAE_INDEX(addr)];
966   return can_access_pt_entry(entry, access_type);
967 }
968
969 /*
970  *   64 Bit access checks
971  */
972 pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type) {
973   gen_pt_t * entry = (gen_pt_t *)&pmle[PML4E64_INDEX(addr)];
974   return can_access_pt_entry(entry, access_type);
975 }
976
977 pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type) {
978   gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE64_INDEX(addr)];
979   return can_access_pt_entry(entry, access_type);
980 }
981
982 pt_access_status_t inline v3_can_access_pde64(pde64_t * pde, addr_t addr, pf_error_t access_type) {
983   gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
984   return can_access_pt_entry(entry, access_type);
985 }
986
987 pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_error_t access_type) {
988   gen_pt_t * entry = (gen_pt_t *)&pte[PTE64_INDEX(addr)];
989   return can_access_pt_entry(entry, access_type);
990 }
991
992
993
994
995
996
997
998
999
1000
1001 /* We generate a page table to correspond to a given memory layout
1002  * pulling pages from the mem_list when necessary
1003  * If there are any gaps in the layout, we add them as unmapped pages
1004  */
1005 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
1006   addr_t current_page_addr = 0;
1007   int i, j;
1008   struct shadow_map * map = &(guest_info->mem_map);
1009
1010   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
1011
1012   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1013     int pte_present = 0;
1014     pte32_t * pte = V3_VAddr(V3_AllocPages(1));
1015     
1016
1017     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1018       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
1019
1020       if (!region || 
1021           (region->host_type == HOST_REGION_HOOK) || 
1022           (region->host_type == HOST_REGION_UNALLOCATED) || 
1023           (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
1024           (region->host_type == HOST_REGION_REMOTE) ||
1025           (region->host_type == HOST_REGION_SWAPPED)) {
1026         pte[j].present = 0;
1027         pte[j].writable = 0;
1028         pte[j].user_page = 0;
1029         pte[j].write_through = 0;
1030         pte[j].cache_disable = 0;
1031         pte[j].accessed = 0;
1032         pte[j].dirty = 0;
1033         pte[j].pte_attr = 0;
1034         pte[j].global_page = 0;
1035         pte[j].vmm_info = 0;
1036         pte[j].page_base_addr = 0;
1037       } else {
1038         addr_t host_addr;
1039         pte[j].present = 1;
1040         pte[j].writable = 1;
1041         pte[j].user_page = 1;
1042         pte[j].write_through = 0;
1043         pte[j].cache_disable = 0;
1044         pte[j].accessed = 0;
1045         pte[j].dirty = 0;
1046         pte[j].pte_attr = 0;
1047         pte[j].global_page = 0;
1048         pte[j].vmm_info = 0;
1049
1050         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
1051           // BIG ERROR
1052           // PANIC
1053           return NULL;
1054         }
1055         
1056         pte[j].page_base_addr = host_addr >> 12;
1057         
1058         pte_present = 1;
1059       }
1060
1061       current_page_addr += PAGE_SIZE;
1062     }
1063
1064     if (pte_present == 0) { 
1065       V3_FreePage(V3_PAddr(pte));
1066
1067       pde[i].present = 0;
1068       pde[i].writable = 0;
1069       pde[i].user_page = 0;
1070       pde[i].write_through = 0;
1071       pde[i].cache_disable = 0;
1072       pde[i].accessed = 0;
1073       pde[i].reserved = 0;
1074       pde[i].large_page = 0;
1075       pde[i].global_page = 0;
1076       pde[i].vmm_info = 0;
1077       pde[i].pt_base_addr = 0;
1078     } else {
1079       pde[i].present = 1;
1080       pde[i].writable = 1;
1081       pde[i].user_page = 1;
1082       pde[i].write_through = 0;
1083       pde[i].cache_disable = 0;
1084       pde[i].accessed = 0;
1085       pde[i].reserved = 0;
1086       pde[i].large_page = 0;
1087       pde[i].global_page = 0;
1088       pde[i].vmm_info = 0;
1089       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1090     }
1091
1092   }
1093
1094   return pde;
1095 }
1096
1097
1098 /* We generate a page table to correspond to a given memory layout
1099  * pulling pages from the mem_list when necessary
1100  * If there are any gaps in the layout, we add them as unmapped pages
1101  */
1102 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
1103   addr_t current_page_addr = 0;
1104   int i, j, k;
1105   struct shadow_map * map = &(guest_info->mem_map);
1106
1107   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
1108   memset(pdpe, 0, PAGE_SIZE);
1109
1110   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1111     int pde_present = 0;
1112     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
1113
1114     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1115
1116
1117       int pte_present = 0;
1118       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
1119       
1120       
1121       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1122         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
1123         
1124         if (!region || 
1125             (region->host_type == HOST_REGION_HOOK) || 
1126             (region->host_type == HOST_REGION_UNALLOCATED) || 
1127             (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
1128             (region->host_type == HOST_REGION_REMOTE) ||
1129             (region->host_type == HOST_REGION_SWAPPED)) {
1130           pte[k].present = 0;
1131           pte[k].writable = 0;
1132           pte[k].user_page = 0;
1133           pte[k].write_through = 0;
1134           pte[k].cache_disable = 0;
1135           pte[k].accessed = 0;
1136           pte[k].dirty = 0;
1137           pte[k].pte_attr = 0;
1138           pte[k].global_page = 0;
1139           pte[k].vmm_info = 0;
1140           pte[k].page_base_addr = 0;
1141           pte[k].rsvd = 0;
1142         } else {
1143           addr_t host_addr;
1144           pte[k].present = 1;
1145           pte[k].writable = 1;
1146           pte[k].user_page = 1;
1147           pte[k].write_through = 0;
1148           pte[k].cache_disable = 0;
1149           pte[k].accessed = 0;
1150           pte[k].dirty = 0;
1151           pte[k].pte_attr = 0;
1152           pte[k].global_page = 0;
1153           pte[k].vmm_info = 0;
1154           
1155           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
1156             // BIG ERROR
1157             // PANIC
1158             return NULL;
1159           }
1160           
1161           pte[k].page_base_addr = host_addr >> 12;
1162           pte[k].rsvd = 0;
1163
1164           pte_present = 1;
1165         }
1166         
1167         current_page_addr += PAGE_SIZE;
1168       }
1169       
1170       if (pte_present == 0) { 
1171         V3_FreePage(V3_PAddr(pte));
1172         
1173         pde[j].present = 0;
1174         pde[j].writable = 0;
1175         pde[j].user_page = 0;
1176         pde[j].write_through = 0;
1177         pde[j].cache_disable = 0;
1178         pde[j].accessed = 0;
1179         pde[j].avail = 0;
1180         pde[j].large_page = 0;
1181         pde[j].global_page = 0;
1182         pde[j].vmm_info = 0;
1183         pde[j].pt_base_addr = 0;
1184         pde[j].rsvd = 0;
1185       } else {
1186         pde[j].present = 1;
1187         pde[j].writable = 1;
1188         pde[j].user_page = 1;
1189         pde[j].write_through = 0;
1190         pde[j].cache_disable = 0;
1191         pde[j].accessed = 0;
1192         pde[j].avail = 0;
1193         pde[j].large_page = 0;
1194         pde[j].global_page = 0;
1195         pde[j].vmm_info = 0;
1196         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1197         pde[j].rsvd = 0;
1198
1199         pde_present = 1;
1200       }
1201       
1202     }
1203     
1204     if (pde_present == 0) { 
1205       V3_FreePage(V3_PAddr(pde));
1206       
1207       pdpe[i].present = 0;
1208       pdpe[i].rsvd = 0;
1209       pdpe[i].write_through = 0;
1210       pdpe[i].cache_disable = 0;
1211       pdpe[i].accessed = 0;
1212       pdpe[i].avail = 0;
1213       pdpe[i].rsvd2 = 0;
1214       pdpe[i].vmm_info = 0;
1215       pdpe[i].pd_base_addr = 0;
1216       pdpe[i].rsvd3 = 0;
1217     } else {
1218       pdpe[i].present = 1;
1219       pdpe[i].rsvd = 0;
1220       pdpe[i].write_through = 0;
1221       pdpe[i].cache_disable = 0;
1222       pdpe[i].accessed = 0;
1223       pdpe[i].avail = 0;
1224       pdpe[i].rsvd2 = 0;
1225       pdpe[i].vmm_info = 0;
1226       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
1227       pdpe[i].rsvd3 = 0;
1228     }
1229     
1230   }
1231
1232
1233   return pdpe;
1234 }
1235
1236
1237
1238
1239
1240
1241 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
1242   addr_t current_page_addr = 0;
1243   int i, j, k, m;
1244   struct shadow_map * map = &(info->mem_map);
1245   
1246   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
1247
1248   for (i = 0; i < 1; i++) {
1249     int pdpe_present = 0;
1250     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
1251
1252     for (j = 0; j < 20; j++) {
1253       int pde_present = 0;
1254       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
1255
1256       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1257         int pte_present = 0;
1258         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
1259
1260
1261         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1262           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
1263           
1264
1265           
1266           if (!region || 
1267               (region->host_type == HOST_REGION_HOOK) || 
1268               (region->host_type == HOST_REGION_UNALLOCATED) || 
1269               (region->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE) || 
1270               (region->host_type == HOST_REGION_REMOTE) ||
1271               (region->host_type == HOST_REGION_SWAPPED)) {
1272             pte[m].present = 0;
1273             pte[m].writable = 0;
1274             pte[m].user_page = 0;
1275             pte[m].write_through = 0;
1276             pte[m].cache_disable = 0;
1277             pte[m].accessed = 0;
1278             pte[m].dirty = 0;
1279             pte[m].pte_attr = 0;
1280             pte[m].global_page = 0;
1281             pte[m].vmm_info = 0;
1282             pte[m].page_base_addr = 0;
1283           } else {
1284             addr_t host_addr;
1285             pte[m].present = 1;
1286             pte[m].writable = 1;
1287             pte[m].user_page = 1;
1288             pte[m].write_through = 0;
1289             pte[m].cache_disable = 0;
1290             pte[m].accessed = 0;
1291             pte[m].dirty = 0;
1292             pte[m].pte_attr = 0;
1293             pte[m].global_page = 0;
1294             pte[m].vmm_info = 0;
1295             
1296             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
1297               // BIG ERROR
1298               // PANIC
1299               return NULL;
1300             }
1301
1302             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
1303
1304             //PrintPTE64(current_page_addr, &(pte[m]));
1305
1306             pte_present = 1;      
1307           }
1308
1309
1310
1311
1312           current_page_addr += PAGE_SIZE;
1313         }
1314         
1315         if (pte_present == 0) {
1316           V3_FreePage(V3_PAddr(pte));
1317
1318           pde[k].present = 0;
1319           pde[k].writable = 0;
1320           pde[k].user_page = 0;
1321           pde[k].write_through = 0;
1322           pde[k].cache_disable = 0;
1323           pde[k].accessed = 0;
1324           pde[k].avail = 0;
1325           pde[k].large_page = 0;
1326           //pde[k].global_page = 0;
1327           pde[k].vmm_info = 0;
1328           pde[k].pt_base_addr = 0;
1329         } else {
1330           pde[k].present = 1;
1331           pde[k].writable = 1;
1332           pde[k].user_page = 1;
1333           pde[k].write_through = 0;
1334           pde[k].cache_disable = 0;
1335           pde[k].accessed = 0;
1336           pde[k].avail = 0;
1337           pde[k].large_page = 0;
1338           //pde[k].global_page = 0;
1339           pde[k].vmm_info = 0;
1340           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1341
1342           pde_present = 1;
1343         }
1344       }
1345
1346       if (pde_present == 0) {
1347         V3_FreePage(V3_PAddr(pde));
1348         
1349         pdpe[j].present = 0;
1350         pdpe[j].writable = 0;
1351         pdpe[j].user_page = 0;
1352         pdpe[j].write_through = 0;
1353         pdpe[j].cache_disable = 0;
1354         pdpe[j].accessed = 0;
1355         pdpe[j].avail = 0;
1356         pdpe[j].large_page = 0;
1357         //pdpe[j].global_page = 0;
1358         pdpe[j].vmm_info = 0;
1359         pdpe[j].pd_base_addr = 0;
1360       } else {
1361         pdpe[j].present = 1;
1362         pdpe[j].writable = 1;
1363         pdpe[j].user_page = 1;
1364         pdpe[j].write_through = 0;
1365         pdpe[j].cache_disable = 0;
1366         pdpe[j].accessed = 0;
1367         pdpe[j].avail = 0;
1368         pdpe[j].large_page = 0;
1369         //pdpe[j].global_page = 0;
1370         pdpe[j].vmm_info = 0;
1371         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
1372
1373
1374         pdpe_present = 1;
1375       }
1376
1377     }
1378
1379     PrintDebug("PML index=%d\n", i);
1380
1381     if (pdpe_present == 0) {
1382       V3_FreePage(V3_PAddr(pdpe));
1383       
1384       pml[i].present = 0;
1385       pml[i].writable = 0;
1386       pml[i].user_page = 0;
1387       pml[i].write_through = 0;
1388       pml[i].cache_disable = 0;
1389       pml[i].accessed = 0;
1390       pml[i].reserved = 0;
1391       //pml[i].large_page = 0;
1392       //pml[i].global_page = 0;
1393       pml[i].vmm_info = 0;
1394       pml[i].pdp_base_addr = 0;
1395     } else {
1396       pml[i].present = 1;
1397       pml[i].writable = 1;
1398       pml[i].user_page = 1;
1399       pml[i].write_through = 0;
1400       pml[i].cache_disable = 0;
1401       pml[i].accessed = 0;
1402       pml[i].reserved = 0;
1403       //pml[i].large_page = 0;
1404       //pml[i].global_page = 0;
1405       pml[i].vmm_info = 0;
1406       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
1407     }
1408   }
1409
1410   return pml;
1411 }
1412
1413
1414 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1415                         void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1416                         void * private_data) {
1417   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1418   pde32_t * guest_pde = NULL;
1419   int i, j;
1420
1421   if (!callback) {
1422     PrintError("Call back was not specified\n");
1423     return -1;
1424   }
1425
1426   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1427     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1428                (void *)guest_pde_pa);
1429     return -1;
1430   }
1431
1432   callback(PAGE_PD32, (addr_t)guest_pde, guest_pde_pa, private_data);
1433
1434   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1435     if (guest_pde[i].present) {
1436       if (guest_pde[i].large_page) {
1437         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1438         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1439         addr_t large_page_va = 0;
1440
1441         if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1442           PrintError("Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1443                      (void *)large_page_pa);
1444           return -1;
1445         }
1446
1447         callback(PAGE_4MB, large_page_va, large_page_pa, private_data);
1448       } else {
1449         addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1450         pte32_t * tmp_pte = NULL;
1451
1452         if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1453           PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1454                      (void *)pte_pa);
1455           return -1;
1456         }
1457
1458         callback(PAGE_PT32, (addr_t)tmp_pte, pte_pa, private_data);
1459
1460         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1461           if (tmp_pte[j].present) {
1462             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1463             addr_t page_va = 0;
1464
1465             if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1466               PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1467                          (void *)page_pa);
1468               return -1;
1469             }
1470             
1471             callback(PAGE_4KB, page_va, page_pa, private_data);
1472           }
1473         }
1474       }
1475     }
1476   }
1477   return 0;
1478 }
1479
1480
1481 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1482                            void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1483                            void * private_data) {
1484   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1485   pdpe32pae_t * guest_pdpe = NULL;
1486   int i, j, k;
1487
1488   if (!callback) {
1489     PrintError("Call back was not specified\n");
1490     return -1;
1491   }
1492
1493   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1494     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1495                (void *)guest_pdpe_pa);
1496     return -1;
1497   }
1498
1499   
1500
1501   callback(PAGE_PDP32PAE, (addr_t)guest_pdpe, guest_pdpe_pa, private_data);
1502
1503   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1504     if (guest_pdpe[i].present) {
1505       addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1506       pde32pae_t * tmp_pde = NULL;
1507
1508       if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1509         PrintError("Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1510                    (void *)pde_pa);
1511         return -1;
1512       }
1513
1514       callback(PAGE_PD32PAE, (addr_t)tmp_pde, pde_pa, private_data);
1515       
1516       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1517         if (tmp_pde[j].present) {
1518           if (tmp_pde[j].large_page) {
1519             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1520             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1521             addr_t large_page_va = 0;
1522             
1523             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1524               PrintError("Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1525                          (void *)large_page_pa);
1526               return -1;
1527             }
1528             
1529             callback(PAGE_2MB, large_page_va, large_page_pa, private_data);
1530           } else {
1531             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1532             pte32pae_t * tmp_pte = NULL;
1533             
1534             if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1535               PrintError("Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1536                          (void *)pte_pa);
1537               return -1;
1538             }
1539             
1540             callback(PAGE_PT32PAE, (addr_t)tmp_pte, pte_pa, private_data);
1541             
1542             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1543               if (tmp_pte[k].present) {
1544                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1545                 addr_t page_va = 0;
1546                 
1547                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1548                   PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1549                              (void *)page_pa);
1550                   return -1;
1551                 }
1552                 
1553                 callback(PAGE_4KB, page_va, page_pa, private_data);
1554               }
1555             }
1556           }
1557         }
1558       }
1559     }
1560   }
1561   return 0;
1562 }
1563
1564
1565
1566
1567 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1568                         void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1569                         void * private_data) {
1570   addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1571   pml4e64_t * guest_pml = NULL;
1572   int i, j, k, m;
1573
1574   if (!callback) {
1575     PrintError("Call back was not specified\n");
1576     return -1;
1577   }
1578
1579   if (guest_pa_to_host_va(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1580     PrintError("Could not get virtual address of Guest PML464 (PA=%p)\n", 
1581                (void *)guest_pml);
1582     return -1;
1583   }
1584
1585
1586   callback(PAGE_PML464, (addr_t)guest_pml, guest_pml_pa, private_data);
1587
1588   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1589     if (guest_pml[i].present) {
1590       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1591       pdpe64_t * tmp_pdpe = NULL;
1592       
1593       
1594       if (guest_pa_to_host_va(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1595         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1596                    (void *)pdpe_pa);
1597         return -1;
1598       }
1599       
1600       callback(PAGE_PDP64, (addr_t)tmp_pdpe, pdpe_pa, private_data);
1601       
1602       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1603         if (tmp_pdpe[j].present) {
1604           if (tmp_pdpe[j].large_page) {
1605             pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1606             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1607             addr_t large_page_va = 0;
1608
1609             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1610               PrintError("Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1611                          (void *)large_page_pa);
1612               return -1;
1613             }
1614
1615             callback(PAGE_1GB, (addr_t)large_page_va, large_page_pa, private_data);
1616
1617           } else {
1618             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1619             pde64_t * tmp_pde = NULL;
1620             
1621             if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1622               PrintError("Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1623                          (void *)pde_pa);
1624               return -1;
1625             }
1626             
1627             callback(PAGE_PD64, (addr_t)tmp_pde, pde_pa, private_data);
1628             
1629             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1630               if (tmp_pde[k].present) {
1631                 if (tmp_pde[k].large_page) {
1632                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1633                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1634                   addr_t large_page_va = 0;
1635                   
1636                   if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1637                     PrintError("Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1638                                (void *)large_page_pa);
1639                     return -1;
1640                   }
1641                   
1642                   callback(PAGE_2MB, large_page_va, large_page_pa, private_data);
1643                 } else {
1644                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1645                   pte64_t * tmp_pte = NULL;
1646                   
1647                   if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1648                     PrintError("Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1649                                (void *)pte_pa);
1650                     return -1;
1651                   }
1652                   
1653                   callback(PAGE_PT64, (addr_t)tmp_pte, pte_pa, private_data);
1654                   
1655                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1656                     if (tmp_pte[m].present) {
1657                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1658                       addr_t page_va = 0;
1659                       
1660                       if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1661                         PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1662                                    (void *)page_pa);
1663                         return -1;
1664                       }
1665                       
1666                       callback(PAGE_4KB, page_va, page_pa, private_data);
1667                     }
1668                   }
1669                 }
1670               }
1671             }
1672           }
1673         }
1674       }
1675     }
1676   }
1677   return 0;
1678 }
1679
1680 int v3_walk_host_pt_32(v3_reg_t host_cr3,
1681                        void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1682                        void * private_data) {
1683   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1684   addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1685   int i, j;
1686
1687   if (!callback) {
1688     PrintError("Call back was not specified\n");
1689     return -1;
1690   }
1691
1692   callback(PAGE_PD32, (addr_t)host_pde, pde_pa, private_data);
1693
1694   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1695     if (host_pde[i].present) {
1696       if (host_pde[i].large_page) {
1697         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1698         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1699
1700         callback(PAGE_4MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1701       } else {
1702         addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1703         pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1704
1705         callback(PAGE_PT32, (addr_t)tmp_pte, pte_pa, private_data);
1706
1707         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1708           if (tmp_pte[j].present) {
1709             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1710             callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1711           }
1712         }
1713       }
1714     }
1715   }
1716   return 0;
1717 }
1718         
1719
1720
1721
1722
1723 int v3_walk_host_pt_32pae(v3_reg_t host_cr3,
1724                           void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1725                           void * private_data) {
1726   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1727   addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1728   int i, j, k;
1729   
1730   if (!callback) {
1731     PrintError("Callback was not specified\n");
1732     return -1;
1733   }
1734   
1735   callback(PAGE_PDP32PAE, (addr_t)host_pdpe, pdpe_pa, private_data);
1736   
1737   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1738     if (host_pdpe[i].present) { 
1739       addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
1740       pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
1741       
1742       callback(PAGE_PD32PAE, (addr_t)tmp_pde, pde_pa, private_data);
1743       
1744       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1745         if (tmp_pde[j].present) {
1746           
1747           if (tmp_pde[j].large_page) {
1748             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1749             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1750
1751             callback(PAGE_2MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1752           } else {
1753             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1754             pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
1755             
1756             callback(PAGE_PT32PAE, (addr_t)tmp_pte, pte_pa, private_data);
1757             
1758             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1759               if (tmp_pte[k].present) {
1760                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1761                 callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1762               }
1763             }
1764           }         
1765         }
1766       }
1767     }
1768   }
1769   return 0;
1770 }
1771                         
1772
1773 int v3_walk_host_pt_64(v3_reg_t host_cr3,
1774                        void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data),
1775                        void * private_data) {
1776   pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1777   addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
1778   int i, j, k, m;
1779
1780   if (!callback) {
1781     PrintError("Callback was not specified\n");
1782     return -1;
1783   }
1784
1785   callback(PAGE_PML464, (addr_t)host_pml, pml_pa, private_data);
1786
1787   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1788     if (host_pml[i].present) {
1789       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
1790       pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
1791
1792       callback(PAGE_PDP64, (addr_t)tmp_pdpe, pdpe_pa, private_data);
1793
1794       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1795         if (tmp_pdpe[j].present) {
1796           if (tmp_pdpe[j].large_page) {
1797             pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1798             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
1799
1800             callback(PAGE_1GB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);       
1801           } else {
1802             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1803             pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
1804
1805             callback(PAGE_PD64, (addr_t)tmp_pde, pde_pa, private_data);
1806
1807             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1808               if (tmp_pde[k].present) {
1809                 if (tmp_pde[k].large_page) {
1810                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1811                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1812                   
1813                   callback(PAGE_2MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1814                 } else {
1815                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1816                   pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
1817
1818                   callback(PAGE_PT64, (addr_t)tmp_pte, pte_pa, private_data);
1819
1820                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1821                     if (tmp_pte[m].present) {
1822                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1823                       callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1824                     }
1825                   }
1826                 }
1827               }
1828             }
1829           }
1830         }
1831       }
1832     }
1833   }
1834   return 0;
1835 }
1836
1837
1838
1839 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
1840 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
1841 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
1842 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
1843 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
1844 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
1845 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
1846 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
1847 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
1848 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
1849 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
1850 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
1851 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
1852
1853
1854 const uchar_t * v3_page_type_to_str(page_type_t type) {
1855   switch (type) {
1856   case PAGE_4KB:
1857     return PAGE_4KB_STR;
1858   case PAGE_2MB:
1859     return PAGE_2MB_STR;
1860   case PAGE_4MB:
1861     return PAGE_4MB_STR;
1862   case PAGE_1GB:
1863     return PAGE_1GB_STR;
1864   case PAGE_PT32:
1865     return PAGE_PT32_STR;
1866   case PAGE_PD32:
1867     return PAGE_PD32_STR;
1868   case PAGE_PDP32PAE:
1869     return PAGE_PDP32PAE_STR;
1870   case PAGE_PD32PAE:
1871     return PAGE_PD32PAE_STR;
1872   case PAGE_PT32PAE:
1873     return PAGE_PT32PAE_STR;
1874   case PAGE_PML464:
1875     return PAGE_PML464_STR;
1876   case PAGE_PDP64:
1877     return PAGE_PDP64_STR;
1878   case PAGE_PD64:
1879     return PAGE_PD64_STR;
1880   case PAGE_PT64:
1881     return PAGE_PT64_STR;
1882   default:
1883     return NULL;
1884   }
1885 }