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.


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