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.


bug fix to check for illegal memory ranges
[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 V3_CONFIG_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_FreePages((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pde[i].pt_base_addr), 1);
71         }
72     }
73
74     V3_FreePages(V3_PAddr(pde), 1);
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_FreePages((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pde[j].pt_base_addr), 1);
100         }
101
102         V3_FreePages(V3_PAddr(pde), 1);
103     }
104
105     V3_FreePages(V3_PAddr(pdpe), 1);
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_FreePages((void *)(addr_t)BASE_TO_PAGE_ADDR_4KB(pde[k].pt_base_addr), 1);
137             }
138             
139             V3_FreePages(V3_PAddr(pde), 1);
140         }
141
142         V3_FreePages(V3_PAddr(pdpe), 1);
143     }
144
145     V3_FreePages(V3_PAddr(pml4), 1);
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 (v3_gpa_to_hva(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 (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
974                     large_page_va = 0 ;
975                 }
976
977
978                 if ((ret == callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
979                     return (ret == -1) ? -1 : PAGE_4MB;
980                 }
981                 return 0;
982             }
983         case PT_ENTRY_PAGE:
984             {
985                 pte32_t * guest_pte = NULL;
986                 addr_t page_pa;
987
988                 if (v3_gpa_to_hva(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
989                     PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
990                                (void *)guest_pte_pa);
991                     return -1;
992                 }
993
994                 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
995                     return (ret == -1) ? -1 : PAGE_PT32;
996                 }
997
998                 if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
999                     return -1;
1000                 } else {
1001                     addr_t page_va;
1002
1003                     if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1004                         page_va = 0;
1005                     }
1006
1007                     if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1008                         return (ret == -1) ? -1 : PAGE_4KB;
1009                     }
1010                     return 0;
1011                 }
1012             }
1013     }
1014
1015     // should never get here
1016     PrintError("End of drill function (guest 32)... Should never have gotten here...\n");
1017     return -1;
1018 }
1019
1020
1021
1022 int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr,
1023                             int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1024                             void * private_data) {                      
1025     addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1026     pdpe32pae_t * guest_pdpe = 0;
1027     addr_t guest_pde_pa = 0;
1028     int ret = 0;
1029
1030     if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
1031         PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
1032                    (void *)guest_pdpe_pa);
1033         return -1;
1034     }
1035
1036     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1037         return (ret == -1) ? -1 : PAGE_PDP32PAE;
1038     }
1039
1040     switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
1041         {
1042             case PT_ENTRY_NOT_PRESENT:
1043                 return -1;
1044             case PT_ENTRY_PAGE:
1045                 {
1046                     pde32pae_t * guest_pde = NULL;
1047                     addr_t guest_pte_pa = 0;
1048         
1049                     if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1050                         PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
1051                                    (void *)guest_pde_pa);
1052                         return -1;
1053                     }
1054
1055                     if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1056                         return (ret == -1) ? -1 : PAGE_PD32PAE;
1057                     }
1058         
1059                     switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
1060                         {
1061                             case PT_ENTRY_NOT_PRESENT:
1062                                 return -1;
1063                             case PT_ENTRY_LARGE_PAGE:
1064                                 {
1065                                     addr_t large_page_pa = (addr_t)guest_pte_pa;
1066                                     addr_t large_page_va = 0;
1067               
1068                                     if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1069                                         large_page_va = 0;
1070                                     }
1071               
1072                                     if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1073                                         return (ret == -1) ? -1 : PAGE_2MB;
1074                                     }
1075                                     return 0;
1076                                 }
1077                             case PT_ENTRY_PAGE:
1078                                 {
1079                                     pte32pae_t * guest_pte = NULL;
1080                                     addr_t page_pa;
1081
1082                                     if (v3_gpa_to_hva(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1083                                         PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
1084                                                    (void *)guest_pte_pa);
1085                                         return -1;
1086                                     }
1087
1088                                     if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1089                                         return (ret == -1) ? -1 : PAGE_PT32PAE;
1090                                     }
1091
1092                                     if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1093                                         return -1;
1094                                     } else {
1095                                         addr_t page_va;
1096                 
1097                                         if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1098                                             page_va = 0;
1099                                         }
1100                 
1101                                         if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1102                                             return (ret == -1) ? -1 : PAGE_4KB;
1103                                         }
1104                                         return 0;
1105                                     }
1106                                 }
1107                         }
1108                 }
1109             default:
1110                 PrintError("Invalid page type for PD32PAE\n");
1111                 return -1;
1112         }
1113
1114     // should never get here
1115     PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n");
1116     return -1;
1117 }
1118
1119 int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1120                          int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1121                          void * private_data) { 
1122     addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
1123     pml4e64_t * guest_pmle = 0;
1124     addr_t guest_pdpe_pa = 0;
1125     int ret = 0;
1126
1127     if (v3_gpa_to_hva(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
1128         PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
1129                    (void *)guest_pml4_pa);
1130         return -1;
1131     }
1132   
1133     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) {
1134         return (ret == -1) ? -1 : PAGE_PML464;
1135     }
1136
1137     switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1138         case PT_ENTRY_NOT_PRESENT:
1139             return -1;
1140         case PT_ENTRY_PAGE:
1141             {
1142                 pdpe64_t * guest_pdp = NULL;
1143                 addr_t guest_pde_pa = 0;
1144
1145                 if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
1146                     PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1147                                (void *)guest_pdpe_pa);
1148                     return -1;
1149                 }
1150
1151                 if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) {
1152                     return (ret == -1) ? -1 : PAGE_PDP64;
1153                 }
1154
1155                 switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1156                     case PT_ENTRY_NOT_PRESENT:
1157                         return -1;
1158                     case PT_ENTRY_LARGE_PAGE:
1159                         {
1160                             addr_t large_page_pa = (addr_t)guest_pde_pa;
1161                             addr_t large_page_va = 0;
1162           
1163                             if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1164                                 large_page_va = 0;
1165                             }
1166           
1167                             if ((ret == callback(info, PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1168                                 return (ret == -1) ? -1 : PAGE_1GB;
1169                             }
1170                             PrintError("1 Gigabyte Pages not supported\n");
1171                             return 0;
1172                         }
1173                     case PT_ENTRY_PAGE:
1174                         {
1175                             pde64_t * guest_pde = NULL;
1176                             addr_t guest_pte_pa = 0;
1177
1178                             if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1179                                 PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", 
1180                                            (void *)guest_pde_pa);
1181                                 return -1;
1182                             }
1183         
1184                             if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1185                                 return (ret == -1) ? -1 : PAGE_PD64;
1186                             }
1187
1188                             switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1189                                 case PT_ENTRY_NOT_PRESENT:
1190                                     return -1;
1191                                 case PT_ENTRY_LARGE_PAGE:
1192                                     {
1193                                         addr_t large_page_pa = (addr_t)guest_pte_pa;
1194                                         addr_t large_page_va = 0;
1195               
1196                                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1197                                             large_page_va = 0;
1198                                         }
1199               
1200                                         if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1201                                             return (ret == -1) ? -1 : PAGE_2MB;
1202                                         }
1203                                         return 0;
1204                                     }
1205                                 case PT_ENTRY_PAGE:
1206                                     {
1207                                         pte64_t * guest_pte = NULL;
1208                                         addr_t page_pa;
1209               
1210                                         if (v3_gpa_to_hva(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1211                                             PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", 
1212                                                        (void *)guest_pte_pa);
1213                                             return -1;
1214                                         }
1215
1216                                         if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) {
1217                                             return (ret == -1) ? -1 : PAGE_PT64;
1218                                         }
1219                 
1220                                         if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1221                                             return -1;
1222                                         } else {
1223                                             addr_t page_va;
1224                 
1225                                             if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1226                                                 page_va = 0;
1227                                             }
1228                 
1229                                             if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1230                                                 return (ret == -1) ? -1 : PAGE_4KB;
1231                                             }
1232
1233                                             return 0;
1234                                         }
1235                                     }
1236                             }
1237                         }
1238                 }
1239             }
1240         default:
1241             return -1;
1242     }
1243
1244     // should never get here
1245     PrintError("End of drill function (guest 64)... Should never have gotten here...\n");
1246     return -1;
1247 }
1248
1249
1250
1251
1252 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1253                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1254                         void * private_data) {
1255     addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1256     pde32_t * guest_pde = NULL;
1257     int i, j;
1258     addr_t vaddr = 0;
1259     int ret = 0;
1260
1261     if (!callback) {
1262         PrintError("Call back was not specified\n");
1263         return -1;
1264     }
1265
1266     if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1267         PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1268                    (void *)guest_pde_pa);
1269         return -1;
1270     }
1271
1272     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1273         return ret;
1274     }
1275
1276     for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1277         if (guest_pde[i].present) {
1278             if (guest_pde[i].large_page) {
1279                 pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1280                 addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1281                 addr_t large_page_va = 0;
1282
1283                 if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1284                     PrintDebug("Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1285                                (void *)large_page_pa);
1286                     // We'll let it through for data pages because they may be unmapped or hooked
1287                     large_page_va = 0;
1288                 }
1289
1290                 if ((ret = callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1291                     return ret;
1292                 }
1293
1294                 vaddr += PAGE_SIZE_4MB;
1295             } else {
1296                 addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1297                 pte32_t * tmp_pte = NULL;
1298
1299                 if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1300                     PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1301                                (void *)pte_pa);
1302                     return -1;
1303                 }
1304
1305                 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1306                     return ret;
1307                 }
1308
1309                 for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1310                     if (tmp_pte[j].present) {
1311                         addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1312                         addr_t page_va = 0;
1313
1314                         if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1315                             PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1316                                        (void *)page_pa);
1317                             // We'll let it through for data pages because they may be unmapped or hooked
1318                             page_va = 0;
1319                         }
1320             
1321                         if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1322                             return ret;
1323                         }
1324                     }
1325
1326                     vaddr += PAGE_SIZE_4KB;
1327                 }
1328             }
1329         } else {
1330             vaddr += PAGE_SIZE_4MB;
1331         }
1332     }
1333     return 0;
1334 }
1335
1336
1337 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1338                            int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1339                            void * private_data) {
1340     addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1341     pdpe32pae_t * guest_pdpe = NULL;
1342     int i, j, k;
1343     addr_t vaddr = 0;
1344     int ret = 0;
1345
1346     if (!callback) {
1347         PrintError("Call back was not specified\n");
1348         return -1;
1349     }
1350
1351     if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1352         PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1353                    (void *)guest_pdpe_pa);
1354         return -1;
1355     }
1356
1357   
1358     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1359         return ret;
1360     }
1361
1362     for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1363         if (guest_pdpe[i].present) {
1364             addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1365             pde32pae_t * tmp_pde = NULL;
1366
1367             if (v3_gpa_to_hva(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1368                 PrintError("Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1369                            (void *)pde_pa);
1370                 return -1;
1371             }
1372
1373             if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1374                 return ret;
1375             }
1376       
1377             for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1378                 if (tmp_pde[j].present) {
1379                     if (tmp_pde[j].large_page) {
1380                         pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1381                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1382                         addr_t large_page_va = 0;
1383             
1384                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1385                             PrintDebug("Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1386                                        (void *)large_page_pa);
1387                             // We'll let it through for data pages because they may be unmapped or hooked
1388                             large_page_va = 0;
1389                         }
1390             
1391                         if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1392                             return ret;
1393                         }
1394
1395                         vaddr += PAGE_SIZE_2MB;
1396                     } else {
1397                         addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1398                         pte32pae_t * tmp_pte = NULL;
1399             
1400                         if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1401                             PrintError("Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1402                                        (void *)pte_pa);
1403                             return -1;
1404                         }
1405             
1406                         if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1407                             return ret;
1408                         }
1409             
1410                         for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1411                             if (tmp_pte[k].present) {
1412                                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1413                                 addr_t page_va = 0;
1414                 
1415                                 if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1416                                     PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1417                                                (void *)page_pa);
1418                                     // We'll let it through for data pages because they may be unmapped or hooked
1419                                     page_va = 0;
1420                                 }
1421                 
1422                                 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1423                                     return ret;
1424                                 }
1425                             }
1426               
1427                             vaddr += PAGE_SIZE_4KB;
1428                         }
1429                     }
1430                 } else {
1431                     vaddr += PAGE_SIZE_2MB;
1432                 }
1433             }
1434         } else {
1435             vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1436         }
1437     }
1438     return 0;
1439 }
1440
1441
1442
1443
1444 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1445                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1446                         void * private_data) {
1447     addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1448     pml4e64_t * guest_pml = NULL;
1449     int i, j, k, m;
1450     addr_t vaddr = 0;
1451     int ret = 0;
1452
1453     if (!callback) {
1454         PrintError("Call back was not specified\n");
1455         return -1;
1456     }
1457
1458     if (v3_gpa_to_hva(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1459         PrintError("Could not get virtual address of Guest PML464 (PA=%p)\n", 
1460                    (void *)guest_pml);
1461         return -1;
1462     }
1463
1464
1465     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data)) != 0) {
1466         return ret;
1467     }
1468
1469     for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1470         if (guest_pml[i].present) {
1471             addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1472             pdpe64_t * tmp_pdpe = NULL;
1473       
1474       
1475             if (v3_gpa_to_hva(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1476                 PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1477                            (void *)pdpe_pa);
1478                 return -1;
1479             }
1480       
1481             if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
1482                 return ret;
1483             }
1484       
1485             for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1486                 if (tmp_pdpe[j].present) {
1487                     if (tmp_pdpe[j].large_page) {
1488                         pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1489                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1490                         addr_t large_page_va = 0;
1491
1492                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1493                             PrintDebug("Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1494                                        (void *)large_page_pa);
1495                             // We'll let it through for data pages because they may be unmapped or hooked
1496                             large_page_va = 0;
1497                         }
1498
1499                         if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data)) != 0) {
1500                             return ret;
1501                         }
1502
1503                         vaddr += PAGE_SIZE_1GB;
1504                     } else {
1505                         addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1506                         pde64_t * tmp_pde = NULL;
1507             
1508                         if (v3_gpa_to_hva(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1509                             PrintError("Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1510                                        (void *)pde_pa);
1511                             return -1;
1512                         }
1513             
1514                         if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1515                             return ret;
1516                         }
1517             
1518                         for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1519                             if (tmp_pde[k].present) {
1520                                 if (tmp_pde[k].large_page) {
1521                                     pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1522                                     addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1523                                     addr_t large_page_va = 0;
1524                   
1525                                     if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1526                                         PrintDebug("Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1527                                                    (void *)large_page_pa);
1528                                         // We'll let it through for data pages because they may be unmapped or hooked
1529                                         large_page_va = 0;
1530                                     }
1531                   
1532                                     if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1533                                         return ret;
1534                                     }
1535
1536                                     vaddr += PAGE_SIZE_2MB;
1537                                 } else {
1538                                     addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1539                                     pte64_t * tmp_pte = NULL;
1540                   
1541                                     if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1542                                         PrintError("Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1543                                                    (void *)pte_pa);
1544                                         return -1;
1545                                     }
1546                   
1547                                     if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1548                                         return ret;
1549                                     }
1550                   
1551                                     for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1552                                         if (tmp_pte[m].present) {
1553                                             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1554                                             addr_t page_va = 0;
1555                       
1556                                             if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1557                                                 PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1558                                                            (void *)page_pa);
1559                                                 // We'll let it through for data pages because they may be unmapped or hooked
1560                                                 page_va = 0;
1561                                             }
1562                       
1563                                             if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1564                                                 return ret;
1565                                             }
1566                                         }
1567
1568                                         vaddr += PAGE_SIZE_4KB;
1569                                     }
1570                                 }
1571                             } else {
1572                                 vaddr += PAGE_SIZE_2MB;
1573                             }
1574                         }
1575                     }
1576                 } else {
1577                     vaddr += PAGE_SIZE_1GB;
1578                 }
1579             }
1580         } else {
1581             vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
1582         }
1583     }
1584     return 0;
1585 }
1586
1587 int v3_walk_host_pt_32(struct guest_info * info, v3_reg_t host_cr3,
1588                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1589                        void * private_data) {
1590     pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1591     addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1592     int i, j;
1593     addr_t vaddr = 0;
1594     int ret = 0;
1595
1596     if (!callback) {
1597         PrintError("Call back was not specified\n");
1598         return -1;
1599     }
1600
1601     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data)) != 0) {
1602         return ret;
1603     }
1604
1605     for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1606         if (host_pde[i].present) {
1607             if (host_pde[i].large_page) {
1608                 pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1609                 addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1610
1611                 if ((ret = callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1612                     return ret;
1613                 }
1614
1615                 vaddr += PAGE_SIZE_4MB;
1616             } else {
1617                 addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1618                 pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1619
1620                 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1621                     return ret;
1622                 }
1623
1624                 for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1625                     if (tmp_pte[j].present) {
1626                         addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1627                         if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1628                             return ret;
1629                         }
1630                     }
1631
1632                     vaddr += PAGE_SIZE_4KB;
1633                 }
1634             }
1635         } else {
1636             vaddr += PAGE_SIZE_4MB;
1637         }
1638     }
1639     return 0;
1640 }
1641
1642
1643
1644
1645
1646 int v3_walk_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3,
1647                           int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1648                           void * private_data) {
1649     pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1650     addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1651     int i, j, k;
1652     addr_t vaddr = 0;
1653     int ret = 0;
1654
1655     if (!callback) {
1656         PrintError("Callback was not specified\n");
1657         return -1;
1658     }
1659   
1660     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data)) != 0) {
1661         return ret;
1662     }
1663   
1664     for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1665         if (host_pdpe[i].present) {     
1666             addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
1667             pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
1668       
1669             if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1670                 return ret;
1671             }
1672       
1673             for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1674                 if (tmp_pde[j].present) {
1675           
1676                     if (tmp_pde[j].large_page) {
1677                         pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1678                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1679
1680                         if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1681                             return ret;
1682                         }
1683
1684                         vaddr += PAGE_SIZE_2MB;
1685                     } else {
1686                         addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1687                         pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
1688             
1689                         if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1690                             return ret;
1691                         }
1692             
1693                         for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1694                             if (tmp_pte[k].present) {
1695                                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1696                                 if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1697                                     return ret;
1698                                 }
1699                             }
1700
1701                             vaddr += PAGE_SIZE_4KB;
1702                         }
1703                     }
1704                 } else {
1705                     vaddr += PAGE_SIZE_2MB;
1706                 }
1707             }
1708         } else {
1709             vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1710         }
1711     }
1712     return 0;
1713 }
1714                         
1715
1716 int v3_walk_host_pt_64(struct guest_info * info, v3_reg_t host_cr3,
1717                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1718                        void * private_data) {
1719     pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1720     addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
1721     int i, j, k, m;
1722     addr_t vaddr = 0;
1723     int ret = 0;
1724
1725     if (!callback) {
1726         PrintError("Callback was not specified\n");
1727         return -1;
1728     }
1729
1730     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data)) != 0) {
1731         return ret;
1732     }
1733
1734     for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1735         if (host_pml[i].present) {
1736             addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
1737             pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
1738
1739             if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
1740                 return ret;
1741             }
1742
1743             for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1744                 if (tmp_pdpe[j].present) {
1745                     if (tmp_pdpe[j].large_page) {
1746                         pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1747                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
1748
1749                         if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1750                             return ret;
1751                         }
1752
1753                         vaddr += PAGE_SIZE_1GB;
1754                     } else {
1755                         addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1756                         pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
1757
1758                         if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1759                             return ret;
1760                         }
1761
1762                         for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1763                             if (tmp_pde[k].present) {
1764                                 if (tmp_pde[k].large_page) {
1765                                     pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1766                                     addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1767                   
1768                                     if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1769                                         return ret;
1770                                     }
1771                   
1772                                     vaddr += PAGE_SIZE_2MB;
1773                                 } else {
1774                                     addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1775                                     pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
1776
1777                                     if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1778                                         return ret;
1779                                     }
1780
1781                                     for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1782                                         if (tmp_pte[m].present) {
1783                                             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1784                                             if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1785                                                 return ret;
1786                                             }
1787                                         }
1788                                         vaddr += PAGE_SIZE_4KB;
1789                                     }
1790                                 }
1791                             } else {
1792                                 vaddr += PAGE_SIZE_2MB;
1793                             }
1794                         }
1795                     }
1796                 } else {
1797                     vaddr += PAGE_SIZE_1GB;
1798                 }
1799             }
1800         } else {
1801             vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
1802         }
1803     }
1804     return 0;
1805 }
1806
1807
1808
1809 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
1810 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
1811 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
1812 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
1813 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
1814 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
1815 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
1816 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
1817 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
1818 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
1819 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
1820 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
1821 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
1822
1823
1824 const uchar_t * v3_page_type_to_str(page_type_t type) {
1825     switch (type) {
1826         case PAGE_4KB:
1827             return PAGE_4KB_STR;
1828         case PAGE_2MB:
1829             return PAGE_2MB_STR;
1830         case PAGE_4MB:
1831             return PAGE_4MB_STR;
1832         case PAGE_1GB:
1833             return PAGE_1GB_STR;
1834         case PAGE_PT32:
1835             return PAGE_PT32_STR;
1836         case PAGE_PD32:
1837             return PAGE_PD32_STR;
1838         case PAGE_PDP32PAE:
1839             return PAGE_PDP32PAE_STR;
1840         case PAGE_PD32PAE:
1841             return PAGE_PD32PAE_STR;
1842         case PAGE_PT32PAE:
1843             return PAGE_PT32PAE_STR;
1844         case PAGE_PML464:
1845             return PAGE_PML464_STR;
1846         case PAGE_PDP64:
1847             return PAGE_PDP64_STR;
1848         case PAGE_PD64:
1849             return PAGE_PD64_STR;
1850         case PAGE_PT64:
1851             return PAGE_PT64_STR;
1852         default:
1853             return NULL;
1854     }
1855 }