From: Jack Lange Date: Mon, 3 Nov 2008 23:55:18 +0000 (-0600) Subject: reworked the paging functions X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=7f5fe648423f83c0883d6daa3f15751f9e74daf0 reworked the paging functions *_lookup functions are now static local to vmm_paging.c and no longer return byte offsets for leaf pages added page table drill functions moved translate and access check functions over to drill implementations --- diff --git a/palacios/include/palacios/vmm_paging.h b/palacios/include/palacios/vmm_paging.h index 15c089a..bce23af 100644 --- a/palacios/include/palacios/vmm_paging.h +++ b/palacios/include/palacios/vmm_paging.h @@ -106,7 +106,8 @@ the host state in the vmcs before entering the guest. #define MAX_PTE64_ENTRIES 512 -typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB, +typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB, + PAGE_NOT_PRESENT, PAGE_PT32, PAGE_PD32, PAGE_PDP32PAE, PAGE_PD32PAE, PAGE_PT32PAE, PAGE_PML464, PAGE_PDP64, PAGE_PD64, PAGE_PT64} page_type_t; @@ -146,11 +147,13 @@ typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB, */ /* Replace The above with these... */ #define PAGE_BASE_ADDR(x) ((x) >> 12) +#define PAGE_BASE_ADDR_4KB(x) ((x) >> 12) #define PAGE_BASE_ADDR_2MB(x) ((x) >> 21) #define PAGE_BASE_ADDR_4MB(x) ((x) >> 22) #define PAGE_BASE_ADDR_1GB(x) ((x) >> 30) #define BASE_TO_PAGE_ADDR(x) (((addr_t)x) << 12) +#define BASE_TO_PAGE_ADDR_4KB(x) (((addr_t)x) << 12) #define BASE_TO_PAGE_ADDR_2MB(x) (((addr_t)x) << 21) #define BASE_TO_PAGE_ADDR_4MB(x) (((addr_t)x) << 22) #define BASE_TO_PAGE_ADDR_1GB(x) (((addr_t)x) << 30) @@ -172,22 +175,29 @@ typedef enum {PAGE_4KB, PAGE_2MB, PAGE_4MB, PAGE_1GB, */ /* use these instead */ #define PAGE_OFFSET(x) ((x) & 0xfff) +#define PAGE_OFFSET_4KB(x) ((x) & 0xfff) #define PAGE_OFFSET_2MB(x) ((x) & 0x1fffff) #define PAGE_OFFSET_4MB(x) ((x) & 0x3fffff) +#define PAGE_OFFSET_1GB(x) ((x) & 0x3fffffff) #define PAGE_POWER 12 -#define PAGE_POWER_2MB 22 -#define PAGE_POWER_4MB 21 +#define PAGE_POWER_4KB 12 +#define PAGE_POWER_2MB 21 +#define PAGE_POWER_4MB 22 +#define PAGE_POWER_1GB 30 // We shift instead of mask because we don't know the address size #define PAGE_ADDR(x) (((x) >> PAGE_POWER) << PAGE_POWER) +#define PAGE_ADDR_4KB(x) (((x) >> PAGE_POWER_4KB) << PAGE_POWER_4KB) #define PAGE_ADDR_2MB(x) (((x) >> PAGE_POWER_2MB) << PAGE_POWER_2MB) #define PAGE_ADDR_4MB(x) (((x) >> PAGE_POWER_4MB) << PAGE_POWER_4MB) +#define PAGE_ADDR_1GB(x) (((x) >> PAGE_POWER_1GB) << PAGE_POWER_1GB) #define PAGE_SIZE 4096 +#define PAGE_SIZE_4KB 4096 #define PAGE_SIZE_2MB (4096 * 512) #define PAGE_SIZE_4MB (4096 * 1024) - +#define PAGE_SIZE_1GB 0x40000000 /* *** */ @@ -476,9 +486,6 @@ typedef struct pf_error_code { -void delete_page_tables_32(pde32_t * pde); -void delete_page_tables_32PAE(pdpe32pae_t * pdpe); -void delete_page_tables_64(pml4e64_t * pml4); struct guest_info; @@ -491,23 +498,18 @@ int v3_translate_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr); int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr); -/* Should these be static? */ -pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry); -pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry); - -pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry); -pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry); -pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry); - -pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry); -pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry); -pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry); -pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry); - - - - - +int v3_find_host_pt_32_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr); +int v3_find_host_pt_32pae_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr); +int v3_find_host_pt_64_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr); +int v3_find_guest_pt_32_page(struct guest_info * info, v3_reg_t guest_cr3, + page_type_t type, addr_t vaddr, + addr_t * page_addr); +int v3_find_guest_pt_32pae_page(struct guest_info * info, v3_reg_t guest_cr3, + page_type_t type, addr_t vaddr, + addr_t * page_addr); +int v3_find_guest_pt_64_page(struct guest_info * info, v3_reg_t guest_cr3, + page_type_t type, addr_t vaddr, + addr_t * page_addr); pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type); pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type); @@ -537,37 +539,64 @@ int v3_check_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t va + +int v3_drill_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); +int v3_drill_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); +int v3_drill_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); + +int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); +int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); +int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data); + + + int v3_walk_host_pt_32(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), void * private_data); int v3_walk_host_pt_32pae(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), void * private_data); int v3_walk_host_pt_64(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), void * private_data); int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), - void * private_data); + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), + void * private_data); int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), - void * private_data); + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), + void * private_data); int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_va, addr_t page_pa, void * private_data), - void * private_data); + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_va, addr_t page_pa, void * private_data), + void * private_data); -struct guest_info; pde32_t * create_passthrough_pts_32(struct guest_info * guest_info); pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info); pml4e64_t * create_passthrough_pts_64(struct guest_info * info); +void delete_page_tables_32(pde32_t * pde); +void delete_page_tables_32PAE(pdpe32pae_t * pdpe); +void delete_page_tables_64(pml4e64_t * pml4); + + const uchar_t * v3_page_type_to_str(page_type_t type); diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 8efa804..96802d4 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -395,9 +395,18 @@ static int start_svm_guest(struct guest_info *info) { PrintDebug("RIP Linear: %p\n", (void *)linear_addr); v3_print_segments(info); v3_print_ctrl_regs(info); + if (info->shdw_pg_mode == SHADOW_PAGING) { + PrintDebug("Shadow Paging Guest Registers:\n"); + PrintDebug("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0)); + PrintDebug("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3)); + // efer + // CR4 + } v3_print_GPRs(info); + + PrintDebug("SVM Exit Code: %p\n", (void *)(addr_t)guest_ctrl->exit_code); diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index f4cd053..876f0b3 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -151,7 +151,7 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t return 0; } - if (guest_info->mem_mode == SHADOW_PAGING) { + if (guest_info->shdw_pg_mode == SHADOW_PAGING) { guest_cr3 = guest_info->shdw_pg_state.guest_cr3; } else { guest_cr3 = guest_info->ctrl_regs.cr3; @@ -161,13 +161,28 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t // Guest Is in Paged mode switch (guest_info->cpu_mode) { case PROTECTED: - return v3_translate_guest_pt_32(guest_info, guest_cr3, guest_va, guest_pa); + if (v3_translate_guest_pt_32(guest_info, guest_cr3, guest_va, guest_pa) == -1) { + PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", + (void *)guest_va, (void *)(addr_t)guest_cr3); + return -1; + } + break; case PROTECTED_PAE: - return v3_translate_guest_pt_32pae(guest_info, guest_cr3, guest_va, guest_pa); + if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, guest_va, guest_pa) == -1) { + PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", + (void *)guest_va, (void *)(addr_t)guest_cr3); + return -1; + } + break; case LONG: case LONG_32_COMPAT: case LONG_16_COMPAT: - return v3_translate_guest_pt_64(guest_info, guest_cr3, guest_va, guest_pa); + if (v3_translate_guest_pt_64(guest_info, guest_cr3, guest_va, guest_pa) == -1) { + PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", + (void *)guest_va, (void *)(addr_t)guest_cr3); + return -1; + } + break; default: return -1; } diff --git a/palacios/src/palacios/vmm_paging.c b/palacios/src/palacios/vmm_paging.c index f63ddf1..7200b95 100644 --- a/palacios/src/palacios/vmm_paging.c +++ b/palacios/src/palacios/vmm_paging.c @@ -24,6 +24,20 @@ #include +static pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry); +static pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry); + +static pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry); +static pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry); +static pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry); + +static pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry); +static pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry); +static pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry); +static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry); + + + #define USE_VMM_PAGING_DEBUG // All of the debug functions defined in vmm_paging.h are implemented in this file @@ -31,6 +45,9 @@ #undef USE_VMM_PAGING_DEBUG + + + void delete_page_tables_32(pde32_t * pde) { int i; @@ -62,289 +79,336 @@ void delete_page_tables_64(pml4e64_t * pml4) { } -int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) { - addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3); - pde32_t * guest_pde = 0; - addr_t guest_pte_pa = 0; - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) { - PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", - (void *)guest_pde_pa); + +static int translate_pt_32_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + addr_t * paddr = (addr_t *)private_data; + + switch (type) { + case PAGE_PD32: + case PAGE_PT32: + return 0; + case PAGE_4MB: + *paddr = page_pa + PAGE_OFFSET_4MB(vaddr); + return 0; + case PAGE_4KB: + *paddr = page_pa + PAGE_OFFSET_4KB(vaddr); + return 0; + default: + PrintError("Inavlid page type (%s) in tranlate pt 32 callback\n", v3_page_type_to_str(type)); return -1; } +} + +static int translate_pt_32pae_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + addr_t * paddr = (addr_t *)private_data; - switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = guest_pte_pa; + switch (type) { + case PAGE_PDP32PAE: + case PAGE_PD32PAE: + case PAGE_PT32PAE: return 0; - case PT_ENTRY_PAGE: - { - pte32_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) { - PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } + case PAGE_2MB: + *paddr = page_pa + PAGE_OFFSET_2MB(vaddr); + return 0; + case PAGE_4KB: + *paddr = page_pa + PAGE_OFFSET_4KB(vaddr); + return 0; + default: + PrintError("Inavlid page type (%s) in translate pt 32pae callback\n", v3_page_type_to_str(type)); + return -1; + } +} - if (pte32_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } +static int translate_pt_64_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + addr_t * paddr = (addr_t *)private_data; - return 0; - } + switch (type) { + case PAGE_PML464: + case PAGE_PDP64: + case PAGE_PD64: + case PAGE_PT64: + return 0; + case PAGE_1GB: + *paddr = page_pa + PAGE_OFFSET_1GB(vaddr); + return 0; + case PAGE_2MB: + *paddr = page_pa + PAGE_OFFSET_2MB(vaddr); + return 0; + case PAGE_4KB: + *paddr = page_pa + PAGE_OFFSET_4KB(vaddr); + return 0; + default: + PrintError("Inavlid page type (%s) in translate pt 64 callback\n", v3_page_type_to_str(type)); + return -1; } +} - // should never get here - return -1; + +int v3_translate_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { + return v3_drill_host_pt_32(host_cr3, vaddr, translate_pt_32_cb, paddr); +} +int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) { + return v3_drill_guest_pt_32(info, guest_cr3, vaddr, translate_pt_32_cb, paddr); } +int v3_translate_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { + return v3_drill_host_pt_32pae(host_cr3, vaddr, translate_pt_32pae_cb, paddr); +} int v3_translate_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) { - addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3); - pdpe32pae_t * guest_pdpe = 0; - addr_t guest_pde_pa = 0; + return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, translate_pt_32pae_cb, paddr); +} - if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) { - PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", - (void *)guest_pdpe_pa); - return -1; + +int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { + return v3_drill_host_pt_64(host_cr3, vaddr, translate_pt_64_cb, paddr); +} +int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) { + return v3_drill_guest_pt_64(info, guest_cr3, vaddr, translate_pt_64_cb, paddr); +} + + + +struct pt_find_data { + page_type_t type; + addr_t * pt_page_addr; +}; + +static int find_pt_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + struct pt_find_data * pt_data = (struct pt_find_data *)private_data; + + if (type == pt_data->type) { + *(pt_data->pt_page_addr) = page_ptr; + return 1; } - switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) - { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_PAGE: - { - pde32pae_t * guest_pde = NULL; - addr_t guest_pte_pa = 0; - - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { - PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", - (void *)guest_pde_pa); - return -1; - } - - switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) - { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = guest_pte_pa; - return 0; - case PT_ENTRY_PAGE: - { - pte32pae_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { - PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } + return 0; +} - if (pte32pae_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } - return 0; - } - } - } - default: - return -1; - } +int v3_find_host_pt_32_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; - // should never get here - return -1; + data.type = type; + data.pt_page_addr = page_addr; + + return v3_drill_host_pt_32(host_cr3, vaddr, find_pt_cb, &data); } -int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr) { - addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3); - pml4e64_t * guest_pmle = 0; - addr_t guest_pdpe_pa = 0; +int v3_find_host_pt_32pae_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; - if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) { - PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", - (void *)guest_pml4_pa); - return -1; - } + data.type = type; + data.pt_page_addr = page_addr; - switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_PAGE: - { - pdpe64_t * guest_pdp = NULL; - addr_t guest_pde_pa = 0; + return v3_drill_host_pt_32pae(host_cr3, vaddr, find_pt_cb, &data); +} - if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) { - PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", - (void *)guest_pdpe_pa); - return -1; - } +int v3_find_host_pt_64_page(v3_reg_t host_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; - switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = 0; - PrintError("1 Gigabyte Pages not supported\n"); - return -1; - case PT_ENTRY_PAGE: - { - pde64_t * guest_pde = NULL; - addr_t guest_pte_pa = 0; + data.type = type; + data.pt_page_addr = page_addr; + + return v3_drill_host_pt_64(host_cr3, vaddr, find_pt_cb, &data); +} +int v3_find_guest_pt_32_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { - PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", - (void *)guest_pde_pa); - return -1; - } + data.type = type; + data.pt_page_addr = page_addr; + + return v3_drill_guest_pt_32(info, guest_cr3, vaddr, find_pt_cb, &data); +} - switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = guest_pte_pa; - return 0; - case PT_ENTRY_PAGE: - { - pte64_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { - PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } - - if (pte64_lookup(guest_pte, vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } +int v3_find_guest_pt_32pae_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; - return 0; - } - } - } - } - } - default: - return -1; - } + data.type = type; + data.pt_page_addr = page_addr; + + return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, find_pt_cb, &data); +} - // should never get here - return -1; +int v3_find_guest_pt_64_page(struct guest_info * info, v3_reg_t guest_cr3, page_type_t type, addr_t vaddr, addr_t * page_addr) { + struct pt_find_data data; + + data.type = type; + data.pt_page_addr = page_addr; + + return v3_drill_guest_pt_64(info, guest_cr3, vaddr, find_pt_cb, &data); } +/* + * + * Page Table Access Checks + * + */ -int v3_translate_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { - pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3); - pte32_t * host_pte = 0; - - switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = (addr_t)host_pte; - return 0; - case PT_ENTRY_PAGE: - if (pte32_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } + +struct pt_check_data { + pf_error_t access_type; + pt_access_status_t * access_status; +}; + +static int check_pt_32_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + struct pt_check_data * chk_data = (struct pt_check_data *)private_data; + + switch (type) { + case PAGE_PD32: + *(chk_data->access_status) = v3_can_access_pde32((pde32_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PT32: + *(chk_data->access_status) = v3_can_access_pte32((pte32_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_4MB: + case PAGE_4KB: return 0; + default: + PrintError("Inavlid page type (%s) in check pt 32 callback\n", v3_page_type_to_str(type)); + return -1; } - - // should never get here - return -1; + + if (chk_data->access_status != PT_ACCESS_OK) { + return 1; + } + + return 0; } -int v3_translate_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { - pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3); - pde32pae_t * host_pde = NULL; - pte32pae_t * host_pte = NULL; +static int check_pt_32pae_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + struct pt_check_data * chk_data = (struct pt_check_data *)private_data; - switch (pdpe32pae_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_PAGE: - switch (pde32pae_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = (addr_t)host_pte; - return 0; - case PT_ENTRY_PAGE: - if (pte32pae_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } - return 0; - } - default: + switch (type) { + case PAGE_PDP32PAE: + *(chk_data->access_status) = v3_can_access_pdpe32pae((pdpe32pae_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PD32PAE: + *(chk_data->access_status) = v3_can_access_pde32pae((pde32pae_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PT32PAE: + *(chk_data->access_status) = v3_can_access_pte32pae((pte32pae_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_2MB: + case PAGE_4KB: + return 0; + default: + PrintError("Inavlid page type (%s) in check pt 32pae callback\n", v3_page_type_to_str(type)); return -1; } - // should never get here - return -1; + if (chk_data->access_status != PT_ACCESS_OK) { + return 1; + } + + return 0; } -int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { - pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3); - pdpe64_t * host_pdpe = NULL; - pde64_t * host_pde = NULL; - pte64_t * host_pte = NULL; +static int check_pt_64_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + struct pt_check_data * chk_data = (struct pt_check_data *)private_data; - switch(pml4e64_lookup(host_pmle, vaddr, (addr_t *)&host_pdpe)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_PAGE: - switch(pdpe64_lookup(V3_VAddr(host_pdpe), vaddr, (addr_t *)&host_pde)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = 0; - PrintError("1 Gigabyte Pages not supported\n"); - return -1; - case PT_ENTRY_PAGE: - switch (pde64_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_NOT_PRESENT: - *paddr = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *paddr = (addr_t)host_pte; - return 0; - case PT_ENTRY_PAGE: - if (pte64_lookup(V3_VAddr(host_pte), vaddr, paddr) == PT_ENTRY_NOT_PRESENT) { - return -1; - } - return 0; - } - } - default: + switch (type) { + case PAGE_PML464: + *(chk_data->access_status) = v3_can_access_pml4e64((pml4e64_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PDP64: + *(chk_data->access_status) = v3_can_access_pdpe64((pdpe64_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PD64: + *(chk_data->access_status) = v3_can_access_pde64((pde64_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_PT64: + *(chk_data->access_status) = v3_can_access_pte64((pte64_t *)page_ptr, vaddr, chk_data->access_type); + break; + case PAGE_1GB: + case PAGE_2MB: + case PAGE_4KB: + return 0; + default: + PrintError("Inavlid page type (%s) in check pt 64 callback\n", v3_page_type_to_str(type)); return -1; } - // should never get here - return -1; + if (chk_data->access_status != PT_ACCESS_OK) { + return 1; + } + + return 0; +} + + + +int v3_check_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_host_pt_32(host_cr3, vaddr, check_pt_32_cb, &access_data); +} + +int v3_check_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_host_pt_32pae(host_cr3, vaddr, check_pt_32pae_cb, &access_data); +} + + + +int v3_check_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_host_pt_64(host_cr3, vaddr, check_pt_64_cb, &access_data); +} + + + +int v3_check_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_guest_pt_32(info, guest_cr3, vaddr, check_pt_32_cb, &access_data); +} + + + + + +int v3_check_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_guest_pt_32pae(info, guest_cr3, vaddr, check_pt_32pae_cb, &access_data); } +int v3_check_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + pf_error_t access_type, pt_access_status_t * access_status) { + struct pt_check_data access_data; + + access_data.access_type = access_type; + access_data.access_status = access_status; + + return v3_drill_guest_pt_64(info, guest_cr3, vaddr, check_pt_64_cb, &access_data); +} + /* @@ -363,7 +427,7 @@ int v3_translate_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr) { * **/ -pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) { +static pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) { pde32_t * pde_entry = &(pd[PDE32_INDEX(addr)]); if (!pde_entry->present) { @@ -373,7 +437,6 @@ pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) { pde32_4MB_t * large_pde = (pde32_4MB_t *)pde_entry; *entry = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr); - *entry += PAGE_OFFSET_4MB(addr); return PT_ENTRY_LARGE_PAGE; } else { @@ -386,7 +449,7 @@ pt_entry_type_t pde32_lookup(pde32_t * pd, addr_t addr, addr_t * entry) { /* Takes a virtual addr (addr) and returns the physical addr (entry) as defined in the page table */ -pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) { +static pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) { pte32_t * pte_entry = &(pt[PTE32_INDEX(addr)]); if (!pte_entry->present) { @@ -394,7 +457,8 @@ pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) { // PrintDebug("Lookup at non present page (index=%d)\n", PTE32_INDEX(addr)); return PT_ENTRY_NOT_PRESENT; } else { - *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr); + *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr); + return PT_ENTRY_PAGE; } @@ -407,7 +471,7 @@ pt_entry_type_t pte32_lookup(pte32_t * pt, addr_t addr, addr_t * entry) { * 32 bit PAE Page Table lookup functions * **/ -pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) { +static pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) { pdpe32pae_t * pdpe_entry = &(pdp[PDPE32PAE_INDEX(addr)]); if (!pdpe_entry->present) { @@ -419,7 +483,7 @@ pt_entry_type_t pdpe32pae_lookup(pdpe32pae_t * pdp, addr_t addr, addr_t * entry) } } -pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) { +static pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) { pde32pae_t * pde_entry = &(pd[PDE32PAE_INDEX(addr)]); if (!pde_entry->present) { @@ -429,7 +493,6 @@ pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) { pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)pde_entry; *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr); - *entry += PAGE_OFFSET_2MB(addr); return PT_ENTRY_LARGE_PAGE; } else { @@ -438,14 +501,14 @@ pt_entry_type_t pde32pae_lookup(pde32pae_t * pd, addr_t addr, addr_t * entry) { } } -pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) { +static pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) { pte32pae_t * pte_entry = &(pt[PTE32PAE_INDEX(addr)]); if (!pte_entry->present) { *entry = 0; return PT_ENTRY_NOT_PRESENT; } else { - *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr); + *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr); return PT_ENTRY_PAGE; } } @@ -457,7 +520,7 @@ pt_entry_type_t pte32pae_lookup(pte32pae_t * pt, addr_t addr, addr_t * entry) { * 64 bit Page Table lookup functions * **/ -pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) { +static pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) { pml4e64_t * pml_entry = &(pml[PML4E64_INDEX(addr)]); if (!pml_entry->present) { @@ -469,7 +532,7 @@ pt_entry_type_t pml4e64_lookup(pml4e64_t * pml, addr_t addr, addr_t * entry) { } } -pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) { +static pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) { pdpe64_t * pdpe_entry = &(pdp[PDPE64_INDEX(addr)]); if (!pdpe_entry->present) { @@ -485,7 +548,7 @@ pt_entry_type_t pdpe64_lookup(pdpe64_t * pdp, addr_t addr, addr_t * entry) { } } -pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) { +static pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) { pde64_t * pde_entry = &(pd[PDE64_INDEX(addr)]); if (!pde_entry->present) { @@ -495,7 +558,6 @@ pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) { pde64_2MB_t * large_pde = (pde64_2MB_t *)pde_entry; *entry = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr); - *entry += PAGE_OFFSET_2MB(addr); return PT_ENTRY_LARGE_PAGE; } else { @@ -504,14 +566,14 @@ pt_entry_type_t pde64_lookup(pde64_t * pd, addr_t addr, addr_t * entry) { } } -pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) { +static pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) { pte64_t * pte_entry = &(pt[PTE64_INDEX(addr)]); if (!pte_entry->present) { *entry = 0; return PT_ENTRY_NOT_PRESENT; } else { - *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr) + PAGE_OFFSET(addr); + *entry = BASE_TO_PAGE_ADDR(pte_entry->page_base_addr); return PT_ENTRY_PAGE; } } @@ -519,406 +581,6 @@ pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) { - - - - -/* - * - * Page Table Access Checks - * - */ - - - - - - -int v3_check_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { - pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3); - pte32_t * host_pte = 0; - - int pt_level = 2; - - // Check accessibility of PDE - *access_status = v3_can_access_pde32(host_pde, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde32_lookup(host_pde, vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pte32(V3_VAddr(host_pte), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - return 0; - default: - return -1; - } - - // should never get here - return -1; -} - -int v3_check_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { - pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3); - pde32pae_t * host_pde = NULL; - pte32pae_t * host_pte = NULL; - int pt_level = 3; - - *access_status = v3_can_access_pdpe32pae(host_pdpe, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pdpe32pae_lookup(host_pdpe, vaddr, (addr_t *)&host_pde)) { - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pde32pae(V3_VAddr(host_pde), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde32pae_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pte32pae(V3_VAddr(host_pte), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - return 0; - default: - return -1; - } - default: - return -1; - } - - // should never get here - return -1; -} - - - -int v3_check_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, pf_error_t access_type, pt_access_status_t * access_status) { - pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3); - pdpe64_t * host_pdpe = NULL; - pde64_t * host_pde = NULL; - pte64_t * host_pte = NULL; - int pt_level = 4; - - - *access_status = v3_can_access_pml4e64(host_pmle, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch(pml4e64_lookup(host_pmle, vaddr, (addr_t *)&host_pdpe)) { - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pdpe64(V3_VAddr(host_pdpe), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch(pdpe64_lookup(V3_VAddr(host_pdpe), vaddr, (addr_t *)&host_pde)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pde64(V3_VAddr(host_pde), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde64_lookup(V3_VAddr(host_pde), vaddr, (addr_t *)&host_pte)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - *access_status = v3_can_access_pte64(V3_VAddr(host_pte), vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - return 0; - default: - return -1; - } - default: - return -1; - } - default: - return -1; - } - - // should never get here - return -1; -} - - - - - -int v3_check_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, - pf_error_t access_type, pt_access_status_t * access_status) { - addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3); - pde32_t * guest_pde = NULL; - addr_t guest_pte_pa = 0; - int pt_level = 2; - - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) { - PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", - (void *)guest_pde_pa); - return -1; - } - - - // Check accessibility of PDE - *access_status = v3_can_access_pde32(guest_pde, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - { - pte32_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) { - PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } - - *access_status = v3_can_access_pte32(guest_pte, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - return 0; - } - default: - return -1; - } - - // should never get here - return -1; -} - - - - - -int v3_check_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, - pf_error_t access_type, pt_access_status_t * access_status) { - addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3); - pdpe32pae_t * guest_pdpe = NULL; - addr_t guest_pde_pa = 0; - int pt_level = 3; - - if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) { - PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", - (void *)guest_pdpe_pa); - return -1; - } - - *access_status = v3_can_access_pdpe32pae(guest_pdpe, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) { - case PT_ENTRY_PAGE: - { - pde32pae_t * guest_pde = NULL; - addr_t guest_pte_pa = 0; - - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { - PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", - (void *)guest_pde_pa); - return -1; - } - - *access_status = v3_can_access_pde32pae(guest_pde, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - { - pte32pae_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { - PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } - - *access_status = v3_can_access_pte32pae(guest_pte, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - return 0; - } - default: - return -1; - } - } - default: - return -1; - } - - // should never get here - return -1; -} - - - pte64_t * guest_pte = NULL; - -int v3_check_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, - pf_error_t access_type, pt_access_status_t * access_status) { - addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3); - pml4e64_t * guest_pmle = NULL; - addr_t guest_pdpe_pa = 0; - int pt_level = 4; - - if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) { - PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", - (void *)guest_pml4_pa); - return -1; - } - - *access_status = v3_can_access_pml4e64(guest_pmle, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch(pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) { - case PT_ENTRY_PAGE: - { - pdpe64_t * guest_pdp = NULL; - addr_t guest_pde_pa = 0; - - if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) { - PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", - (void *)guest_pdpe_pa); - return -1; - } - - *access_status = v3_can_access_pdpe64(guest_pdp, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch(pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - { - pde64_t * guest_pde = NULL; - addr_t guest_pte_pa = 0; - - if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { - PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", - (void *)guest_pde_pa); - return -1; - } - - *access_status = v3_can_access_pde64(guest_pde, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - pt_level--; - - switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) { - case PT_ENTRY_LARGE_PAGE: - return 0; - case PT_ENTRY_PAGE: - { - pte64_t * guest_pte = NULL; - - if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { - PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", - (void *)guest_pte_pa); - return -1; - } - - *access_status = v3_can_access_pte64(guest_pte, vaddr, access_type); - - if (*access_status != PT_ACCESS_OK) { - return pt_level; - } - - return 0; - } - default: - return -1; - } - } - default: - return -1; - } - } - default: - return -1; - } - - // should never get here - return -1; -} - - - - - static pt_access_status_t can_access_pt_entry(gen_pt_t * pt, pf_error_t access_type) { if (pt->present == 0) { return PT_ACCESS_NOT_PRESENT; @@ -1411,12 +1073,503 @@ pml4e64_t * create_passthrough_pts_64(struct guest_info * info) { } +int v3_drill_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3); + addr_t host_pde_pa = CR3_TO_PDE32_PA(host_cr3); + addr_t host_pte_pa = 0; + addr_t page_pa = 0; + int ret; + + if ((ret = callback(PAGE_PD32, vaddr, (addr_t)host_pde, host_pde_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PD32; + } + + switch (pde32_lookup(host_pde, vaddr, &host_pte_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + if ((ret == callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4MB; + } + return 0; + case PT_ENTRY_PAGE: + if ((ret = callback(PAGE_PT32, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT32; + } + + if (pte32_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + return 0; + } + } + return -1; +} + + + +int v3_drill_host_pt_32pae(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3); + addr_t host_pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3); + addr_t host_pde_pa = 0; + addr_t host_pte_pa = 0; + addr_t page_pa = 0; + int ret; + + if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, host_pdpe_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PDP32PAE; + } + + switch (pdpe32pae_lookup(host_pdpe, vaddr, &host_pde_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_PAGE: + + if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PD32PAE; + } + + switch (pde32pae_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_2MB; + } + return 0; + case PT_ENTRY_PAGE: + if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT32PAE; + } + + if (pte32pae_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + return 0; + } + } + default: + return -1; + } + + // should never get here + return -1; +} + + +int v3_drill_host_pt_64(v3_reg_t host_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3); + addr_t host_pmle_pa = CR3_TO_PML4E64_PA(host_cr3); + addr_t host_pdpe_pa = 0; + addr_t host_pde_pa = 0; + addr_t host_pte_pa = 0; + addr_t page_pa = 0; + int ret; + + if ((ret = callback(PAGE_PML464, vaddr, (addr_t)host_pmle, host_pmle_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PML464; + } + + switch(pml4e64_lookup(host_pmle, vaddr, &host_pdpe_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_PAGE: + + if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)V3_VAddr((void *)host_pdpe_pa), host_pdpe_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PDP64; + } + + switch(pdpe64_lookup(V3_VAddr((void *)host_pdpe_pa), vaddr, &host_pde_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + if ((ret == callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_1GB; + } + PrintError("1 Gigabyte Pages not supported\n"); + return 0; + case PT_ENTRY_PAGE: + + if ((ret = callback(PAGE_PD64, vaddr, (addr_t)V3_VAddr((void *)host_pde_pa), host_pde_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PD64; + } + + switch (pde64_lookup(V3_VAddr((void *)host_pde_pa), vaddr, &host_pte_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + if ((ret == callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_2MB; + } + return 0; + case PT_ENTRY_PAGE: + + if ((ret = callback(PAGE_PT64, vaddr, (addr_t)V3_VAddr((void *)host_pte_pa), host_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT64; + } + + if (pte64_lookup(V3_VAddr((void *)host_pte_pa), vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + if ((ret = callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)PAGE_BASE_ADDR(page_pa)), page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + return 0; + } + } + } + default: + return -1; + } + // should never get here + return -1; +} + + + + + + + +int v3_drill_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3); + pde32_t * guest_pde = NULL; + addr_t guest_pte_pa = 0; + int ret; + + + if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t*)&guest_pde) == -1) { + PrintError("Could not get virtual address of Guest PDE32 (PA=%p)\n", + (void *)guest_pde_pa); + return -1; + } + + if ((ret = callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PD32; + } + + switch (pde32_lookup(guest_pde, vaddr, &guest_pte_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + { + addr_t large_page_pa = (addr_t)guest_pte_pa; + addr_t large_page_va = 0; + + if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { + PrintError("Could not get virtual address of Guest Page 4MB (PA=%p)\n", + (void *)large_page_va); + return -1; + } + + + if ((ret == callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4MB; + } + return 0; + } + case PT_ENTRY_PAGE: + { + pte32_t * guest_pte = NULL; + addr_t page_pa; + + if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t*)&guest_pte) == -1) { + PrintError("Could not get virtual address of Guest PTE32 (PA=%p)\n", + (void *)guest_pte_pa); + return -1; + } + + if ((ret = callback(PAGE_PT32, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT32; + } + + if (pte32_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + addr_t page_va; + + if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { + PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", + (void *)page_pa); + return -1; + } + + if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + return 0; + } + } + } + + // should never get here + PrintError("End of drill function (guest 32)... Should never have gotten here...\n"); + return -1; +} + + + +int v3_drill_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3); + pdpe32pae_t * guest_pdpe = 0; + addr_t guest_pde_pa = 0; + int ret = 0; + + if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t*)&guest_pdpe) == -1) { + PrintError("Could not get virtual address of Guest PDPE32PAE (PA=%p)\n", + (void *)guest_pdpe_pa); + return -1; + } + + if ((ret = callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PDP32PAE; + } + + switch (pdpe32pae_lookup(guest_pdpe, vaddr, &guest_pde_pa)) + { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_PAGE: + { + pde32pae_t * guest_pde = NULL; + addr_t guest_pte_pa = 0; + + if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { + PrintError("Could not get virtual Address of Guest PDE32PAE (PA=%p)\n", + (void *)guest_pde_pa); + return -1; + } + + if ((ret = callback(PAGE_PD32PAE, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PD32PAE; + } + + switch (pde32pae_lookup(guest_pde, vaddr, &guest_pte_pa)) + { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + { + addr_t large_page_pa = (addr_t)guest_pte_pa; + addr_t large_page_va = 0; + + if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { + PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", + (void *)large_page_va); + + } + + if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_2MB; + } + return 0; + } + case PT_ENTRY_PAGE: + { + pte32pae_t * guest_pte = NULL; + addr_t page_pa; + + if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { + PrintError("Could not get virtual Address of Guest PTE32PAE (PA=%p)\n", + (void *)guest_pte_pa); + return -1; + } + + if ((ret = callback(PAGE_PT32PAE, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT32PAE; + } + + if (pte32pae_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + addr_t page_va; + + if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { + PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", + (void *)page_pa); + return -1; + } + + if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + return 0; + } + } + } + } + default: + PrintError("Invalid page type for PD32PAE\n"); + return -1; + } + + // should never get here + PrintError("End of drill function (guest 32pae)... Should never have gotten here...\n"); + return -1; +} + +int v3_drill_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, + int (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), + void * private_data) { + addr_t guest_pml4_pa = CR3_TO_PML4E64_PA(guest_cr3); + pml4e64_t * guest_pmle = 0; + addr_t guest_pdpe_pa = 0; + int ret = 0; + + if (guest_pa_to_host_va(info, guest_pml4_pa, (addr_t*)&guest_pmle) == -1) { + PrintError("Could not get virtual address of Guest PML4E64 (PA=%p)\n", + (void *)guest_pml4_pa); + return -1; + } + + if ((ret = callback(PAGE_PML464, vaddr, (addr_t)guest_pmle, guest_pml4_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PML464; + } + + switch (pml4e64_lookup(guest_pmle, vaddr, &guest_pdpe_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_PAGE: + { + pdpe64_t * guest_pdp = NULL; + addr_t guest_pde_pa = 0; + + if (guest_pa_to_host_va(info, guest_pdpe_pa, (addr_t *)&guest_pdp) == -1) { + PrintError("Could not get virtual address of Guest PDPE64 (PA=%p)\n", + (void *)guest_pdpe_pa); + return -1; + } + + if ((ret = callback(PAGE_PDP64, vaddr, (addr_t)guest_pdp, guest_pdpe_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PDP64; + } + + switch (pdpe64_lookup(guest_pdp, vaddr, &guest_pde_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + { + addr_t large_page_pa = (addr_t)guest_pde_pa; + addr_t large_page_va = 0; + + if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { + PrintDebug("Could not get virtual address of Guest Page 1GB (PA=%p)\n", + (void *)large_page_va); + + } + + if ((ret == callback(PAGE_1GB, vaddr, large_page_va, large_page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_1GB; + } + PrintError("1 Gigabyte Pages not supported\n"); + return 0; + } + case PT_ENTRY_PAGE: + { + pde64_t * guest_pde = NULL; + addr_t guest_pte_pa = 0; + + if (guest_pa_to_host_va(info, guest_pde_pa, (addr_t *)&guest_pde) == -1) { + PrintError("Could not get virtual address of guest PDE64 (PA=%p)\n", + (void *)guest_pde_pa); + return -1; + } + + if ((ret = callback(PAGE_PD64, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_PD64; + } + + switch (pde64_lookup(guest_pde, vaddr, &guest_pte_pa)) { + case PT_ENTRY_NOT_PRESENT: + return -1; + case PT_ENTRY_LARGE_PAGE: + { + addr_t large_page_pa = (addr_t)guest_pte_pa; + addr_t large_page_va = 0; + + if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { + PrintDebug("Could not get virtual address of Guest Page 2MB (PA=%p)\n", + (void *)large_page_va); + + } + + if ((ret == callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_2MB; + } + return 0; + } + case PT_ENTRY_PAGE: + { + pte64_t * guest_pte = NULL; + addr_t page_pa; + + if (guest_pa_to_host_va(info, guest_pte_pa, (addr_t *)&guest_pte) == -1) { + PrintError("Could not get virtual address of guest PTE64 (PA=%p)\n", + (void *)guest_pte_pa); + return -1; + } + + if ((ret = callback(PAGE_PT64, vaddr, (addr_t)guest_pte, guest_pte_pa, private_data) != 0)) { + return (ret == -1) ? -1 : PAGE_PT64; + } + + if (pte64_lookup(guest_pte, vaddr, &page_pa) == PT_ENTRY_NOT_PRESENT) { + return -1; + } else { + addr_t page_va; + + if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { + PrintError("Could not get virtual address of Guest Page 4KB (PA=%p)\n", + (void *)page_pa); + return -1; + } + + if ((ret = callback(PAGE_4KB, vaddr, page_va, page_pa, private_data)) != 0) { + return (ret == -1) ? -1 : PAGE_4KB; + } + + return 0; + } + } + } + } + } + } + default: + return -1; + } + + // should never get here + PrintError("End of drill function (guest 64)... Should never have gotten here...\n"); + return -1; +} + + + + int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { addr_t guest_pde_pa = CR3_TO_PDE32_PA(guest_cr3); pde32_t * guest_pde = NULL; int i, j; + addr_t vaddr = 0; if (!callback) { PrintError("Call back was not specified\n"); @@ -1429,7 +1582,7 @@ int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PD32, (addr_t)guest_pde, guest_pde_pa, private_data); + callback(PAGE_PD32, vaddr, (addr_t)guest_pde, guest_pde_pa, private_data); for (i = 0; i < MAX_PDE32_ENTRIES; i++) { if (guest_pde[i].present) { @@ -1439,12 +1592,15 @@ int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t large_page_va = 0; if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { - PrintError("Could not get virtual address of Guest 4MB Page (PA=%p)\n", - (void *)large_page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 4MB Page (PA=%p)\n", + (void *)large_page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + large_page_va = 0; } - callback(PAGE_4MB, large_page_va, large_page_pa, private_data); + callback(PAGE_4MB, vaddr, large_page_va, large_page_pa, private_data); + + vaddr += PAGE_SIZE_4MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(guest_pde[i].pt_base_addr); pte32_t * tmp_pte = NULL; @@ -1455,7 +1611,7 @@ int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PT32, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (j = 0; j < MAX_PTE32_ENTRIES; j++) { if (tmp_pte[j].present) { @@ -1463,15 +1619,20 @@ int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t page_va = 0; if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { - PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", - (void *)page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", + (void *)page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + page_va = 0; } - callback(PAGE_4KB, page_va, page_pa, private_data); + callback(PAGE_4KB, vaddr, page_va, page_pa, private_data); } + + vaddr += PAGE_SIZE_4KB; } } + } else { + vaddr += PAGE_SIZE_4MB; } } return 0; @@ -1479,11 +1640,12 @@ int v3_walk_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { addr_t guest_pdpe_pa = CR3_TO_PDPE32PAE_PA(guest_cr3); pdpe32pae_t * guest_pdpe = NULL; int i, j, k; + addr_t vaddr = 0; if (!callback) { PrintError("Call back was not specified\n"); @@ -1498,7 +1660,7 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, - callback(PAGE_PDP32PAE, (addr_t)guest_pdpe, guest_pdpe_pa, private_data); + callback(PAGE_PDP32PAE, vaddr, (addr_t)guest_pdpe, guest_pdpe_pa, private_data); for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) { if (guest_pdpe[i].present) { @@ -1511,7 +1673,7 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PD32PAE, (addr_t)tmp_pde, pde_pa, private_data); + callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data); for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) { if (tmp_pde[j].present) { @@ -1521,12 +1683,15 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t large_page_va = 0; if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { - PrintError("Could not get virtual address of Guest 2MB Page (PA=%p)\n", - (void *)large_page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 2MB Page (PA=%p)\n", + (void *)large_page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + large_page_va = 0; } - callback(PAGE_2MB, large_page_va, large_page_pa, private_data); + callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data); + + vaddr += PAGE_SIZE_2MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr); pte32pae_t * tmp_pte = NULL; @@ -1537,7 +1702,7 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PT32PAE, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) { if (tmp_pte[k].present) { @@ -1545,17 +1710,24 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t page_va = 0; if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { - PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", - (void *)page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", + (void *)page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + page_va = 0; } - callback(PAGE_4KB, page_va, page_pa, private_data); + callback(PAGE_4KB, vaddr, page_va, page_pa, private_data); } + + vaddr += PAGE_SIZE_4KB; } } + } else { + vaddr += PAGE_SIZE_2MB; } } + } else { + vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES; } } return 0; @@ -1565,11 +1737,12 @@ int v3_walk_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { addr_t guest_pml_pa = CR3_TO_PML4E64_PA(guest_cr3); pml4e64_t * guest_pml = NULL; int i, j, k, m; + addr_t vaddr = 0; if (!callback) { PrintError("Call back was not specified\n"); @@ -1583,7 +1756,7 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, } - callback(PAGE_PML464, (addr_t)guest_pml, guest_pml_pa, private_data); + callback(PAGE_PML464, vaddr, (addr_t)guest_pml, guest_pml_pa, private_data); for (i = 0; i < MAX_PML4E64_ENTRIES; i++) { if (guest_pml[i].present) { @@ -1597,7 +1770,7 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PDP64, (addr_t)tmp_pdpe, pdpe_pa, private_data); + callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data); for (j = 0; j < MAX_PDPE64_ENTRIES; j++) { if (tmp_pdpe[j].present) { @@ -1607,13 +1780,15 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t large_page_va = 0; if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { - PrintError("Could not get virtual address of Guest 1GB page (PA=%p)\n", - (void *)large_page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 1GB page (PA=%p)\n", + (void *)large_page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + large_page_va = 0; } - callback(PAGE_1GB, (addr_t)large_page_va, large_page_pa, private_data); + callback(PAGE_1GB, vaddr, (addr_t)large_page_va, large_page_pa, private_data); + vaddr += PAGE_SIZE_1GB; } else { addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr); pde64_t * tmp_pde = NULL; @@ -1624,7 +1799,7 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PD64, (addr_t)tmp_pde, pde_pa, private_data); + callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data); for (k = 0; k < MAX_PDE64_ENTRIES; k++) { if (tmp_pde[k].present) { @@ -1634,12 +1809,15 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t large_page_va = 0; if (guest_pa_to_host_va(info, large_page_pa, &large_page_va) == -1) { - PrintError("Could not get virtual address of Guest 2MB page (PA=%p)\n", - (void *)large_page_pa); - return -1; + PrintDebug("Could not get virtual address of Guest 2MB page (PA=%p)\n", + (void *)large_page_pa); + // We'll let it through for data pages because they may be unmapped or hooked + large_page_va = 0; } - callback(PAGE_2MB, large_page_va, large_page_pa, private_data); + callback(PAGE_2MB, vaddr, large_page_va, large_page_pa, private_data); + + vaddr += PAGE_SIZE_2MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr); pte64_t * tmp_pte = NULL; @@ -1650,7 +1828,7 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, return -1; } - callback(PAGE_PT64, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (m = 0; m < MAX_PTE64_ENTRIES; m++) { if (tmp_pte[m].present) { @@ -1658,38 +1836,48 @@ int v3_walk_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t page_va = 0; if (guest_pa_to_host_va(info, page_pa, &page_va) == -1) { - PrintError("Could not get virtual address of Guest 4KB Page (PA=%p)\n", + PrintDebug("Could not get virtual address of Guest 4KB Page (PA=%p)\n", (void *)page_pa); - return -1; + // We'll let it through for data pages because they may be unmapped or hooked + page_va = 0; } - callback(PAGE_4KB, page_va, page_pa, private_data); + callback(PAGE_4KB, vaddr, page_va, page_pa, private_data); } + + vaddr += PAGE_SIZE_4KB; } } + } else { + vaddr += PAGE_SIZE_2MB; } } } + } else { + vaddr += PAGE_SIZE_1GB; } } + } else { + vaddr += ((ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES); } } return 0; } int v3_walk_host_pt_32(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { pde32_t * host_pde = (pde32_t *)CR3_TO_PDE32_VA(host_cr3); addr_t pde_pa = CR3_TO_PDE32_PA(host_cr3); int i, j; + addr_t vaddr = 0; if (!callback) { PrintError("Call back was not specified\n"); return -1; } - callback(PAGE_PD32, (addr_t)host_pde, pde_pa, private_data); + callback(PAGE_PD32, vaddr, (addr_t)host_pde, pde_pa, private_data); for (i = 0; i < MAX_PDE32_ENTRIES; i++) { if (host_pde[i].present) { @@ -1697,49 +1885,56 @@ int v3_walk_host_pt_32(v3_reg_t host_cr3, pde32_4MB_t * large_pde = (pde32_4MB_t *)&(host_pde[i]); addr_t large_page_pa = BASE_TO_PAGE_ADDR_4MB(large_pde->page_base_addr); - callback(PAGE_4MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + callback(PAGE_4MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + + vaddr += PAGE_SIZE_4MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(host_pde[i].pt_base_addr); pte32_t * tmp_pte = (pte32_t *)V3_VAddr((void *)pte_pa); - callback(PAGE_PT32, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT32, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (j = 0; j < MAX_PTE32_ENTRIES; j++) { if (tmp_pte[j].present) { addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[j].page_base_addr); - callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); + callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); } + + vaddr += PAGE_SIZE_4KB; } } + } else { + vaddr += PAGE_SIZE_4MB; } } return 0; } - + int v3_walk_host_pt_32pae(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { pdpe32pae_t * host_pdpe = (pdpe32pae_t *)CR3_TO_PDPE32PAE_VA(host_cr3); addr_t pdpe_pa = CR3_TO_PDPE32PAE_PA(host_cr3); int i, j, k; - + addr_t vaddr = 0; + if (!callback) { PrintError("Callback was not specified\n"); return -1; } - callback(PAGE_PDP32PAE, (addr_t)host_pdpe, pdpe_pa, private_data); + callback(PAGE_PDP32PAE, vaddr, (addr_t)host_pdpe, pdpe_pa, private_data); for (i = 0; i < MAX_PDPE32PAE_ENTRIES; i++) { if (host_pdpe[i].present) { addr_t pde_pa = BASE_TO_PAGE_ADDR(host_pdpe[i].pd_base_addr); pde32pae_t * tmp_pde = (pde32pae_t *)V3_VAddr((void *)pde_pa); - callback(PAGE_PD32PAE, (addr_t)tmp_pde, pde_pa, private_data); + callback(PAGE_PD32PAE, vaddr, (addr_t)tmp_pde, pde_pa, private_data); for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) { if (tmp_pde[j].present) { @@ -1748,22 +1943,30 @@ int v3_walk_host_pt_32pae(v3_reg_t host_cr3, pde32pae_2MB_t * large_pde = (pde32pae_2MB_t *)&(tmp_pde[j]); addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr); - callback(PAGE_2MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + + vaddr += PAGE_SIZE_2MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[j].pt_base_addr); pte32pae_t * tmp_pte = (pte32pae_t *)V3_VAddr((void *)pte_pa); - callback(PAGE_PT32PAE, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT32PAE, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) { if (tmp_pte[k].present) { addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[k].page_base_addr); - callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); + callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); } + + vaddr += PAGE_SIZE_4KB; } - } + } + } else { + vaddr += PAGE_SIZE_2MB; } } + } else { + vaddr += PAGE_SIZE_2MB * MAX_PDE32PAE_ENTRIES; } } return 0; @@ -1771,25 +1974,26 @@ int v3_walk_host_pt_32pae(v3_reg_t host_cr3, int v3_walk_host_pt_64(v3_reg_t host_cr3, - void (*callback)(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data), + void (*callback)(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data), void * private_data) { pml4e64_t * host_pml = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3); addr_t pml_pa = CR3_TO_PML4E64_PA(host_cr3); int i, j, k, m; + addr_t vaddr = 0; if (!callback) { PrintError("Callback was not specified\n"); return -1; } - callback(PAGE_PML464, (addr_t)host_pml, pml_pa, private_data); + callback(PAGE_PML464, vaddr, (addr_t)host_pml, pml_pa, private_data); for (i = 0; i < MAX_PML4E64_ENTRIES; i++) { if (host_pml[i].present) { addr_t pdpe_pa = BASE_TO_PAGE_ADDR(host_pml[i].pdp_base_addr); pdpe64_t * tmp_pdpe = (pdpe64_t *)V3_VAddr((void *)pdpe_pa); - callback(PAGE_PDP64, (addr_t)tmp_pdpe, pdpe_pa, private_data); + callback(PAGE_PDP64, vaddr, (addr_t)tmp_pdpe, pdpe_pa, private_data); for (j = 0; j < MAX_PDPE64_ENTRIES; j++) { if (tmp_pdpe[j].present) { @@ -1797,12 +2001,14 @@ int v3_walk_host_pt_64(v3_reg_t host_cr3, pdpe64_1GB_t * large_pdp = (pdpe64_1GB_t *)&(tmp_pdpe[j]); addr_t large_page_pa = BASE_TO_PAGE_ADDR_1GB(large_pdp->page_base_addr); - callback(PAGE_1GB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + callback(PAGE_1GB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + + vaddr += PAGE_SIZE_1GB; } else { addr_t pde_pa = BASE_TO_PAGE_ADDR(tmp_pdpe[j].pd_base_addr); pde64_t * tmp_pde = (pde64_t *)V3_VAddr((void *)pde_pa); - callback(PAGE_PD64, (addr_t)tmp_pde, pde_pa, private_data); + callback(PAGE_PD64, vaddr, (addr_t)tmp_pde, pde_pa, private_data); for (k = 0; k < MAX_PDE64_ENTRIES; k++) { if (tmp_pde[k].present) { @@ -1810,25 +2016,34 @@ int v3_walk_host_pt_64(v3_reg_t host_cr3, pde64_2MB_t * large_pde = (pde64_2MB_t *)&(tmp_pde[k]); addr_t large_page_pa = BASE_TO_PAGE_ADDR_2MB(large_pde->page_base_addr); - callback(PAGE_2MB, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + callback(PAGE_2MB, vaddr, (addr_t)V3_VAddr((void *)large_page_pa), large_page_pa, private_data); + + vaddr += PAGE_SIZE_2MB; } else { addr_t pte_pa = BASE_TO_PAGE_ADDR(tmp_pde[k].pt_base_addr); pte64_t * tmp_pte = (pte64_t *)V3_VAddr((void *)pte_pa); - callback(PAGE_PT64, (addr_t)tmp_pte, pte_pa, private_data); + callback(PAGE_PT64, vaddr, (addr_t)tmp_pte, pte_pa, private_data); for (m = 0; m < MAX_PTE64_ENTRIES; m++) { if (tmp_pte[m].present) { addr_t page_pa = BASE_TO_PAGE_ADDR(tmp_pte[m].page_base_addr); - callback(PAGE_4KB, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); + callback(PAGE_4KB, vaddr, (addr_t)V3_VAddr((void *)page_pa), page_pa, private_data); } + vaddr += PAGE_SIZE_4KB; } } + } else { + vaddr += PAGE_SIZE_2MB; } } } + } else { + vaddr += PAGE_SIZE_1GB; } } + } else { + vaddr += (ullong_t)PAGE_SIZE_1GB * (ullong_t)MAX_PDPE64_ENTRIES; } } return 0; diff --git a/palacios/src/palacios/vmm_paging_debug.h b/palacios/src/palacios/vmm_paging_debug.h index c87e829..84d2d1a 100644 --- a/palacios/src/palacios/vmm_paging_debug.h +++ b/palacios/src/palacios/vmm_paging_debug.h @@ -50,59 +50,6 @@ void PrintPTE32(addr_t virtual_address, pte32_t * pte) - - -void PrintPD32(pde32_t * pde) -{ - int i; - - PrintDebug("Page Directory at %p:\n", pde); - for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { - if ( pde[i].present) { - PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); - } - } -} - -void PrintPT32(addr_t starting_address, pte32_t * pte) -{ - int i; - - PrintDebug("Page Table at %p:\n", pte); - for (i = 0; (i < MAX_PTE32_ENTRIES) ; i++) { - if (pte[i].present) { - PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i])); - } - } -} - - - - - - - -void PrintDebugPageTables(pde32_t * pde) -{ - int i; - - PrintDebug("Dumping the pages starting with the pde page at %p\n", pde); - - for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { - if (pde[i].present) { - PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); - PrintPT32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (pte32_t *)V3_VAddr((void *)(addr_t)(pde[i].pt_base_addr << PAGE_POWER))); - } - } -} - - - - - - - - void PrintPDPE32PAE(addr_t virtual_address, pdpe32pae_t * pdpe) { PrintDebug("PDPE %p -> %p : present=%x, wt=%x, cd=%x, accessed=%x, kernelInfo=%x\n", @@ -154,46 +101,6 @@ void PrintPTE32PAE(addr_t virtual_address, pte32pae_t * pte) -void PrintDebugPageTables32PAE(pdpe32pae_t * pdpe) -{ - int i, j, k; - pde32pae_t * pde; - pte32pae_t * pte; - addr_t virtual_addr = 0; - - PrintDebug("Dumping the pages starting with the pde page at %p\n", pdpe); - - for (i = 0; (i < MAX_PDPE32PAE_ENTRIES); i++) { - - if (pdpe[i].present) { - pde = (pde32pae_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(pdpe[i].pd_base_addr)); - - PrintPDPE32PAE(virtual_addr, &(pdpe[i])); - - for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) { - - if (pde[j].present) { - pte = (pte32pae_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(pde[j].pt_base_addr)); - - PrintPDE32PAE(virtual_addr, &(pde[j])); - - for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) { - if (pte[k].present) { - PrintPTE32PAE(virtual_addr, &(pte[k])); - } - - virtual_addr += PAGE_SIZE; - } - } else { - virtual_addr += PAGE_SIZE * MAX_PTE32PAE_ENTRIES; - } - } - } else { - virtual_addr += PAGE_SIZE * MAX_PDE32PAE_ENTRIES * MAX_PTE32PAE_ENTRIES; - } - } -} - void PrintPML4e64(addr_t virtual_address, pml4e64_t * pml) @@ -269,6 +176,104 @@ void PrintPTE64(addr_t virtual_address, pte64_t * pte) + + + + + + + +void PrintPD32(pde32_t * pde) +{ + int i; + + PrintDebug("Page Directory at %p:\n", pde); + for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { + if ( pde[i].present) { + PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); + } + } +} + +void PrintPT32(addr_t starting_address, pte32_t * pte) +{ + int i; + + PrintDebug("Page Table at %p:\n", pte); + for (i = 0; (i < MAX_PTE32_ENTRIES) ; i++) { + if (pte[i].present) { + PrintPTE32(starting_address + (PAGE_SIZE * i), &(pte[i])); + } + } +} + + + + + + + +void PrintDebugPageTables(pde32_t * pde) +{ + int i; + + PrintDebug("Dumping the pages starting with the pde page at %p\n", pde); + + for (i = 0; (i < MAX_PDE32_ENTRIES); i++) { + if (pde[i].present) { + PrintPDE32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), &(pde[i])); + PrintPT32((addr_t)(PAGE_SIZE * MAX_PTE32_ENTRIES * i), (pte32_t *)V3_VAddr((void *)(addr_t)(pde[i].pt_base_addr << PAGE_POWER))); + } + } +} + + + + +void PrintDebugPageTables32PAE(pdpe32pae_t * pdpe) +{ + int i, j, k; + pde32pae_t * pde; + pte32pae_t * pte; + addr_t virtual_addr = 0; + + PrintDebug("Dumping the pages starting with the pde page at %p\n", pdpe); + + for (i = 0; (i < MAX_PDPE32PAE_ENTRIES); i++) { + + if (pdpe[i].present) { + pde = (pde32pae_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(pdpe[i].pd_base_addr)); + + PrintPDPE32PAE(virtual_addr, &(pdpe[i])); + + for (j = 0; j < MAX_PDE32PAE_ENTRIES; j++) { + + if (pde[j].present) { + pte = (pte32pae_t *)V3_VAddr((void *)(addr_t)BASE_TO_PAGE_ADDR(pde[j].pt_base_addr)); + + PrintPDE32PAE(virtual_addr, &(pde[j])); + + for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) { + if (pte[k].present) { + PrintPTE32PAE(virtual_addr, &(pte[k])); + } + + virtual_addr += PAGE_SIZE; + } + } else { + virtual_addr += PAGE_SIZE * MAX_PTE32PAE_ENTRIES; + } + } + } else { + virtual_addr += PAGE_SIZE * MAX_PDE32PAE_ENTRIES * MAX_PTE32PAE_ENTRIES; + } + } +} + + + + + void PrintPageTree_64(addr_t virtual_addr, pml4e64_t * pml) { uint_t pml4_index = PML4E64_INDEX(virtual_addr); uint_t pdpe_index = PDPE64_INDEX(virtual_addr); diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 702b6f0..894ecc4 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -99,56 +99,6 @@ int v3_init_shadow_page_state(struct guest_info * info) { -/* - For now we'll do something a little more lightweight -int cache_page_tables32(struct guest_info * info, addr_t pde) { - struct shadow_page_state * state = &(info->shdw_pg_state); - addr_t pde_host_addr; - pde32_t * tmp_pde; - struct hashtable * pte_cache = NULL; - int i = 0; - - - pte_cache = (struct hashtable *)find_cr3_in_cache(state->cr3_cache, pde); - if (pte_cache != NULL) { - PrintError("CR3 already present in cache\n"); - state->current_ptes = pte_cache; - return 1; - } else { - PrintError("Creating new CR3 cache entry\n"); - pte_cache = create_hashtable(0, &pte_hash_fn, &pte_equals); - state->current_ptes = pte_cache; - add_cr3_to_cache(state->cr3_cache, pde, pte_cache); - } - - if (guest_pa_to_host_va(info, pde, &pde_host_addr) == -1) { - PrintError("Could not lookup host address of guest PDE\n"); - return -1; - } - - tmp_pde = (pde32_t *)pde_host_addr; - - add_pte_map(pte_cache, pde, pde_host_addr); - - - for (i = 0; i < MAX_PDE32_ENTRIES; i++) { - if ((tmp_pde[i].present) && (tmp_pde[i].large_page == 0)) { - addr_t pte_host_addr; - - if (guest_pa_to_host_va(info, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), &pte_host_addr) == -1) { - PrintError("Could not lookup host address of guest PDE\n"); - return -1; - } - - add_pte_map(pte_cache, (addr_t)(PDE32_T_ADDR(tmp_pde[i])), pte_host_addr); - } - } - - - return 0; -} -*/ - int v3_cache_page_tables(struct guest_info * info, addr_t cr3) { switch(v3_get_cpu_mode(info)) { @@ -278,8 +228,8 @@ static int activate_shadow_pt_32pae(struct guest_info * info) { return -1; } -static void activate_shadow_pt_64_cb(page_type_t type, addr_t page_ptr, addr_t page_pa, void * private_data) { - PrintDebug("CB: Page: %p, Type: %s\n", (void *)page_pa, v3_page_type_to_str(type)); +static void activate_shadow_pt_64_cb(page_type_t type, addr_t vaddr, addr_t page_ptr, addr_t page_pa, void * private_data) { + PrintDebug("CB: Page: %p->%p (host_ptr=%p), Type: %s\n", (void *)vaddr, (void *)page_pa, (void *)page_ptr, v3_page_type_to_str(type)); } @@ -967,133 +917,3 @@ int v3_handle_shadow_invlpg(struct guest_info * info) } -/* - - -static int create_pd32_nonaligned_4MB_page(struct guest_info * info, pte32_t * pt, addr_t guest_addr, pde32_4MB_t * large_shadow_pde) { - uint_t i = 0; - pte32_t * pte_cursor; - addr_t guest_pa = 0; - - for (i = 0; i < 1024; i++) { - guest_pa = guest_addr + (PAGE_SIZE * i); - host_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa); - - pte_cursor = &(pt[i]); - - if (host_page_type == HOST_REGION_INVALID) { - // Currently we don't support this, but in theory we could - PrintError("Invalid Host Memory Type\n"); - return -1; - } else if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) { - addr_t shadow_pa = get_shadow_addr(info, guest_pa); - - - pte_cursor->page_base_addr = PT32_BASE_ADDR(shadow_pa); - pte_cursor->present = 1; - pte_cursor->writable = large_shadow_pde->writable; - pte_cursor->user_page = large_shadow_pde->user_page; - pte_cursor->write_through = 0; - pte_cursor->cache_disable = 0; - pte_cursor->global_page = 0; - - } else { - PrintError("Unsupported Host Memory Type\n"); - return -1; - } - } - return 0; -} - - -static int handle_large_pagefault32(struct guest_info * info, - pde32_t * guest_pde, pde32_t * shadow_pde, - addr_t fault_addr, pf_error_t error_code ) { - struct shadow_region * mem_reg; - pde32_4MB_t * large_guest_pde = (pde32_4MB_t *)guest_pde; - pde32_4MB_t * large_shadow_pde = (pde32_4MB_t *)shadow_pde; - host_region_type_t host_page_type; - addr_t guest_start_addr = PDE32_4MB_T_ADDR(*large_guest_pde); - // addr_t guest_end_addr = guest_start_addr + PAGE_SIZE_4MB; // start address + 4MB - - - // Check that the Guest PDE entry points to valid memory - // else Machine Check the guest - PrintDebug("Large Page: Page Base Addr=%x\n", guest_start_addr); - - host_page_type = get_shadow_addr_type(info, guest_start_addr); - - if (host_page_type == HOST_REGION_INVALID) { - PrintError("Invalid guest address in large page (0x%x)\n", guest_start_addr); - v3_raise_exception(info, MC_EXCEPTION); - return -1; - } - - // else... - - if (host_page_type == HOST_REGION_PHYSICAL_MEMORY) { - - addr_t host_start_addr = 0; - addr_t region_end_addr = 0; - - // Check for a large enough region in host memory - mem_reg = get_shadow_region_by_addr(&(info->mem_map), guest_start_addr); - PrintDebug("Host region: host_addr=%x (guest_start=%x, end=%x)\n", - mem_reg->host_addr, mem_reg->guest_start, mem_reg->guest_end); - host_start_addr = mem_reg->host_addr + (guest_start_addr - mem_reg->guest_start); - region_end_addr = mem_reg->host_addr + (mem_reg->guest_end - mem_reg->guest_start); - - PrintDebug("Host Start Addr=%x; Region End Addr=%x\n", host_start_addr, region_end_addr); - - - //4f - if (large_guest_pde->dirty == 1) { // dirty - large_shadow_pde->writable = guest_pde->writable; - } else if (error_code.write == 1) { // not dirty, access is write - large_shadow_pde->writable = guest_pde->writable; - large_guest_pde->dirty = 1; - } else { // not dirty, access is read - large_shadow_pde->writable = 0; - } - - - // Check if the region is at least an additional 4MB - - - //4b. - if ((PD32_4MB_PAGE_OFFSET(host_start_addr) == 0) && - (region_end_addr >= host_start_addr + PAGE_SIZE_4MB)) { // if 4MB boundary - large_shadow_pde->page_base_addr = PD32_4MB_BASE_ADDR(host_start_addr); - } else { // else generate 4k pages - pte32_t * shadow_pt = NULL; - PrintDebug("Handling non aligned large page\n"); - - shadow_pde->large_page = 0; - - shadow_pt = create_new_shadow_pt32(); - - if (create_pd32_nonaligned_4MB_page(info, shadow_pt, guest_start_addr, large_shadow_pde) == -1) { - PrintError("Non Aligned Large Page Error\n"); - V3_Free(shadow_pt); - return -1; - } - - -#ifdef DEBUG_SHADOW_PAGING - PrintDebug("non-aligned Shadow PT\n"); - PrintPT32(PT32_PAGE_ADDR(fault_addr), shadow_pt); -#endif - shadow_pde->pt_base_addr = PD32_BASE_ADDR(shadow_pt); - } - - } else { - // Handle hooked pages as well as other special pages - if (handle_special_page_fault(info, fault_addr, guest_start_addr, error_code) == -1) { - PrintError("Special Page Fault handler returned error for address: %x\n", fault_addr); - return -1; - } - } - - return 0; -} -*/