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.


Cleanup and sanity-checking of switch issues, negative array indexes, operand indepen...
[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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE, "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(VM_NONE, VCORE_NONE,"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(info->vm_info, info, "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(info->vm_info, info, "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(info->vm_info, info, "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(info->vm_info, info, "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(info->vm_info, info, "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(info->vm_info, info, "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(info->vm_info, info, "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(VM_NONE, VCORE_NONE, "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         pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)pdpe_entry;
660
661         *entry = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
662
663         return PT_ENTRY_LARGE_PAGE;
664     } else {
665         *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
666         return PT_ENTRY_PAGE;
667     }
668 }
669
670 static pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) {
671     pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]);
672
673     if (!pde_entry->present) {
674         *entry = 0;
675         return PT_ENTRY_NOT_PRESENT;
676     } else if (pde_entry->large_page) {
677         pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
678
679         *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
680
681         return PT_ENTRY_LARGE_PAGE;
682     } else {
683         *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
684         return PT_ENTRY_PAGE;
685     }
686 }
687
688 static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) {
689     pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]);
690
691     if (!pte_entry->present) {
692         *entry = 0;
693         return PT_ENTRY_NOT_PRESENT;
694     } else {
695         *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
696         return PT_ENTRY_PAGE;
697     }
698 }
699
700
701
702
703 static pt_access_status_t can_access_pt_entry(gen_pt_t * pt, pf_error_t access_type) {
704     if (pt->present == 0) {
705         return PT_ACCESS_NOT_PRESENT;
706     } else if ((pt->writable == 0) && (access_type.write == 1)) {
707         return PT_ACCESS_WRITE_ERROR;
708     } else if ((pt->user_page == 0) && (access_type.user == 1)) {
709         // Check CR0.WP?
710         return PT_ACCESS_USER_ERROR;
711     }
712
713     return PT_ACCESS_OK;
714 }
715
716
717
718 /*
719  *   32 bit access checks
720  */
721 pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) {
722     gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)];
723     return can_access_pt_entry(entry, access_type);
724 }
725
726 pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) {
727     gen_pt_t * entry = (gen_pt_t *)&pte[PTE32_INDEX(addr)];
728     return can_access_pt_entry(entry, access_type);
729 }
730
731
732 /*
733  *  32 bit PAE access checks
734  */
735 pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type) {
736     gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE32PAE_INDEX(addr)];
737     return can_access_pt_entry(entry, access_type);
738 }
739
740 pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type) {
741     gen_pt_t * entry = (gen_pt_t *)&pde[PDE32PAE_INDEX(addr)];
742     return can_access_pt_entry(entry, access_type);
743 }
744
745 pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type) {
746     gen_pt_t * entry = (gen_pt_t *)&pte[PTE32PAE_INDEX(addr)];
747     return can_access_pt_entry(entry, access_type);
748 }
749
750 /*
751  *   64 Bit access checks
752  */
753 pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type) {
754     gen_pt_t * entry = (gen_pt_t *)&pmle[PML4E64_INDEX(addr)];
755     return can_access_pt_entry(entry, access_type);
756 }
757
758 pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type) {
759     gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE64_INDEX(addr)];
760     return can_access_pt_entry(entry, access_type);
761 }
762
763 pt_access_status_t inline v3_can_access_pde64(pde64_t * pde, addr_t addr, pf_error_t access_type) {
764     gen_pt_t * entry = (gen_pt_t *)&pde[PDE64_INDEX(addr)];
765     return can_access_pt_entry(entry, access_type);
766 }
767
768 pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_error_t access_type) {
769     gen_pt_t * entry = (gen_pt_t *)&pte[PTE64_INDEX(addr)];
770     return can_access_pt_entry(entry, access_type);
771 }
772
773
774
775
776
777
778 int v3_drill_host_pt_32(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr, 
779                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
780                         void * private_data) {
781     pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
782     addr_t host_pde_pa = CR3_TO_PDE32_PA(host_cr3);
783     addr_t host_pte_pa = 0;
784     addr_t page_pa = 0;
785     int ret;
786
787     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, host_pde_pa, private_data)) != 0) {
788         return (ret == -1) ? -1 : PAGE_PD32;
789     }
790
791     switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) {
792         case PT_ENTRY_NOT_PRESENT:
793             return -1;
794         case PT_ENTRY_LARGE_PAGE:
795             if ((ret = callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
796                 return (ret == -1) ? -1 : PAGE_4MB;
797             }
798             return 0;
799         case PT_ENTRY_PAGE:
800             if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
801                 return (ret == -1) ? -1 : PAGE_PT32;
802             }
803     
804             if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
805                 return -1;
806             } else {
807                 if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
808                     return (ret == -1) ? -1 : PAGE_4KB;
809                 }
810                 return 0;
811             }
812     }
813     return -1;
814 }
815
816
817
818 int v3_drill_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr,
819                            int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
820                            void * private_data) {
821     pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
822     addr_t host_pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
823     addr_t host_pde_pa = 0;
824     addr_t host_pte_pa = 0;
825     addr_t page_pa = 0;
826     int ret;
827
828     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, host_pdpe_pa, private_data)) != 0) {
829         return (ret == -1) ? -1 : PAGE_PDP32PAE;
830     }
831
832     switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) {
833         case PT_ENTRY_NOT_PRESENT:
834             return -1;
835         case PT_ENTRY_PAGE:
836
837             if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
838                 return (ret == -1) ? -1 : PAGE_PD32PAE;
839             }
840       
841             switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
842                 case PT_ENTRY_NOT_PRESENT:
843                     return -1;
844                 case PT_ENTRY_LARGE_PAGE:
845                     if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
846                         return (ret == -1) ? -1 : PAGE_2MB;
847                     }
848                     return 0;
849                 case PT_ENTRY_PAGE:
850                     if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
851                         return (ret == -1) ? -1 : PAGE_PT32PAE;
852                     }
853
854                     if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
855                         return -1;
856                     } else {
857                         if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
858                             return (ret == -1) ? -1 : PAGE_4KB;
859                         }
860                         return 0;
861                     } 
862             }
863         default:
864             return -1;
865     }
866
867     // should never get here
868     return -1;
869 }
870
871
872 int v3_drill_host_pt_64(struct guest_info * info, v3_reg_t host_cr3, addr_t vaddr,
873                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
874                         void * private_data) {
875     pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
876     addr_t host_pmle_pa = CR3_TO_PML4E64_PA(host_cr3);
877     addr_t host_pdpe_pa = 0;
878     addr_t host_pde_pa = 0;
879     addr_t host_pte_pa = 0;
880     addr_t page_pa = 0;
881     int ret;
882
883     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pmle, host_pmle_pa, private_data)) != 0) {
884         return (ret == -1) ? -1 : PAGE_PML464;
885     }
886
887     switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) {
888         case PT_ENTRY_NOT_PRESENT:
889             return -1;
890         case PT_ENTRY_PAGE:
891
892             if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)V3_VAddr((void *)host_pdpe_pa), host_pdpe_pa, private_data)) != 0) {
893                 return (ret == -1) ? -1 : PAGE_PDP64;
894             }
895
896             switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) {
897                 case PT_ENTRY_NOT_PRESENT:
898                     return -1;
899                 case PT_ENTRY_LARGE_PAGE:
900                     if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
901                         return (ret == -1) ? -1 : PAGE_1GB;
902                     }
903                     PrintError(info->vm_info, info, "1 Gigabyte Pages not supported\n");
904                     return 0;
905                 case PT_ENTRY_PAGE:
906
907                     if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) {
908                         return (ret == -1) ? -1 : PAGE_PD64;
909                     }
910
911                     switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
912                         case PT_ENTRY_NOT_PRESENT:
913                             return -1;
914                         case PT_ENTRY_LARGE_PAGE:
915                             if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
916                                 return (ret == -1) ? -1 : PAGE_2MB;
917                             }
918                             return 0;
919                         case PT_ENTRY_PAGE:
920
921                             if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) {
922                                 return (ret == -1) ? -1 : PAGE_PT64;
923                             }
924
925                             if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
926                                 return -1;
927                             } else {
928                                 if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) {
929                                     return (ret == -1) ? -1 : PAGE_4KB;
930                                 }
931                                 return 0;
932                             }
933                     }
934             }
935         default:
936             return -1;
937     }
938     // should never get here
939     return -1;
940 }
941
942
943
944
945
946
947
948 int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
949                          int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
950                          void * private_data) {
951     addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
952     pde32_t * guest_pde = NULL;
953     addr_t guest_pte_pa = 0;
954     int ret; 
955   
956
957     if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
958         PrintError(info->vm_info, info, "Could not get virtual address of Guest PDE32 (PA=%p)\n", 
959                    (void *)guest_pde_pa);
960         return -1;
961     }
962   
963     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
964         return (ret == -1) ? -1 : PAGE_PD32;
965     }
966   
967     switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
968         case PT_ENTRY_NOT_PRESENT:
969             return -1;
970         case PT_ENTRY_LARGE_PAGE:
971             {
972                 addr_t large_page_pa = (addr_t)guest_pte_pa;
973                 addr_t large_page_va = 0;
974       
975                 if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
976                     large_page_va = 0 ;
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 (v3_gpa_to_hva(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) {
991                     PrintError(info->vm_info, info, "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 (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1006                         page_va = 0;
1007                     }
1008
1009                     if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1010                         return (ret == -1) ? -1 : PAGE_4KB;
1011                     }
1012                     return 0;
1013                 }
1014             }
1015     }
1016
1017     // should never get here
1018     PrintError(info->vm_info, info, "End of drill function (guest 32)... Should never have gotten here...\n");
1019     return -1;
1020 }
1021
1022
1023
1024 int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr,
1025                             int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1026                             void * private_data) {                      
1027     addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1028     pdpe32pae_t * guest_pdpe = 0;
1029     addr_t guest_pde_pa = 0;
1030     int ret = 0;
1031
1032     if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) {
1033         PrintError(info->vm_info, info, "Could not get virtual address of Guest PDPE32PAE (PA=%p)\n",
1034                    (void *)guest_pdpe_pa);
1035         return -1;
1036     }
1037
1038     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1039         return (ret == -1) ? -1 : PAGE_PDP32PAE;
1040     }
1041
1042     switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) 
1043         {
1044             case PT_ENTRY_NOT_PRESENT:
1045                 return -1;
1046                 break; 
1047             case PT_ENTRY_PAGE:
1048                 {
1049                     pde32pae_t * guest_pde = NULL;
1050                     addr_t guest_pte_pa = 0;
1051         
1052                     if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1053                         PrintError(info->vm_info, info, "Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", 
1054                                    (void *)guest_pde_pa);
1055                         return -1;
1056                     }
1057
1058                     if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1059                         return (ret == -1) ? -1 : PAGE_PD32PAE;
1060                     }
1061         
1062                     switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) 
1063                         {
1064                             case PT_ENTRY_NOT_PRESENT:
1065                                 return -1;
1066                                 break;
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 (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1073                                         large_page_va = 0;
1074                                     }
1075               
1076                                     if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1077                                         return (ret == -1) ? -1 : PAGE_2MB;
1078                                     }
1079                                     return 0;
1080                                 }
1081                                 break;
1082                             case PT_ENTRY_PAGE:
1083                                 {
1084                                     pte32pae_t * guest_pte = NULL;
1085                                     addr_t page_pa;
1086
1087                                     if (v3_gpa_to_hva(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1088                                         PrintError(info->vm_info, info, "Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", 
1089                                                    (void *)guest_pte_pa);
1090                                         return -1;
1091                                     }
1092
1093                                     if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data)) != 0) {
1094                                         return (ret == -1) ? -1 : PAGE_PT32PAE;
1095                                     }
1096
1097                                     if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1098                                         return -1;
1099                                     } else {
1100                                         addr_t page_va;
1101                 
1102                                         if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1103                                             page_va = 0;
1104                                         }
1105                 
1106                                         if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1107                                             return (ret == -1) ? -1 : PAGE_4KB;
1108                                         }
1109                                         return 0;
1110                                     }
1111                                 }
1112                                 break;
1113                         }
1114                 }
1115                 break;
1116             default:
1117                 PrintError(info->vm_info, info, "Invalid page type for PD32PAE\n");
1118                 return -1;
1119         }
1120
1121     // should never get here
1122     PrintError(info->vm_info, info, "End of drill function (guest 32pae)... Should never have gotten here...\n");
1123     return -1;
1124 }
1125
1126 int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, 
1127                          int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1128                          void * private_data) { 
1129     addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3);
1130     pml4e64_t * guest_pmle = 0;
1131     addr_t guest_pdpe_pa = 0;
1132     int ret = 0;
1133
1134     if (v3_gpa_to_hva(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) {
1135         PrintError(info->vm_info, info, "Could not get virtual address of Guest PML4E64 (PA=%p)\n", 
1136                    (void *)guest_pml4_pa);
1137         return -1;
1138     }
1139   
1140     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) {
1141         return (ret == -1) ? -1 : PAGE_PML464;
1142     }
1143
1144     switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1145         case PT_ENTRY_NOT_PRESENT:
1146             return -1;
1147         case PT_ENTRY_PAGE:
1148             {
1149                 pdpe64_t * guest_pdp = NULL;
1150                 addr_t guest_pde_pa = 0;
1151
1152                 if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) {
1153                     PrintError(info->vm_info, info, "Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1154                                (void *)guest_pdpe_pa);
1155                     return -1;
1156                 }
1157
1158                 if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) {
1159                     return (ret == -1) ? -1 : PAGE_PDP64;
1160                 }
1161
1162                 switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1163                     case PT_ENTRY_NOT_PRESENT:
1164                         return -1;
1165                     case PT_ENTRY_LARGE_PAGE:
1166                         {
1167                             addr_t large_page_pa = (addr_t)guest_pde_pa;
1168                             addr_t large_page_va = 0;
1169           
1170                             if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1171                                 large_page_va = 0;
1172                             }
1173           
1174                             if ((ret = callback(info, PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1175                                 return (ret == -1) ? -1 : PAGE_1GB;
1176                             }
1177                             PrintError(info->vm_info, info, "1 Gigabyte Pages not supported\n");
1178                             return 0;
1179                         }
1180                     case PT_ENTRY_PAGE:
1181                         {
1182                             pde64_t * guest_pde = NULL;
1183                             addr_t guest_pte_pa = 0;
1184
1185                             if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1186                                 PrintError(info->vm_info, info, "Could not get virtual address of guest PDE64 (PA=%p)\n", 
1187                                            (void *)guest_pde_pa);
1188                                 return -1;
1189                             }
1190         
1191                             if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1192                                 return (ret == -1) ? -1 : PAGE_PD64;
1193                             }
1194
1195                             switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1196                                 case PT_ENTRY_NOT_PRESENT:
1197                                     return -1;
1198                                 case PT_ENTRY_LARGE_PAGE:
1199                                     {
1200                                         addr_t large_page_pa = (addr_t)guest_pte_pa;
1201                                         addr_t large_page_va = 0;
1202               
1203                                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1204                                             large_page_va = 0;
1205                                         }
1206               
1207                                         if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1208                                             return (ret == -1) ? -1 : PAGE_2MB;
1209                                         }
1210                                         return 0;
1211                                     }
1212                                 case PT_ENTRY_PAGE:
1213                                     {
1214                                         pte64_t * guest_pte = NULL;
1215                                         addr_t page_pa;
1216               
1217                                         if (v3_gpa_to_hva(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) {
1218                                             PrintError(info->vm_info, info, "Could not get virtual address of guest PTE64 (PA=%p)\n", 
1219                                                        (void *)guest_pte_pa);
1220                                             return -1;
1221                                         }
1222
1223                                         if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data)) != 0) {
1224                                             return (ret == -1) ? -1 : PAGE_PT64;
1225                                         }
1226                 
1227                                         if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
1228                                             return -1;
1229                                         } else {
1230                                             addr_t page_va;
1231                 
1232                                             if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1233                                                 page_va = 0;
1234                                             }
1235                 
1236                                             if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1237                                                 return (ret == -1) ? -1 : PAGE_4KB;
1238                                             }
1239
1240                                             return 0;
1241                                         }
1242                                     }
1243                             }
1244                         }
1245                 }
1246             }
1247         default:
1248             return -1;
1249     }
1250
1251     // should never get here
1252     PrintError(info->vm_info, info, "End of drill function (guest 64)... Should never have gotten here...\n");
1253     return -1;
1254 }
1255
1256
1257
1258
1259 int v3_walk_guest_pt_32(struct guest_info * info,  v3_reg_t guest_cr3,
1260                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1261                         void * private_data) {
1262     addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3);
1263     pde32_t * guest_pde = NULL;
1264     int i, j;
1265     addr_t vaddr = 0;
1266     int ret = 0;
1267
1268     if (!callback) {
1269         PrintError(info->vm_info, info, "Call back was not specified\n");
1270         return -1;
1271     }
1272
1273     if (v3_gpa_to_hva(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) {
1274         PrintError(info->vm_info, info, "Could not get virtual address of Guest PDE32 (PA=%p)\n", 
1275                    (void *)guest_pde_pa);
1276         return -1;
1277     }
1278
1279     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
1280         return ret;
1281     }
1282
1283     for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1284         if (guest_pde[i].present) {
1285             if (guest_pde[i].large_page) {
1286                 pde32_4MB_t * large_pde = (pde32_4MB_t *)&(guest_pde[i]);
1287                 addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1288                 addr_t large_page_va = 0;
1289
1290                 if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1291                     PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 4MB Page (PA=%p)\n", 
1292                                (void *)large_page_pa);
1293                     // We'll let it through for data pages because they may be unmapped or hooked
1294                     large_page_va = 0;
1295                 }
1296
1297                 if ((ret = callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1298                     return ret;
1299                 }
1300
1301                 vaddr += PAGE_SIZE_4MB;
1302             } else {
1303                 addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1304                 pte32_t * tmp_pte = NULL;
1305
1306                 if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1307                     PrintError(info->vm_info, info, "Could not get virtual address of Guest PTE32 (PA=%p)\n", 
1308                                (void *)pte_pa);
1309                     return -1;
1310                 }
1311
1312                 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1313                     return ret;
1314                 }
1315
1316                 for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1317                     if (tmp_pte[j].present) {
1318                         addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1319                         addr_t page_va = 0;
1320
1321                         if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1322                             PrintDebug(info->vm_info, info, "Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1323                                        (void *)page_pa);
1324                             // We'll let it through for data pages because they may be unmapped or hooked
1325                             page_va = 0;
1326                         }
1327             
1328                         if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1329                             return ret;
1330                         }
1331                     }
1332
1333                     vaddr += PAGE_SIZE_4KB;
1334                 }
1335             }
1336         } else {
1337             vaddr += PAGE_SIZE_4MB;
1338         }
1339     }
1340     return 0;
1341 }
1342
1343
1344 int v3_walk_guest_pt_32pae(struct guest_info * info,  v3_reg_t guest_cr3,
1345                            int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1346                            void * private_data) {
1347     addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3);
1348     pdpe32pae_t * guest_pdpe = NULL;
1349     int i, j, k;
1350     addr_t vaddr = 0;
1351     int ret = 0;
1352
1353     if (!callback) {
1354         PrintError(info->vm_info, info, "Call back was not specified\n");
1355         return -1;
1356     }
1357
1358     if (v3_gpa_to_hva(info, guest_pdpe_pa, (addr_t *)&guest_pdpe) == -1) {
1359         PrintError(info->vm_info, info, "Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", 
1360                    (void *)guest_pdpe_pa);
1361         return -1;
1362     }
1363
1364   
1365     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
1366         return ret;
1367     }
1368
1369     for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1370         if (guest_pdpe[i].present) {
1371             addr_t pde_pa = BASE_TO_PAGE_ADDR(guest_pdpe[i].pd_base_addr);
1372             pde32pae_t * tmp_pde = NULL;
1373
1374             if (v3_gpa_to_hva(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1375                 PrintError(info->vm_info, info, "Could not get virtual address of Guest PDE32PAE (PA=%p)\n", 
1376                            (void *)pde_pa);
1377                 return -1;
1378             }
1379
1380             if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1381                 return ret;
1382             }
1383       
1384             for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1385                 if (tmp_pde[j].present) {
1386                     if (tmp_pde[j].large_page) {
1387                         pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1388                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1389                         addr_t large_page_va = 0;
1390             
1391                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1392                             PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 2MB Page (PA=%p)\n", 
1393                                        (void *)large_page_pa);
1394                             // We'll let it through for data pages because they may be unmapped or hooked
1395                             large_page_va = 0;
1396                         }
1397             
1398                         if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1399                             return ret;
1400                         }
1401
1402                         vaddr += PAGE_SIZE_2MB;
1403                     } else {
1404                         addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1405                         pte32pae_t * tmp_pte = NULL;
1406             
1407                         if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1408                             PrintError(info->vm_info, info, "Could not get virtual address of Guest PTE32PAE (PA=%p)\n", 
1409                                        (void *)pte_pa);
1410                             return -1;
1411                         }
1412             
1413                         if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1414                             return ret;
1415                         }
1416             
1417                         for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1418                             if (tmp_pte[k].present) {
1419                                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1420                                 addr_t page_va = 0;
1421                 
1422                                 if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1423                                     PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1424                                                (void *)page_pa);
1425                                     // We'll let it through for data pages because they may be unmapped or hooked
1426                                     page_va = 0;
1427                                 }
1428                 
1429                                 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1430                                     return ret;
1431                                 }
1432                             }
1433               
1434                             vaddr += PAGE_SIZE_4KB;
1435                         }
1436                     }
1437                 } else {
1438                     vaddr += PAGE_SIZE_2MB;
1439                 }
1440             }
1441         } else {
1442             vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1443         }
1444     }
1445     return 0;
1446 }
1447
1448
1449
1450
1451 int v3_walk_guest_pt_64(struct guest_info * info,  v3_reg_t guest_cr3,
1452                         int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1453                         void * private_data) {
1454     addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3);
1455     pml4e64_t * guest_pml = NULL;
1456     int i, j, k, m;
1457     addr_t vaddr = 0;
1458     int ret = 0;
1459
1460     if (!callback) {
1461         PrintError(info->vm_info, info, "Call back was not specified\n");
1462         return -1;
1463     }
1464
1465     if (v3_gpa_to_hva(info, guest_pml_pa, (addr_t *)&guest_pml) == -1) {
1466         PrintError(info->vm_info, info, "Could not get virtual address of Guest PML464 (PA=%p)\n", 
1467                    (void *)guest_pml);
1468         return -1;
1469     }
1470
1471
1472     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data)) != 0) {
1473         return ret;
1474     }
1475
1476     for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1477         if (guest_pml[i].present) {
1478             addr_t pdpe_pa = BASE_TO_PAGE_ADDR(guest_pml[i].pdp_base_addr);
1479             pdpe64_t * tmp_pdpe = NULL;
1480       
1481       
1482             if (v3_gpa_to_hva(info, pdpe_pa, (addr_t *)&tmp_pdpe) == -1) {
1483                 PrintError(info->vm_info, info, "Could not get virtual address of Guest PDPE64 (PA=%p)\n", 
1484                            (void *)pdpe_pa);
1485                 return -1;
1486             }
1487       
1488             if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
1489                 return ret;
1490             }
1491       
1492             for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1493                 if (tmp_pdpe[j].present) {
1494                     if (tmp_pdpe[j].large_page) {
1495                         pdpe64_1GB_t * large_pdpe = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1496                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdpe->page_base_addr);
1497                         addr_t large_page_va = 0;
1498
1499                         if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1500                             PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 1GB page (PA=%p)\n", 
1501                                        (void *)large_page_pa);
1502                             // We'll let it through for data pages because they may be unmapped or hooked
1503                             large_page_va = 0;
1504                         }
1505
1506                         if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data)) != 0) {
1507                             return ret;
1508                         }
1509
1510                         vaddr += PAGE_SIZE_1GB;
1511                     } else {
1512                         addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1513                         pde64_t * tmp_pde = NULL;
1514             
1515                         if (v3_gpa_to_hva(info, pde_pa, (addr_t *)&tmp_pde) == -1) {
1516                             PrintError(info->vm_info, info, "Could not get virtual address of Guest PDE64 (PA=%p)\n", 
1517                                        (void *)pde_pa);
1518                             return -1;
1519                         }
1520             
1521                         if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1522                             return ret;
1523                         }
1524             
1525                         for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1526                             if (tmp_pde[k].present) {
1527                                 if (tmp_pde[k].large_page) {
1528                                     pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1529                                     addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1530                                     addr_t large_page_va = 0;
1531                   
1532                                     if (v3_gpa_to_hva(info, large_page_pa, &large_page_va) == -1) {
1533                                         PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 2MB page (PA=%p)\n", 
1534                                                    (void *)large_page_pa);
1535                                         // We'll let it through for data pages because they may be unmapped or hooked
1536                                         large_page_va = 0;
1537                                     }
1538                   
1539                                     if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1540                                         return ret;
1541                                     }
1542
1543                                     vaddr += PAGE_SIZE_2MB;
1544                                 } else {
1545                                     addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1546                                     pte64_t * tmp_pte = NULL;
1547                   
1548                                     if (v3_gpa_to_hva(info, pte_pa, (addr_t *)&tmp_pte) == -1) {
1549                                         PrintError(info->vm_info, info, "Could not get virtual address of Guest PTE64 (PA=%p)\n", 
1550                                                    (void *)pte_pa);
1551                                         return -1;
1552                                     }
1553                   
1554                                     if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1555                                         return ret;
1556                                     }
1557                   
1558                                     for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1559                                         if (tmp_pte[m].present) {
1560                                             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1561                                             addr_t page_va = 0;
1562                       
1563                                             if (v3_gpa_to_hva(info, page_pa, &page_va) == -1) {
1564                                                 PrintDebug(info->vm_info, info,"Could not get virtual address of Guest 4KB Page (PA=%p)\n", 
1565                                                            (void *)page_pa);
1566                                                 // We'll let it through for data pages because they may be unmapped or hooked
1567                                                 page_va = 0;
1568                                             }
1569                       
1570                                             if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1571                                                 return ret;
1572                                             }
1573                                         }
1574
1575                                         vaddr += PAGE_SIZE_4KB;
1576                                     }
1577                                 }
1578                             } else {
1579                                 vaddr += PAGE_SIZE_2MB;
1580                             }
1581                         }
1582                     }
1583                 } else {
1584                     vaddr += PAGE_SIZE_1GB;
1585                 }
1586             }
1587         } else {
1588             vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
1589         }
1590     }
1591     return 0;
1592 }
1593
1594 int v3_walk_host_pt_32(struct guest_info * info, v3_reg_t host_cr3,
1595                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1596                        void * private_data) {
1597     pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3);
1598     addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3);
1599     int i, j;
1600     addr_t vaddr = 0;
1601     int ret = 0;
1602
1603     if (!callback) {
1604         PrintError(info->vm_info, info, "Call back was not specified\n");
1605         return -1;
1606     }
1607
1608     if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data)) != 0) {
1609         return ret;
1610     }
1611
1612     for (i = 0; i < MAX_PDE32_ENTRIES; i++) {
1613         if (host_pde[i].present) {
1614             if (host_pde[i].large_page) {
1615                 pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]);
1616                 addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
1617
1618                 if ((ret = callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1619                     return ret;
1620                 }
1621
1622                 vaddr += PAGE_SIZE_4MB;
1623             } else {
1624                 addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr);
1625                 pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa);
1626
1627                 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1628                     return ret;
1629                 }
1630
1631                 for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
1632                     if (tmp_pte[j].present) {
1633                         addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr);
1634                         if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1635                             return ret;
1636                         }
1637                     }
1638
1639                     vaddr += PAGE_SIZE_4KB;
1640                 }
1641             }
1642         } else {
1643             vaddr += PAGE_SIZE_4MB;
1644         }
1645     }
1646     return 0;
1647 }
1648
1649
1650
1651
1652
1653 int v3_walk_host_pt_32pae(struct guest_info * info, v3_reg_t host_cr3,
1654                           int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1655                           void * private_data) {
1656     pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3);
1657     addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3);
1658     int i, j, k;
1659     addr_t vaddr = 0;
1660     int ret = 0;
1661
1662     if (!callback) {
1663         PrintError(info->vm_info, info, "Callback was not specified\n");
1664         return -1;
1665     }
1666   
1667     if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data)) != 0) {
1668         return ret;
1669     }
1670   
1671     for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) {
1672         if (host_pdpe[i].present) {     
1673             addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr);
1674             pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa);
1675       
1676             if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1677                 return ret;
1678             }
1679       
1680             for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1681                 if (tmp_pde[j].present) {
1682           
1683                     if (tmp_pde[j].large_page) {
1684                         pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]);
1685                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1686
1687                         if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1688                             return ret;
1689                         }
1690
1691                         vaddr += PAGE_SIZE_2MB;
1692                     } else {
1693                         addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1694                         pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa);
1695             
1696                         if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1697                             return ret;
1698                         }
1699             
1700                         for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
1701                             if (tmp_pte[k].present) {
1702                                 addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr);
1703                                 if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1704                                     return ret;
1705                                 }
1706                             }
1707
1708                             vaddr += PAGE_SIZE_4KB;
1709                         }
1710                     }
1711                 } else {
1712                     vaddr += PAGE_SIZE_2MB;
1713                 }
1714             }
1715         } else {
1716             vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
1717         }
1718     }
1719     return 0;
1720 }
1721                         
1722
1723 int v3_walk_host_pt_64(struct guest_info * info, v3_reg_t host_cr3,
1724                        int (*callback)(struct guest_info * info, page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data),
1725                        void * private_data) {
1726     pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3);
1727     addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3);
1728     int i, j, k, m;
1729     addr_t vaddr = 0;
1730     int ret = 0;
1731
1732     if (!callback) {
1733         PrintError(info->vm_info, info, "Callback was not specified\n");
1734         return -1;
1735     }
1736
1737     if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data)) != 0) {
1738         return ret;
1739     }
1740
1741     for (i = 0; i < MAX_PML4E64_ENTRIES; i++) {
1742         if (host_pml[i].present) {
1743             addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr);
1744             pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa);
1745
1746             if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
1747                 return ret;
1748             }
1749
1750             for (j = 0; j < MAX_PDPE64_ENTRIES; j++) {
1751                 if (tmp_pdpe[j].present) {
1752                     if (tmp_pdpe[j].large_page) {
1753                         pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]);
1754                         addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr);
1755
1756                         if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1757                             return ret;
1758                         }
1759
1760                         vaddr += PAGE_SIZE_1GB;
1761                     } else {
1762                         addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1763                         pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa);
1764
1765                         if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1766                             return ret;
1767                         }
1768
1769                         for (k = 0; k < MAX_PDE64_ENTRIES; k++) {
1770                             if (tmp_pde[k].present) {
1771                                 if (tmp_pde[k].large_page) {
1772                                     pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]);
1773                                     addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
1774                   
1775                                     if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1776                                         return ret;
1777                                     }
1778                   
1779                                     vaddr += PAGE_SIZE_2MB;
1780                                 } else {
1781                                     addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1782                                     pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa);
1783
1784                                     if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
1785                                         return ret;
1786                                     }
1787
1788                                     for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
1789                                         if (tmp_pte[m].present) {
1790                                             addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr);
1791                                             if ((ret = callback(info, PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data)) != 0) {
1792                                                 return ret;
1793                                             }
1794                                         }
1795                                         vaddr += PAGE_SIZE_4KB;
1796                                     }
1797                                 }
1798                             } else {
1799                                 vaddr += PAGE_SIZE_2MB;
1800                             }
1801                         }
1802                     }
1803                 } else {
1804                     vaddr += PAGE_SIZE_1GB;
1805                 }
1806             }
1807         } else {
1808             vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
1809         }
1810     }
1811     return 0;
1812 }
1813
1814
1815
1816 static const uchar_t PAGE_4KB_STR[] = "4KB_PAGE";
1817 static const uchar_t PAGE_2MB_STR[] = "2MB_PAGE";
1818 static const uchar_t PAGE_4MB_STR[] = "4MB_PAGE";
1819 static const uchar_t PAGE_1GB_STR[] = "1GB_PAGE";
1820 static const uchar_t PAGE_PT32_STR[] = "32 Bit PT";
1821 static const uchar_t PAGE_PD32_STR[] = "32 Bit PD";
1822 static const uchar_t PAGE_PDP32PAE_STR[] = "32 Bit PAE PDP";
1823 static const uchar_t PAGE_PD32PAE_STR[] = "32 Bit PAE PD";
1824 static const uchar_t PAGE_PT32PAE_STR[] = "32 Bit PAE PT";
1825 static const uchar_t PAGE_PML464_STR[] = "64 Bit PML4";
1826 static const uchar_t PAGE_PDP64_STR[] = "64 Bit PDP";
1827 static const uchar_t PAGE_PD64_STR[] = "64 Bit PD";
1828 static const uchar_t PAGE_PT64_STR[] = "64 Bit PT";
1829
1830
1831 const uchar_t * v3_page_type_to_str(page_type_t type) {
1832     switch (type) {
1833         case PAGE_4KB:
1834             return PAGE_4KB_STR;
1835         case PAGE_2MB:
1836             return PAGE_2MB_STR;
1837         case PAGE_4MB:
1838             return PAGE_4MB_STR;
1839         case PAGE_1GB:
1840             return PAGE_1GB_STR;
1841         case PAGE_PT32:
1842             return PAGE_PT32_STR;
1843         case PAGE_PD32:
1844             return PAGE_PD32_STR;
1845         case PAGE_PDP32PAE:
1846             return PAGE_PDP32PAE_STR;
1847         case PAGE_PD32PAE:
1848             return PAGE_PD32PAE_STR;
1849         case PAGE_PT32PAE:
1850             return PAGE_PT32PAE_STR;
1851         case PAGE_PML464:
1852             return PAGE_PML464_STR;
1853         case PAGE_PDP64:
1854             return PAGE_PDP64_STR;
1855         case PAGE_PD64:
1856             return PAGE_PD64_STR;
1857         case PAGE_PT64:
1858             return PAGE_PT64_STR;
1859         default:
1860             return NULL;
1861     }
1862 }