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.


working instruction emulation
[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 == SHDW_REGION_FULL_HOOK) || 
681           (region->host_type == SHDW_REGION_UNALLOCATED)) {
682         pte[j].present = 0;
683         pte[j].writable = 0;
684         pte[j].user_page = 0;
685         pte[j].write_through = 0;
686         pte[j].cache_disable = 0;
687         pte[j].accessed = 0;
688         pte[j].dirty = 0;
689         pte[j].pte_attr = 0;
690         pte[j].global_page = 0;
691         pte[j].vmm_info = 0;
692         pte[j].page_base_addr = 0;
693       } else {
694         addr_t host_addr;
695         pte[j].present = 1;
696
697         if (region->host_type == SHDW_REGION_WRITE_HOOK) {
698           pte[j].writable = 0;
699           PrintDebug("Marking Write hook host_addr %p as RO\n", (void *)current_page_addr);
700         } else {
701           pte[j].writable = 1;
702         }
703           
704         pte[j].user_page = 1;
705         pte[j].write_through = 0;
706         pte[j].cache_disable = 0;
707         pte[j].accessed = 0;
708         pte[j].dirty = 0;
709         pte[j].pte_attr = 0;
710         pte[j].global_page = 0;
711         pte[j].vmm_info = 0;
712
713         if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
714           // BIG ERROR
715           // PANIC
716           return NULL;
717         }
718         
719         pte[j].page_base_addr = host_addr >> 12;
720         
721         pte_present = 1;
722       }
723
724       current_page_addr += PAGE_SIZE;
725     }
726
727     if (pte_present == 0) { 
728       V3_FreePage(V3_PAddr(pte));
729
730       pde[i].present = 0;
731       pde[i].writable = 0;
732       pde[i].user_page = 0;
733       pde[i].write_through = 0;
734       pde[i].cache_disable = 0;
735       pde[i].accessed = 0;
736       pde[i].reserved = 0;
737       pde[i].large_page = 0;
738       pde[i].global_page = 0;
739       pde[i].vmm_info = 0;
740       pde[i].pt_base_addr = 0;
741     } else {
742       pde[i].present = 1;
743       pde[i].writable = 1;
744       pde[i].user_page = 1;
745       pde[i].write_through = 0;
746       pde[i].cache_disable = 0;
747       pde[i].accessed = 0;
748       pde[i].reserved = 0;
749       pde[i].large_page = 0;
750       pde[i].global_page = 0;
751       pde[i].vmm_info = 0;
752       pde[i].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
753     }
754
755   }
756
757   return pde;
758 }
759
760
761 /* We generate a page table to correspond to a given memory layout
762  * pulling pages from the mem_list when necessary
763  * If there are any gaps in the layout, we add them as unmapped pages
764  */
765 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
766   addr_t current_page_addr = 0;
767   int i, j, k;
768   struct shadow_map * map = &(guest_info->mem_map);
769
770   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
771   memset(pdpe, 0, PAGE_SIZE);
772
773   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
774     int pde_present = 0;
775     pde32pae_t * pde = V3_VAddr(V3_AllocPages(1));
776
777     for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
778
779
780       int pte_present = 0;
781       pte32pae_t * pte = V3_VAddr(V3_AllocPages(1));
782       
783       
784       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
785         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
786         
787         if (!region || 
788             (region->host_type == SHDW_REGION_FULL_HOOK) || 
789             (region->host_type == SHDW_REGION_UNALLOCATED)) {
790           pte[k].present = 0;
791           pte[k].writable = 0;
792           pte[k].user_page = 0;
793           pte[k].write_through = 0;
794           pte[k].cache_disable = 0;
795           pte[k].accessed = 0;
796           pte[k].dirty = 0;
797           pte[k].pte_attr = 0;
798           pte[k].global_page = 0;
799           pte[k].vmm_info = 0;
800           pte[k].page_base_addr = 0;
801           pte[k].rsvd = 0;
802         } else {
803           addr_t host_addr;
804           pte[k].present = 1;
805         
806           if (region->host_type == SHDW_REGION_WRITE_HOOK) {
807             pte[k].writable = 0;
808           } else {
809             pte[k].writable = 1;
810           }
811
812           pte[k].user_page = 1;
813           pte[k].write_through = 0;
814           pte[k].cache_disable = 0;
815           pte[k].accessed = 0;
816           pte[k].dirty = 0;
817           pte[k].pte_attr = 0;
818           pte[k].global_page = 0;
819           pte[k].vmm_info = 0;
820           
821           if (guest_pa_to_host_pa(guest_info, current_page_addr, &host_addr) == -1) {
822             // BIG ERROR
823             // PANIC
824             return NULL;
825           }
826           
827           pte[k].page_base_addr = host_addr >> 12;
828           pte[k].rsvd = 0;
829
830           pte_present = 1;
831         }
832         
833         current_page_addr += PAGE_SIZE;
834       }
835       
836       if (pte_present == 0) { 
837         V3_FreePage(V3_PAddr(pte));
838         
839         pde[j].present = 0;
840         pde[j].writable = 0;
841         pde[j].user_page = 0;
842         pde[j].write_through = 0;
843         pde[j].cache_disable = 0;
844         pde[j].accessed = 0;
845         pde[j].avail = 0;
846         pde[j].large_page = 0;
847         pde[j].global_page = 0;
848         pde[j].vmm_info = 0;
849         pde[j].pt_base_addr = 0;
850         pde[j].rsvd = 0;
851       } else {
852         pde[j].present = 1;
853         pde[j].writable = 1;
854         pde[j].user_page = 1;
855         pde[j].write_through = 0;
856         pde[j].cache_disable = 0;
857         pde[j].accessed = 0;
858         pde[j].avail = 0;
859         pde[j].large_page = 0;
860         pde[j].global_page = 0;
861         pde[j].vmm_info = 0;
862         pde[j].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
863         pde[j].rsvd = 0;
864
865         pde_present = 1;
866       }
867       
868     }
869     
870     if (pde_present == 0) { 
871       V3_FreePage(V3_PAddr(pde));
872       
873       pdpe[i].present = 0;
874       pdpe[i].rsvd = 0;
875       pdpe[i].write_through = 0;
876       pdpe[i].cache_disable = 0;
877       pdpe[i].accessed = 0;
878       pdpe[i].avail = 0;
879       pdpe[i].rsvd2 = 0;
880       pdpe[i].vmm_info = 0;
881       pdpe[i].pd_base_addr = 0;
882       pdpe[i].rsvd3 = 0;
883     } else {
884       pdpe[i].present = 1;
885       pdpe[i].rsvd = 0;
886       pdpe[i].write_through = 0;
887       pdpe[i].cache_disable = 0;
888       pdpe[i].accessed = 0;
889       pdpe[i].avail = 0;
890       pdpe[i].rsvd2 = 0;
891       pdpe[i].vmm_info = 0;
892       pdpe[i].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
893       pdpe[i].rsvd3 = 0;
894     }
895     
896   }
897
898
899   return pdpe;
900 }
901
902
903
904
905
906
907 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
908   addr_t current_page_addr = 0;
909   int i, j, k, m;
910   struct shadow_map * map = &(info->mem_map);
911   
912   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
913
914   for (i = 0; i < 1; i++) {
915     int pdpe_present = 0;
916     pdpe64_t * pdpe = V3_VAddr(V3_AllocPages(1));
917
918     for (j = 0; j < 20; j++) {
919       int pde_present = 0;
920       pde64_t * pde = V3_VAddr(V3_AllocPages(1));
921
922       for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
923         int pte_present = 0;
924         pte64_t * pte = V3_VAddr(V3_AllocPages(1));
925
926
927         for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
928           struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
929           
930
931           
932           if (!region || 
933               (region->host_type == SHDW_REGION_FULL_HOOK) || 
934               (region->host_type == SHDW_REGION_UNALLOCATED)) {
935             pte[m].present = 0;
936             pte[m].writable = 0;
937             pte[m].user_page = 0;
938             pte[m].write_through = 0;
939             pte[m].cache_disable = 0;
940             pte[m].accessed = 0;
941             pte[m].dirty = 0;
942             pte[m].pte_attr = 0;
943             pte[m].global_page = 0;
944             pte[m].vmm_info = 0;
945             pte[m].page_base_addr = 0;
946           } else {
947             addr_t host_addr;
948             pte[m].present = 1;
949
950             if (region->host_type == SHDW_REGION_WRITE_HOOK) {
951               pte[m].writable = 0;
952             } else {
953               pte[m].writable = 1;
954             }
955         
956             pte[m].user_page = 1;
957             pte[m].write_through = 0;
958             pte[m].cache_disable = 0;
959             pte[m].accessed = 0;
960             pte[m].dirty = 0;
961             pte[m].pte_attr = 0;
962             pte[m].global_page = 0;
963             pte[m].vmm_info = 0;
964             
965             if (guest_pa_to_host_pa(info, current_page_addr, &host_addr) == -1) {
966               // BIG ERROR
967               // PANIC
968               return NULL;
969             }
970
971             pte[m].page_base_addr = PAGE_BASE_ADDR(host_addr);
972
973             //PrintPTE64(current_page_addr, &(pte[m]));
974
975             pte_present = 1;      
976           }
977
978
979
980
981           current_page_addr += PAGE_SIZE;
982         }
983         
984         if (pte_present == 0) {
985           V3_FreePage(V3_PAddr(pte));
986
987           pde[k].present = 0;
988           pde[k].writable = 0;
989           pde[k].user_page = 0;
990           pde[k].write_through = 0;
991           pde[k].cache_disable = 0;
992           pde[k].accessed = 0;
993           pde[k].avail = 0;
994           pde[k].large_page = 0;
995           //pde[k].global_page = 0;
996           pde[k].vmm_info = 0;
997           pde[k].pt_base_addr = 0;
998         } else {
999           pde[k].present = 1;
1000           pde[k].writable = 1;
1001           pde[k].user_page = 1;
1002           pde[k].write_through = 0;
1003           pde[k].cache_disable = 0;
1004           pde[k].accessed = 0;
1005           pde[k].avail = 0;
1006           pde[k].large_page = 0;
1007           //pde[k].global_page = 0;
1008           pde[k].vmm_info = 0;
1009           pde[k].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte));
1010
1011           pde_present = 1;
1012         }
1013       }
1014
1015       if (pde_present == 0) {
1016         V3_FreePage(V3_PAddr(pde));
1017         
1018         pdpe[j].present = 0;
1019         pdpe[j].writable = 0;
1020         pdpe[j].user_page = 0;
1021         pdpe[j].write_through = 0;
1022         pdpe[j].cache_disable = 0;
1023         pdpe[j].accessed = 0;
1024         pdpe[j].avail = 0;
1025         pdpe[j].large_page = 0;
1026         //pdpe[j].global_page = 0;
1027         pdpe[j].vmm_info = 0;
1028         pdpe[j].pd_base_addr = 0;
1029       } else {
1030         pdpe[j].present = 1;
1031         pdpe[j].writable = 1;
1032         pdpe[j].user_page = 1;
1033         pdpe[j].write_through = 0;
1034         pdpe[j].cache_disable = 0;
1035         pdpe[j].accessed = 0;
1036         pdpe[j].avail = 0;
1037         pdpe[j].large_page = 0;
1038         //pdpe[j].global_page = 0;
1039         pdpe[j].vmm_info = 0;
1040         pdpe[j].pd_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pde));
1041
1042
1043         pdpe_present = 1;
1044       }
1045
1046     }
1047
1048     PrintDebug("PML index=%d\n", i);
1049
1050     if (pdpe_present == 0) {
1051       V3_FreePage(V3_PAddr(pdpe));
1052       
1053       pml[i].present = 0;
1054       pml[i].writable = 0;
1055       pml[i].user_page = 0;
1056       pml[i].write_through = 0;
1057       pml[i].cache_disable = 0;
1058       pml[i].accessed = 0;
1059       pml[i].reserved = 0;
1060       //pml[i].large_page = 0;
1061       //pml[i].global_page = 0;
1062       pml[i].vmm_info = 0;
1063       pml[i].pdp_base_addr = 0;
1064     } else {
1065       pml[i].present = 1;
1066       pml[i].writable = 1;
1067       pml[i].user_page = 1;
1068       pml[i].write_through = 0;
1069       pml[i].cache_disable = 0;
1070       pml[i].accessed = 0;
1071       pml[i].reserved = 0;
1072       //pml[i].large_page = 0;
1073       //pml[i].global_page = 0;
1074       pml[i].vmm_info = 0;
1075       pml[i].pdp_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pdpe));
1076     }
1077   }
1078
1079   return pml;
1080 }
1081
1082
1083 int v3_drill_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, 
1084                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1085                         void * private_data) {
1086   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1087   addr_t host_pde_pa = CR3_TO_PDE32_PA(host_cr3);
1088   addr_t host_pte_pa = 0;
1089   addr_t page_pa = 0;
1090   int ret;
1091
1092   if ((ret = callback(PAGE_PD32, vaddr, (addr_t)host_pde, host_pde_pa, private_data)) != 0) {
1093     return (ret == -1) ? -1 : PAGE_PD32;
1094   }
1095
1096   switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) {
1097   case PT_ENTRY_NOT_PRESENT:
1098     return -1;
1099   case PT_ENTRY_LARGE_PAGE:
1100     if ((ret == callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1101       return (ret == -1) ? -1 : PAGE_4MB;
1102     }
1103     return 0;
1104   case PT_ENTRY_PAGE:
1105     if ((ret = callback(PAGE_PT32, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1106       return (ret == -1) ? -1 : PAGE_PT32;
1107     }
1108     
1109     if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1110       return -1;
1111     } else {
1112       if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1113         return (ret == -1) ? -1 : PAGE_4KB;
1114       }
1115       return 0;
1116     }
1117   }
1118   return -1;
1119 }
1120
1121
1122
1123 int v3_drill_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr,
1124                            int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1125                            void * private_data) {
1126   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1127   addr_t host_pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1128   addr_t host_pde_pa = 0;
1129   addr_t host_pte_pa = 0;
1130   addr_t page_pa = 0;
1131   int ret;
1132
1133   if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, host_pdpe_pa, private_data)) != 0) {
1134     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1135   }
1136
1137   switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) {
1138   case PT_ENTRY_NOT_PRESENT:
1139     return -1;
1140   case PT_ENTRY_PAGE:
1141
1142     if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1143       return (ret == -1) ? -1 : PAGE_PD32PAE;
1144     }
1145       
1146     switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1147     case PT_ENTRY_NOT_PRESENT:
1148       return -1;
1149     case PT_ENTRY_LARGE_PAGE:
1150       if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1151         return (ret == -1) ? -1 : PAGE_2MB;
1152       }
1153       return 0;
1154     case PT_ENTRY_PAGE:
1155       if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1156         return (ret == -1) ? -1 : PAGE_PT32PAE;
1157       }
1158
1159       if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1160         return -1;
1161       } else {
1162         if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1163           return (ret == -1) ? -1 : PAGE_4KB;
1164         }
1165         return 0;
1166       } 
1167     }
1168   default:
1169     return -1;
1170   }
1171
1172   // should never get here
1173   return -1;
1174 }
1175
1176
1177 int v3_drill_host_pt_64(v3_reg_t host_cr3, addr_t vaddr,
1178                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1179                         void * private_data) {
1180   pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1181   addr_t host_pmle_pa = CR3_TO_PML4E64_PA(host_cr3);
1182   addr_t host_pdpe_pa = 0;
1183   addr_t host_pde_pa = 0;
1184   addr_t host_pte_pa = 0;
1185   addr_t page_pa = 0;
1186   int ret;
1187
1188   if ((ret = callback(PAGE_PML464, vaddr, (addr_t)host_pmle, host_pmle_pa, private_data)) != 0) {
1189     return (ret == -1) ? -1 : PAGE_PML464;
1190   }
1191
1192   switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) {
1193   case PT_ENTRY_NOT_PRESENT:
1194     return -1;
1195   case PT_ENTRY_PAGE:
1196
1197     if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)V3_VAddr((void *)host_pdpe_pa), host_pdpe_pa, private_data)) != 0) {
1198       return (ret == -1) ? -1 : PAGE_PDP64;
1199     }
1200
1201     switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) {
1202     case PT_ENTRY_NOT_PRESENT:
1203       return -1;
1204     case PT_ENTRY_LARGE_PAGE:
1205       if ((ret == callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
1206         return (ret == -1) ? -1 : PAGE_1GB;
1207       }
1208       PrintError("1 Gigabyte Pages not supported\n");
1209       return 0;
1210     case PT_ENTRY_PAGE:
1211
1212       if ((ret = callback(PAGE_PD64, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) {
1213         return (ret == -1) ? -1 : PAGE_PD64;
1214       }
1215
1216       switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
1217       case PT_ENTRY_NOT_PRESENT:
1218         return -1;
1219       case PT_ENTRY_LARGE_PAGE:
1220         if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
1221           return (ret == -1) ? -1 : PAGE_2MB;
1222         }
1223         return 0;
1224       case PT_ENTRY_PAGE:
1225
1226         if ((ret = callback(PAGE_PT64, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) {
1227           return (ret == -1) ? -1 : PAGE_PT64;
1228         }
1229
1230         if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1231           return -1;
1232         } else {
1233           if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
1234             return (ret == -1) ? -1 : PAGE_4KB;
1235           }
1236           return 0;
1237         }
1238       }
1239     }
1240   default:
1241     return -1;
1242   }
1243   // should never get here
1244   return -1;
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1254                          int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1255                          void * private_data) {
1256   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1257   pde32_t * guest_pde = NULL;
1258   addr_t guest_pte_pa = 0;
1259   int ret; 
1260   
1261
1262   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) {
1263     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1264                (void *)guest_pde_pa);
1265     return -1;
1266   }
1267   
1268   if ((ret = callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1269     return (ret == -1) ? -1 : PAGE_PD32;
1270   }
1271   
1272   switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1273   case PT_ENTRY_NOT_PRESENT:
1274     return -1;
1275   case PT_ENTRY_LARGE_PAGE:
1276     {
1277       addr_t large_page_pa = (addr_t)guest_pte_pa;
1278       addr_t large_page_va = 0;
1279       
1280       if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1281         PrintError("Could not get virtual address of Guest Page 4MB (PA=%p)\n", 
1282                    (void *)large_page_va);
1283         return -1;
1284       }
1285
1286
1287       if ((ret == callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1288         return (ret == -1) ? -1 : PAGE_4MB;
1289       }
1290       return 0;
1291     }
1292   case PT_ENTRY_PAGE:
1293     {
1294       pte32_t * guest_pte = NULL;
1295       addr_t page_pa;
1296
1297       if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
1298         PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1299                    (void *)guest_pte_pa);
1300         return -1;
1301       }
1302
1303       if ((ret = callback(PAGE_PT32, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1304         return (ret == -1) ? -1 : PAGE_PT32;
1305       }
1306
1307       if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1308         return -1;
1309       } else {
1310         addr_t page_va;
1311
1312         if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1313           PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1314                      (void *)page_pa);
1315           return -1;
1316         }
1317
1318         if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1319           return (ret == -1) ? -1 : PAGE_4KB;
1320         }
1321         return 0;
1322       }
1323     }
1324   }
1325
1326   // should never get here
1327   PrintError("End of drill function (guest 32)... Should never have gotten here...\n");
1328   return -1;
1329 }
1330
1331
1332
1333 int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr,
1334                                 int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1335                                 void * private_data) {                  
1336   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1337   pdpe32pae_t * guest_pdpe = 0;
1338   addr_t guest_pde_pa = 0;
1339   int ret = 0;
1340
1341   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
1342     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
1343                (void *)guest_pdpe_pa);
1344     return -1;
1345   }
1346
1347   if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1348     return (ret == -1) ? -1 : PAGE_PDP32PAE;
1349   }
1350
1351   switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
1352     {
1353     case PT_ENTRY_NOT_PRESENT:
1354       return -1;
1355     case PT_ENTRY_PAGE:
1356       {
1357         pde32pae_t * guest_pde = NULL;
1358         addr_t guest_pte_pa = 0;
1359         
1360         if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1361           PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
1362                      (void *)guest_pde_pa);
1363           return -1;
1364         }
1365
1366         if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1367           return (ret == -1) ? -1 : PAGE_PD32PAE;
1368         }
1369         
1370         switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
1371           {
1372           case PT_ENTRY_NOT_PRESENT:
1373             return -1;
1374           case PT_ENTRY_LARGE_PAGE:
1375             {
1376               addr_t large_page_pa = (addr_t)guest_pte_pa;
1377               addr_t large_page_va = 0;
1378               
1379               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1380                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1381                            (void *)large_page_va);
1382
1383               }
1384               
1385               if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1386                 return (ret == -1) ? -1 : PAGE_2MB;
1387               }
1388               return 0;
1389             }
1390           case PT_ENTRY_PAGE:
1391             {
1392               pte32pae_t * guest_pte = NULL;
1393               addr_t page_pa;
1394
1395               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1396                 PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
1397                            (void *)guest_pte_pa);
1398                 return -1;
1399               }
1400
1401               if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1402                 return (ret == -1) ? -1 : PAGE_PT32PAE;
1403               }
1404
1405               if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1406                 return -1;
1407               } else {
1408                 addr_t page_va;
1409                 
1410                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1411                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1412                              (void *)page_pa);
1413                   return -1;
1414                 }
1415                 
1416                 if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1417                   return (ret == -1) ? -1 : PAGE_4KB;
1418                 }
1419                 return 0;
1420               }
1421             }
1422           }
1423       }
1424     default:
1425       PrintError("Invalid page type for PD32PAE\n");
1426       return -1;
1427     }
1428
1429   // should never get here
1430   PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n");
1431   return -1;
1432 }
1433
1434 int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1435                                 int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1436                                 void * private_data) {  
1437   addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
1438   pml4e64_t * guest_pmle = 0;
1439   addr_t guest_pdpe_pa = 0;
1440   int ret = 0;
1441
1442   if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
1443     PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
1444                (void *)guest_pml4_pa);
1445     return -1;
1446   }
1447   
1448   if ((ret = callback(PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) {
1449     return (ret == -1) ? -1 : PAGE_PML464;
1450   }
1451
1452   switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1453   case PT_ENTRY_NOT_PRESENT:
1454     return -1;
1455   case PT_ENTRY_PAGE:
1456     {
1457       pdpe64_t * guest_pdp = NULL;
1458       addr_t guest_pde_pa = 0;
1459
1460       if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
1461         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1462                    (void *)guest_pdpe_pa);
1463         return -1;
1464       }
1465
1466       if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) {
1467         return (ret == -1) ? -1 : PAGE_PDP64;
1468       }
1469
1470       switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1471       case PT_ENTRY_NOT_PRESENT:
1472         return -1;
1473       case PT_ENTRY_LARGE_PAGE:
1474         {
1475           addr_t large_page_pa = (addr_t)guest_pde_pa;
1476           addr_t large_page_va = 0;
1477           
1478           if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1479             PrintDebug("Could not get virtual address of Guest Page 1GB (PA=%p)\n", 
1480                        (void *)large_page_va);
1481             
1482           }
1483           
1484           if ((ret == callback(PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1485             return (ret == -1) ? -1 : PAGE_1GB;
1486           }
1487           PrintError("1 Gigabyte Pages not supported\n");
1488           return 0;
1489         }
1490       case PT_ENTRY_PAGE:
1491         {
1492           pde64_t * guest_pde = NULL;
1493           addr_t guest_pte_pa = 0;
1494
1495           if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1496             PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
1497                        (void *)guest_pde_pa);
1498             return -1;
1499           }
1500         
1501           if ((ret = callback(PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1502             return (ret == -1) ? -1 : PAGE_PD64;
1503           }
1504
1505           switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1506           case PT_ENTRY_NOT_PRESENT:
1507             return -1;
1508           case PT_ENTRY_LARGE_PAGE:
1509             {
1510               addr_t large_page_pa = (addr_t)guest_pte_pa;
1511               addr_t large_page_va = 0;
1512               
1513               if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1514                 PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", 
1515                            (void *)large_page_va);
1516
1517               }
1518               
1519               if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1520                 return (ret == -1) ? -1 : PAGE_2MB;
1521               }
1522               return 0;
1523             }
1524           case PT_ENTRY_PAGE:
1525             {
1526               pte64_t * guest_pte = NULL;
1527               addr_t page_pa;
1528               
1529               if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1530                 PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
1531                            (void *)guest_pte_pa);
1532                 return -1;
1533               }
1534
1535               if ((ret = callback(PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1536                 return (ret == -1) ? -1 : PAGE_PT64;
1537               }
1538                 
1539               if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1540                 return -1;
1541               } else {
1542                 addr_t page_va;
1543                 
1544                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1545                   PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", 
1546                              (void *)page_pa);
1547                   return -1;
1548                 }
1549                 
1550                 if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1551                   return (ret == -1) ? -1 : PAGE_4KB;
1552                 }
1553
1554                 return 0;
1555               }
1556             }
1557           }
1558         }
1559       }
1560     }
1561   default:
1562     return -1;
1563   }
1564
1565   // should never get here
1566   PrintError("End of drill function (guest 64)... Should never have gotten here...\n");
1567   return -1;
1568 }
1569
1570
1571
1572
1573 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1574                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1575                         void * private_data) {
1576   addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1577   pde32_t * guest_pde = NULL;
1578   int i, j;
1579   addr_t vaddr = 0;
1580
1581   if (!callback) {
1582     PrintError("Call back was not specified\n");
1583     return -1;
1584   }
1585
1586   if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1587     PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1588                (void *)guest_pde_pa);
1589     return -1;
1590   }
1591
1592   callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data);
1593
1594   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1595     if (guest_pde[i].present) {
1596       if (guest_pde[i].large_page) {
1597         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1598         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1599         addr_t large_page_va = 0;
1600
1601         if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1602           PrintDebug("Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1603                      (void *)large_page_pa);
1604           // We'll let it through for data pages because they may be unmapped or hooked
1605           large_page_va = 0;
1606         }
1607
1608         callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data);
1609
1610         vaddr += PAGE_SIZE_4MB;
1611       } else {
1612         addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1613         pte32_t * tmp_pte = NULL;
1614
1615         if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1616           PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1617                      (void *)pte_pa);
1618           return -1;
1619         }
1620
1621         callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1622
1623         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1624           if (tmp_pte[j].present) {
1625             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1626             addr_t page_va = 0;
1627
1628             if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1629               PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1630                  (void *)page_pa);
1631               // We'll let it through for data pages because they may be unmapped or hooked
1632               page_va = 0;
1633             }
1634             
1635             callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1636           }
1637
1638           vaddr += PAGE_SIZE_4KB;
1639         }
1640       }
1641     } else {
1642       vaddr += PAGE_SIZE_4MB;
1643     }
1644   }
1645   return 0;
1646 }
1647
1648
1649 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1650                            int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1651                            void * private_data) {
1652   addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1653   pdpe32pae_t * guest_pdpe = NULL;
1654   int i, j, k;
1655   addr_t vaddr = 0;
1656
1657   if (!callback) {
1658     PrintError("Call back was not specified\n");
1659     return -1;
1660   }
1661
1662   if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1663     PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1664                (void *)guest_pdpe_pa);
1665     return -1;
1666   }
1667
1668   
1669
1670   callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data);
1671
1672   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1673     if (guest_pdpe[i].present) {
1674       addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1675       pde32pae_t * tmp_pde = NULL;
1676
1677       if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1678         PrintError("Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1679                    (void *)pde_pa);
1680         return -1;
1681       }
1682
1683       callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1684       
1685       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1686         if (tmp_pde[j].present) {
1687           if (tmp_pde[j].large_page) {
1688             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1689             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1690             addr_t large_page_va = 0;
1691             
1692             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1693               PrintDebug("Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1694                          (void *)large_page_pa);
1695               // We'll let it through for data pages because they may be unmapped or hooked
1696               large_page_va = 0;
1697             }
1698             
1699             callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data);
1700
1701             vaddr += PAGE_SIZE_2MB;
1702           } else {
1703             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1704             pte32pae_t * tmp_pte = NULL;
1705             
1706             if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1707               PrintError("Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1708                          (void *)pte_pa);
1709               return -1;
1710             }
1711             
1712             callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1713             
1714             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1715               if (tmp_pte[k].present) {
1716                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1717                 addr_t page_va = 0;
1718                 
1719                 if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1720                   PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1721                              (void *)page_pa);
1722                   // We'll let it through for data pages because they may be unmapped or hooked
1723                   page_va = 0;
1724                 }
1725                 
1726                 callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1727               }
1728               
1729               vaddr += PAGE_SIZE_4KB;
1730             }
1731           }
1732         } else {
1733           vaddr += PAGE_SIZE_2MB;
1734         }
1735       }
1736     } else {
1737       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1738     }
1739   }
1740   return 0;
1741 }
1742
1743
1744
1745
1746 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1747                         int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1748                         void * private_data) {
1749   addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1750   pml4e64_t * guest_pml = NULL;
1751   int i, j, k, m;
1752   addr_t vaddr = 0;
1753
1754   if (!callback) {
1755     PrintError("Call back was not specified\n");
1756     return -1;
1757   }
1758
1759   if (guest_pa_to_host_va(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1760     PrintError("Could not get virtual address of Guest PML464 (PA=%p)\n", 
1761                (void *)guest_pml);
1762     return -1;
1763   }
1764
1765
1766   callback(PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data);
1767
1768   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1769     if (guest_pml[i].present) {
1770       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1771       pdpe64_t * tmp_pdpe = NULL;
1772       
1773       
1774       if (guest_pa_to_host_va(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1775         PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1776                    (void *)pdpe_pa);
1777         return -1;
1778       }
1779       
1780       callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data);
1781       
1782       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1783         if (tmp_pdpe[j].present) {
1784           if (tmp_pdpe[j].large_page) {
1785             pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1786             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1787             addr_t large_page_va = 0;
1788
1789             if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1790               PrintDebug("Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1791                          (void *)large_page_pa);
1792               // We'll let it through for data pages because they may be unmapped or hooked
1793               large_page_va = 0;
1794             }
1795
1796             callback(PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data);
1797
1798             vaddr += PAGE_SIZE_1GB;
1799           } else {
1800             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1801             pde64_t * tmp_pde = NULL;
1802             
1803             if (guest_pa_to_host_va(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1804               PrintError("Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1805                          (void *)pde_pa);
1806               return -1;
1807             }
1808             
1809             callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1810             
1811             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1812               if (tmp_pde[k].present) {
1813                 if (tmp_pde[k].large_page) {
1814                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1815                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1816                   addr_t large_page_va = 0;
1817                   
1818                   if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) {
1819                     PrintDebug("Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1820                                (void *)large_page_pa);
1821                     // We'll let it through for data pages because they may be unmapped or hooked
1822                     large_page_va = 0;
1823                   }
1824                   
1825                   callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data);
1826
1827                   vaddr += PAGE_SIZE_2MB;
1828                 } else {
1829                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1830                   pte64_t * tmp_pte = NULL;
1831                   
1832                   if (guest_pa_to_host_va(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1833                     PrintError("Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1834                                (void *)pte_pa);
1835                     return -1;
1836                   }
1837                   
1838                   callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1839                   
1840                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1841                     if (tmp_pte[m].present) {
1842                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1843                       addr_t page_va = 0;
1844                       
1845                       if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) {
1846                         PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1847                                    (void *)page_pa);
1848                         // We'll let it through for data pages because they may be unmapped or hooked
1849                         page_va = 0;
1850                       }
1851                       
1852                       callback(PAGE_4KB, vaddr, page_va, page_pa, private_data);
1853                     }
1854
1855                     vaddr += PAGE_SIZE_4KB;
1856                   }
1857                 }
1858               } else {
1859                 vaddr += PAGE_SIZE_2MB;
1860               }
1861             }
1862           }
1863         } else {
1864           vaddr += PAGE_SIZE_1GB;
1865         }
1866       }
1867     } else {
1868       vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
1869     }
1870   }
1871   return 0;
1872 }
1873
1874 int v3_walk_host_pt_32(v3_reg_t host_cr3,
1875                        int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1876                        void * private_data) {
1877   pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1878   addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1879   int i, j;
1880   addr_t vaddr = 0;
1881
1882   if (!callback) {
1883     PrintError("Call back was not specified\n");
1884     return -1;
1885   }
1886
1887   callback(PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data);
1888
1889   for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1890     if (host_pde[i].present) {
1891       if (host_pde[i].large_page) {
1892         pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1893         addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1894
1895         callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1896
1897         vaddr += PAGE_SIZE_4MB;
1898       } else {
1899         addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1900         pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1901
1902         callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1903
1904         for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1905           if (tmp_pte[j].present) {
1906             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1907             callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1908           }
1909
1910           vaddr += PAGE_SIZE_4KB;
1911         }
1912       }
1913     } else {
1914       vaddr += PAGE_SIZE_4MB;
1915     }
1916   }
1917   return 0;
1918 }
1919
1920
1921
1922
1923
1924 int v3_walk_host_pt_32pae(v3_reg_t host_cr3,
1925                           int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1926                           void * private_data) {
1927   pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1928   addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1929   int i, j, k;
1930   addr_t vaddr = 0;
1931
1932   if (!callback) {
1933     PrintError("Callback was not specified\n");
1934     return -1;
1935   }
1936   
1937   callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data);
1938   
1939   for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1940     if (host_pdpe[i].present) { 
1941       addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
1942       pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
1943       
1944       callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
1945       
1946       for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1947         if (tmp_pde[j].present) {
1948           
1949           if (tmp_pde[j].large_page) {
1950             pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1951             addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1952
1953             callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
1954
1955             vaddr += PAGE_SIZE_2MB;
1956           } else {
1957             addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1958             pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
1959             
1960             callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
1961             
1962             for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1963               if (tmp_pte[k].present) {
1964                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1965                 callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
1966               }
1967
1968               vaddr += PAGE_SIZE_4KB;
1969             }
1970           }
1971         } else {
1972           vaddr += PAGE_SIZE_2MB;
1973         }
1974       }
1975     } else {
1976       vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1977     }
1978   }
1979   return 0;
1980 }
1981                         
1982
1983 int v3_walk_host_pt_64(v3_reg_t host_cr3,
1984                        int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1985                        void * private_data) {
1986   pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1987   addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
1988   int i, j, k, m;
1989   addr_t vaddr = 0;
1990
1991   if (!callback) {
1992     PrintError("Callback was not specified\n");
1993     return -1;
1994   }
1995
1996   callback(PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data);
1997
1998   for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1999     if (host_pml[i].present) {
2000       addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
2001       pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
2002
2003       callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data);
2004
2005       for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
2006         if (tmp_pdpe[j].present) {
2007           if (tmp_pdpe[j].large_page) {
2008             pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
2009             addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
2010
2011             callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
2012
2013             vaddr += PAGE_SIZE_1GB;
2014           } else {
2015             addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
2016             pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
2017
2018             callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data);
2019
2020             for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
2021               if (tmp_pde[k].present) {
2022                 if (tmp_pde[k].large_page) {
2023                   pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
2024                   addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
2025                   
2026                   callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data);
2027                   
2028                   vaddr += PAGE_SIZE_2MB;
2029                 } else {
2030                   addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
2031                   pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
2032
2033                   callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data);
2034
2035                   for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
2036                     if (tmp_pte[m].present) {
2037                       addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
2038                       callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data);
2039                     }
2040                     vaddr += PAGE_SIZE_4KB;
2041                   }
2042                 }
2043               } else {
2044                 vaddr += PAGE_SIZE_2MB;
2045               }
2046             }
2047           }
2048         } else {
2049           vaddr += PAGE_SIZE_1GB;
2050         }
2051       }
2052     } else {
2053       vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
2054     }
2055   }
2056   return 0;
2057 }
2058
2059
2060
2061 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
2062 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
2063 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
2064 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
2065 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
2066 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
2067 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
2068 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
2069 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
2070 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
2071 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
2072 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
2073 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
2074
2075
2076 const uchar_t * v3_page_type_to_str(page_type_t type) {
2077   switch (type) {
2078   case PAGE_4KB:
2079     return PAGE_4KB_STR;
2080   case PAGE_2MB:
2081     return PAGE_2MB_STR;
2082   case PAGE_4MB:
2083     return PAGE_4MB_STR;
2084   case PAGE_1GB:
2085     return PAGE_1GB_STR;
2086   case PAGE_PT32:
2087     return PAGE_PT32_STR;
2088   case PAGE_PD32:
2089     return PAGE_PD32_STR;
2090   case PAGE_PDP32PAE:
2091     return PAGE_PDP32PAE_STR;
2092   case PAGE_PD32PAE:
2093     return PAGE_PD32PAE_STR;
2094   case PAGE_PT32PAE:
2095     return PAGE_PT32PAE_STR;
2096   case PAGE_PML464:
2097     return PAGE_PML464_STR;
2098   case PAGE_PDP64:
2099     return PAGE_PDP64_STR;
2100   case PAGE_PD64:
2101     return PAGE_PD64_STR;
2102   case PAGE_PT64:
2103     return PAGE_PT64_STR;
2104   default:
2105     return NULL;
2106   }
2107 }