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.


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