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.


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