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.


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