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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_paging.h>
22 #include <palacios/vmm.h>
24 #include <palacios/vm_guest_mem.h>
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);
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);
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);
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
49 #ifndef DEBUG_SHADOW_PAGING
51 #define PrintDebug(fmt, args...)
56 void delete_page_tables_32(pde32_t * pde) {
62 PrintDebug("Deleting Page Tables -- PDE (%p)\n", pde);
64 for (i = 0; (i < MAX_PDE32_ENTRIES); i++) {
66 // We double cast, first to an addr_t to handle 64 bit issues, then to the pointer
68 pte32_t * pte = (pte32_t *)((addr_t)(uint_t)(pde[i].pt_base_addr << PAGE_POWER));
76 V3_FreePage(V3_PAddr(pde));
79 void delete_page_tables_32PAE(pdpe32pae_t * pdpe) {
80 PrintError("Unimplemented function\n");
83 void delete_page_tables_64(pml4e64_t * pml4) {
84 PrintError("Unimplemented function\n");
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;
98 *paddr = page_pa + PAGE_OFFSET_4MB(vaddr);
101 *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
104 PrintError("Inavlid page type (%s) in tranlate pt 32 callback\n", v3_page_type_to_str(type));
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;
118 *paddr = page_pa + PAGE_OFFSET_2MB(vaddr);
121 *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
124 PrintError("Inavlid page type (%s) in translate pt 32pae callback\n", v3_page_type_to_str(type));
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;
139 *paddr = page_pa + PAGE_OFFSET_1GB(vaddr);
142 *paddr = page_pa + PAGE_OFFSET_2MB(vaddr);
145 *paddr = page_pa + PAGE_OFFSET_4KB(vaddr);
148 PrintError("Inavlid page type (%s) in translate pt 64 callback\n", v3_page_type_to_str(type));
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);
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);
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);
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);
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);
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);
179 struct pt_find_data {
181 addr_t * pt_page_ptr;
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;
189 PrintDebug("FIND_PT Type=%s, page_pa = %p\n",
190 v3_page_type_to_str(type),
193 if (type == pt_data->type) {
194 *(pt_data->pt_page_ptr) = page_ptr;
195 *(pt_data->pt_page_pa) = page_pa;
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;
208 data.pt_page_ptr = page_ptr;
209 data.pt_page_pa = page_pa;
211 return v3_drill_host_pt_32(info, host_cr3, vaddr, find_pt_cb, &data);
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;
219 data.pt_page_ptr = page_ptr;
220 data.pt_page_pa = page_pa;
222 return v3_drill_host_pt_32pae(info, host_cr3, vaddr, find_pt_cb, &data);
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;
230 data.pt_page_ptr = page_ptr;
231 data.pt_page_pa = page_pa;
233 return v3_drill_host_pt_64(info, host_cr3, vaddr, find_pt_cb, &data);
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;
240 data.pt_page_ptr = page_ptr;
241 data.pt_page_pa = page_pa;
243 return v3_drill_guest_pt_32(info, guest_cr3, vaddr, find_pt_cb, &data);
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;
251 data.pt_page_ptr = page_ptr;
252 data.pt_page_pa = page_pa;
254 return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, find_pt_cb, &data);
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;
262 data.pt_page_ptr = page_ptr;
263 data.pt_page_pa = page_pa;
265 return v3_drill_guest_pt_64(info, guest_cr3, vaddr, find_pt_cb, &data);
271 * Page Table Access Checks
276 struct pt_check_data {
277 pf_error_t access_type;
278 pt_access_status_t * access_status;
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;
286 *(chk_data->access_status) = v3_can_access_pde32((pde32_t *)page_ptr, vaddr, chk_data->access_type);
289 *(chk_data->access_status) = v3_can_access_pte32((pte32_t *)page_ptr, vaddr, chk_data->access_type);
295 PrintError("Inavlid page type (%s) in check pt 32 callback\n", v3_page_type_to_str(type));
299 if (chk_data->access_status != PT_ACCESS_OK) {
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;
312 *(chk_data->access_status) = v3_can_access_pdpe32pae((pdpe32pae_t *)page_ptr, vaddr, chk_data->access_type);
315 *(chk_data->access_status) = v3_can_access_pde32pae((pde32pae_t *)page_ptr, vaddr, chk_data->access_type);
318 *(chk_data->access_status) = v3_can_access_pte32pae((pte32pae_t *)page_ptr, vaddr, chk_data->access_type);
324 PrintError("Inavlid page type (%s) in check pt 32pae callback\n", v3_page_type_to_str(type));
328 if (chk_data->access_status != PT_ACCESS_OK) {
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;
341 *(chk_data->access_status) = v3_can_access_pml4e64((pml4e64_t *)page_ptr, vaddr, chk_data->access_type);
344 *(chk_data->access_status) = v3_can_access_pdpe64((pdpe64_t *)page_ptr, vaddr, chk_data->access_type);
347 *(chk_data->access_status) = v3_can_access_pde64((pde64_t *)page_ptr, vaddr, chk_data->access_type);
350 *(chk_data->access_status) = v3_can_access_pte64((pte64_t *)page_ptr, vaddr, chk_data->access_type);
357 PrintError("Inavlid page type (%s) in check pt 64 callback\n", v3_page_type_to_str(type));
361 if (chk_data->access_status != PT_ACCESS_OK) {
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;
373 access_data.access_type = access_type;
374 access_data.access_status = access_status;
376 return v3_drill_host_pt_32(info, host_cr3, vaddr, check_pt_32_cb, &access_data);
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;
382 access_data.access_type = access_type;
383 access_data.access_status = access_status;
385 return v3_drill_host_pt_32pae(info, host_cr3, vaddr, check_pt_32pae_cb, &access_data);
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;
393 access_data.access_type = access_type;
394 access_data.access_status = access_status;
396 return v3_drill_host_pt_64(info, host_cr3, vaddr, check_pt_64_cb, &access_data);
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;
405 access_data.access_type = access_type;
406 access_data.access_status = access_status;
408 return v3_drill_guest_pt_32(info, guest_cr3, vaddr, check_pt_32_cb, &access_data);
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;
419 access_data.access_type = access_type;
420 access_data.access_status = access_status;
422 return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, check_pt_32pae_cb, &access_data);
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;
431 access_data.access_type = access_type;
432 access_data.access_status = access_status;
434 return v3_drill_guest_pt_64(info, guest_cr3, vaddr, check_pt_64_cb, &access_data);
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) {
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);
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);
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);
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);
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);
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);
474 * PAGE TABLE LOOKUP FUNCTIONS
476 * The value of entry is a return type:
477 * Page not present: *entry = 0
482 * 32 bit Page Table lookup functions
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)]);
489 if (!pde_entry->present) {
491 return PT_ENTRY_NOT_PRESENT;
492 } else if (pde_entry->large_page) {
493 pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry;
495 *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr);
497 return PT_ENTRY_LARGE_PAGE;
499 *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
500 return PT_ENTRY_PAGE;
506 /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table
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)]);
511 if (!pte_entry->present) {
513 // PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr));
514 return PT_ENTRY_NOT_PRESENT;
516 *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
518 return PT_ENTRY_PAGE;
527 * 32 bit PAE Page Table lookup functions
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)]);
533 if (!pdpe_entry->present) {
535 return PT_ENTRY_NOT_PRESENT;
537 *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
538 return PT_ENTRY_PAGE;
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)]);
545 if (!pde_entry->present) {
547 return PT_ENTRY_NOT_PRESENT;
548 } else if (pde_entry->large_page) {
549 pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry;
551 *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
553 return PT_ENTRY_LARGE_PAGE;
555 *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
556 return PT_ENTRY_PAGE;
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)]);
563 if (!pte_entry->present) {
565 return PT_ENTRY_NOT_PRESENT;
567 *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
568 return PT_ENTRY_PAGE;
576 * 64 bit Page Table lookup functions
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)]);
582 if (!pml_entry->present) {
584 return PT_ENTRY_NOT_PRESENT;
586 *entry = BASE_TO_PAGE_ADDR(pml_entry->pdp_base_addr);
587 return PT_ENTRY_PAGE;
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)]);
594 if (!pdpe_entry->present) {
596 return PT_ENTRY_NOT_PRESENT;
597 } else if (pdpe_entry->large_page) {
598 PrintError("1 Gigabyte pages not supported\n");
602 *entry = BASE_TO_PAGE_ADDR(pdpe_entry->pd_base_addr);
603 return PT_ENTRY_PAGE;
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)]);
610 if (!pde_entry->present) {
612 return PT_ENTRY_NOT_PRESENT;
613 } else if (pde_entry->large_page) {
614 pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry;
616 *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr);
618 return PT_ENTRY_LARGE_PAGE;
620 *entry = BASE_TO_PAGE_ADDR(pde_entry->pt_base_addr);
621 return PT_ENTRY_PAGE;
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)]);
628 if (!pte_entry->present) {
630 return PT_ENTRY_NOT_PRESENT;
632 *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr);
633 return PT_ENTRY_PAGE;
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)) {
647 return PT_ACCESS_USER_ERROR;
656 * 32 bit access checks
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);
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);
670 * 32 bit PAE access checks
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);
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);
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);
688 * 64 Bit access checks
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);
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);
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);
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);
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;
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;
728 switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) {
729 case PT_ENTRY_NOT_PRESENT:
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;
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;
741 if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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;
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;
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;
769 switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) {
770 case PT_ENTRY_NOT_PRESENT:
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;
778 switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
779 case PT_ENTRY_NOT_PRESENT:
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;
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;
791 if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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;
804 // should never get here
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;
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;
824 switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) {
825 case PT_ENTRY_NOT_PRESENT:
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;
833 switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) {
834 case PT_ENTRY_NOT_PRESENT:
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;
840 PrintError("1 Gigabyte Pages not supported\n");
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;
848 switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) {
849 case PT_ENTRY_NOT_PRESENT:
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;
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;
862 if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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;
875 // should never get here
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;
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);
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;
904 switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) {
905 case PT_ENTRY_NOT_PRESENT:
907 case PT_ENTRY_LARGE_PAGE:
909 addr_t large_page_pa = (addr_t)guest_pte_pa;
910 addr_t large_page_va = 0;
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);
919 if ((ret == callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
920 return (ret == -1) ? -1 : PAGE_4MB;
926 pte32_t * guest_pte = NULL;
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);
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;
939 if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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",
950 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
951 return (ret == -1) ? -1 : PAGE_4KB;
958 // should never get here
959 PrintError("End of drill function (guest 32)... Should never have gotten here...\n");
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;
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);
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;
983 switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa))
985 case PT_ENTRY_NOT_PRESENT:
989 pde32pae_t * guest_pde = NULL;
990 addr_t guest_pte_pa = 0;
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);
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;
1002 switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa))
1004 case PT_ENTRY_NOT_PRESENT:
1006 case PT_ENTRY_LARGE_PAGE:
1008 addr_t large_page_pa = (addr_t)guest_pte_pa;
1009 addr_t large_page_va = 0;
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);
1017 if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1018 return (ret == -1) ? -1 : PAGE_2MB;
1024 pte32pae_t * guest_pte = NULL;
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);
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;
1037 if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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",
1048 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1049 return (ret == -1) ? -1 : PAGE_4KB;
1057 PrintError("Invalid page type for PD32PAE\n");
1061 // should never get here
1062 PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n");
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;
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);
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;
1084 switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) {
1085 case PT_ENTRY_NOT_PRESENT:
1089 pdpe64_t * guest_pdp = NULL;
1090 addr_t guest_pde_pa = 0;
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);
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;
1102 switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) {
1103 case PT_ENTRY_NOT_PRESENT:
1105 case PT_ENTRY_LARGE_PAGE:
1107 addr_t large_page_pa = (addr_t)guest_pde_pa;
1108 addr_t large_page_va = 0;
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);
1116 if ((ret == callback(info, PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1117 return (ret == -1) ? -1 : PAGE_1GB;
1119 PrintError("1 Gigabyte Pages not supported\n");
1124 pde64_t * guest_pde = NULL;
1125 addr_t guest_pte_pa = 0;
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);
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;
1137 switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) {
1138 case PT_ENTRY_NOT_PRESENT:
1140 case PT_ENTRY_LARGE_PAGE:
1142 addr_t large_page_pa = (addr_t)guest_pte_pa;
1143 addr_t large_page_va = 0;
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);
1151 if ((ret == callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1152 return (ret == -1) ? -1 : PAGE_2MB;
1158 pte64_t * guest_pte = NULL;
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);
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;
1171 if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) {
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",
1182 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1183 return (ret == -1) ? -1 : PAGE_4KB;
1197 // should never get here
1198 PrintError("End of drill function (guest 64)... Should never have gotten here...\n");
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;
1215 PrintError("Call back was not specified\n");
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);
1225 if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) {
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;
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
1243 if ((ret = callback(info, PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1247 vaddr += PAGE_SIZE_4MB;
1249 addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr);
1250 pte32_t * tmp_pte = NULL;
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",
1258 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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);
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",
1270 // We'll let it through for data pages because they may be unmapped or hooked
1274 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1279 vaddr += PAGE_SIZE_4KB;
1283 vaddr += PAGE_SIZE_4MB;
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;
1300 PrintError("Call back was not specified\n");
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);
1311 if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) {
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;
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",
1326 if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
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;
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
1344 if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1348 vaddr += PAGE_SIZE_2MB;
1350 addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr);
1351 pte32pae_t * tmp_pte = NULL;
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",
1359 if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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);
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",
1371 // We'll let it through for data pages because they may be unmapped or hooked
1375 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1380 vaddr += PAGE_SIZE_4KB;
1384 vaddr += PAGE_SIZE_2MB;
1388 vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
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;
1407 PrintError("Call back was not specified\n");
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",
1418 if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data)) != 0) {
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;
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",
1434 if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
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;
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
1452 if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data)) != 0) {
1456 vaddr += PAGE_SIZE_1GB;
1458 addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr);
1459 pde64_t * tmp_pde = NULL;
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",
1467 if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
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;
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
1485 if ((ret = callback(info, PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) {
1489 vaddr += PAGE_SIZE_2MB;
1491 addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr);
1492 pte64_t * tmp_pte = NULL;
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",
1500 if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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);
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",
1512 // We'll let it through for data pages because they may be unmapped or hooked
1516 if ((ret = callback(info, PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) {
1521 vaddr += PAGE_SIZE_4KB;
1525 vaddr += PAGE_SIZE_2MB;
1530 vaddr += PAGE_SIZE_1GB;
1534 vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES);
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);
1550 PrintError("Call back was not specified\n");
1554 if ((ret = callback(info, PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data)) != 0) {
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);
1564 if ((ret = callback(info, PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1568 vaddr += PAGE_SIZE_4MB;
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);
1573 if ((ret = callback(info, PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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) {
1585 vaddr += PAGE_SIZE_4KB;
1589 vaddr += PAGE_SIZE_4MB;
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);
1609 PrintError("Callback was not specified\n");
1613 if ((ret = callback(info, PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data)) != 0) {
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);
1622 if ((ret = callback(info, PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
1626 for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) {
1627 if (tmp_pde[j].present) {
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);
1633 if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1637 vaddr += PAGE_SIZE_2MB;
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);
1642 if ((ret = callback(info, PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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) {
1654 vaddr += PAGE_SIZE_4KB;
1658 vaddr += PAGE_SIZE_2MB;
1662 vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES;
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);
1679 PrintError("Callback was not specified\n");
1683 if ((ret = callback(info, PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data)) != 0) {
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);
1692 if ((ret = callback(info, PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data)) != 0) {
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);
1702 if ((ret = callback(info, PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1706 vaddr += PAGE_SIZE_1GB;
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);
1711 if ((ret = callback(info, PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data)) != 0) {
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);
1721 if ((ret = callback(info, PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data)) != 0) {
1725 vaddr += PAGE_SIZE_2MB;
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);
1730 if ((ret = callback(info, PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data)) != 0) {
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) {
1741 vaddr += PAGE_SIZE_4KB;
1745 vaddr += PAGE_SIZE_2MB;
1750 vaddr += PAGE_SIZE_1GB;
1754 vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES;
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";
1777 const uchar_t * v3_page_type_to_str(page_type_t type) {
1780 return PAGE_4KB_STR;
1782 return PAGE_2MB_STR;
1784 return PAGE_4MB_STR;
1786 return PAGE_1GB_STR;
1788 return PAGE_PT32_STR;
1790 return PAGE_PD32_STR;
1792 return PAGE_PDP32PAE_STR;
1794 return PAGE_PD32PAE_STR;
1796 return PAGE_PT32PAE_STR;
1798 return PAGE_PML464_STR;
1800 return PAGE_PDP64_STR;
1802 return PAGE_PD64_STR;
1804 return PAGE_PT64_STR;