From: Jack Lange Date: Fri, 31 Oct 2008 19:36:06 +0000 (-0500) Subject: added pae+64 bit page table access checks X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=a71d13e84ccd2ea959299c7f01513e6f9e593b7d added pae+64 bit page table access checks moved memory conversion functions to use new page table translate functions --- diff --git a/palacios/include/palacios/vmm_paging.h b/palacios/include/palacios/vmm_paging.h index 51e13d0..7c472d7 100644 --- a/palacios/include/palacios/vmm_paging.h +++ b/palacios/include/palacios/vmm_paging.h @@ -93,17 +93,18 @@ the host state in the vmcs before entering the guest. -#define MAX_PTE32_ENTRIES 1024 #define MAX_PDE32_ENTRIES 1024 +#define MAX_PTE32_ENTRIES 1024 -#define MAX_PTE32PAE_ENTRIES 512 -#define MAX_PDE32PAE_ENTRIES 512 #define MAX_PDPE32PAE_ENTRIES 4 +#define MAX_PDE32PAE_ENTRIES 512 +#define MAX_PTE32PAE_ENTRIES 512 -#define MAX_PTE64_ENTRIES 512 -#define MAX_PDE64_ENTRIES 512 -#define MAX_PDPE64_ENTRIES 512 #define MAX_PML4E64_ENTRIES 512 +#define MAX_PDPE64_ENTRIES 512 +#define MAX_PDE64_ENTRIES 512 +#define MAX_PTE64_ENTRIES 512 + /* Converts an address into a page table index */ @@ -224,6 +225,13 @@ the host state in the vmcs before entering the guest. typedef enum {PT_ENTRY_NOT_PRESENT, PT_ENTRY_LARGE_PAGE, PT_ENTRY_PAGE} pt_entry_type_t; typedef enum {PT_ACCESS_OK, PT_ACCESS_NOT_PRESENT, PT_ACCESS_WRITE_ERROR, PT_ACCESS_USER_ERROR} pt_access_status_t; + +typedef struct gen_pt { + uint_t present : 1; + uint_t writable : 1; + uint_t user_page : 1; +} __attribute__((packed)) gen_pt_t; + typedef struct pde32 { uint_t present : 1; uint_t writable : 1; @@ -467,13 +475,13 @@ void delete_page_tables_64(pml4e64_t * pml4); struct guest_info; -int v3_translate_guest_pt_32(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr); -int v3_translate_guest_pt_32pae(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr); -int v3_translate_guest_pt_64(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr); +int v3_translate_guest_pt_32(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr); +int v3_translate_guest_pt_32pae(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr); +int v3_translate_guest_pt_64(struct guest_info * info, v3_reg_t guest_cr3, addr_t vaddr, addr_t * paddr); -int v3_translate_host_pt_32(addr_t host_cr3, addr_t vaddr, addr_t * paddr); -int v3_translate_host_pt_32pae(addr_t host_cr3, addr_t vaddr, addr_t * paddr); -int v3_translate_host_pt_64(addr_t host_cr3, addr_t vaddr, addr_t * paddr); +int v3_translate_host_pt_32(v3_reg_t host_cr3, addr_t vaddr, addr_t * paddr); +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? */ @@ -494,8 +502,18 @@ pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry); -pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type); -pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type); +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); + +pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type); +pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type); +pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type); + +pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type); +pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type); +pt_access_status_t inline v3_can_access_pde64(pde64_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); + diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index c320727..f4cd053 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -143,82 +143,35 @@ int guest_pa_to_host_va(struct guest_info * guest_info, addr_t guest_pa, addr_t int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t * guest_pa) { + v3_reg_t guest_cr3 = 0; + if (guest_info->mem_mode == PHYSICAL_MEM) { // guest virtual address is the same as the physical *guest_pa = guest_va; return 0; } + if (guest_info->mem_mode == SHADOW_PAGING) { + guest_cr3 = guest_info->shdw_pg_state.guest_cr3; + } else { + guest_cr3 = guest_info->ctrl_regs.cr3; + } // Guest Is in Paged mode switch (guest_info->cpu_mode) { case PROTECTED: - { - addr_t tmp_pa = 0; - pde32_t * pde = 0; - addr_t guest_pde = 0; - - if (guest_info->shdw_pg_mode == SHADOW_PAGING) { - guest_pde = CR3_TO_PDE32_PA((guest_info->shdw_pg_state.guest_cr3)); - } else if (guest_info->shdw_pg_mode == NESTED_PAGING) { - guest_pde = CR3_TO_PDE32_PA((guest_info->ctrl_regs.cr3)); - } - - if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) { - PrintError("In GVA->GPA: Invalid GPA(%p)->HVA PDE32 lookup\n", - (void *)guest_pde); - return -1; - } - - - switch (pde32_lookup(pde, guest_va, &tmp_pa)) { - case PT_ENTRY_NOT_PRESENT: - *guest_pa = 0; - return -1; - case PT_ENTRY_LARGE_PAGE: - *guest_pa = tmp_pa; - return 0; - case PT_ENTRY_PAGE: - { - pte32_t * pte = 0; - - - if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) { - PrintError("In GVA->GPA: Invalid GPA(%p)->HVA PTE32 lookup\n", - (void *)guest_pa); - return -1; - } - - //PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa); - - if (pte32_lookup(pte, guest_va, guest_pa) != PT_ENTRY_PAGE) { - PrintError("In GVA->GPA: PTE32 Lookup failure GVA=%p; PTE=%p\n", - (void *)guest_va, (void *)pte); - // PrintPT32(PDE32_INDEX(guest_va) << 22, pte); - return -1; - } - - return 0; - } - default: - return -1; - } - } + return v3_translate_guest_pt_32(guest_info, guest_cr3, guest_va, guest_pa); case PROTECTED_PAE: - { - // Fill in - } + return v3_translate_guest_pt_32pae(guest_info, guest_cr3, guest_va, guest_pa); case LONG: - { - // Fill in - } + case LONG_32_COMPAT: + case LONG_16_COMPAT: + return v3_translate_guest_pt_64(guest_info, guest_cr3, guest_va, guest_pa); default: return -1; } - - return 0; } diff --git a/palacios/src/palacios/vmm_paging.c b/palacios/src/palacios/vmm_paging.c index 3bea238..718c2d8 100644 --- a/palacios/src/palacios/vmm_paging.c +++ b/palacios/src/palacios/vmm_paging.c @@ -62,7 +62,7 @@ void delete_page_tables_64(pml4e64_t * pml4) { } -int v3_translate_guest_pt_32(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr) { +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; @@ -102,7 +102,7 @@ int v3_translate_guest_pt_32(struct guest_info * info, addr_t guest_cr3, addr_t } -int v3_translate_guest_pt_32pae(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * 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; @@ -162,7 +162,7 @@ int v3_translate_guest_pt_32pae(struct guest_info * info, addr_t guest_cr3, addr return 0; } -int v3_translate_guest_pt_64(struct guest_info * info, addr_t guest_cr3, addr_t vaddr, addr_t * paddr) { +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; @@ -242,7 +242,7 @@ int v3_translate_guest_pt_64(struct guest_info * info, addr_t guest_cr3, addr_t -int v3_translate_host_pt_32(addr_t host_cr3, addr_t vaddr, addr_t * paddr) { +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; @@ -265,7 +265,7 @@ int v3_translate_host_pt_32(addr_t host_cr3, addr_t vaddr, addr_t * paddr) { } -int v3_translate_host_pt_32pae(addr_t host_cr3, addr_t vaddr, addr_t * paddr) { +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; @@ -297,7 +297,7 @@ int v3_translate_host_pt_32pae(addr_t host_cr3, addr_t vaddr, addr_t * paddr) { } -int v3_translate_host_pt_64(addr_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) { pml4e64_t * host_pmle = (pml4e64_t *)CR3_TO_PML4E64_VA(host_cr3); pdpe64_t * host_pdpe = NULL; pde64_t * host_pde = NULL; @@ -519,47 +519,81 @@ pt_entry_type_t pte64_lookup(pte64_t * pt, addr_t addr, addr_t * entry) { +static pt_access_status_t can_access_pt(gen_pt_t * pt, pf_error_t access_type) { + if (pt->present == 0) { + return PT_ACCESS_NOT_PRESENT; + } else if ((pt->writable == 0) && (access_type.write == 1)) { + return PT_ACCESS_WRITE_ERROR; + } else if ((pt->user_page == 0) && (access_type.user == 1)) { + // Check CR0.WP? + return PT_ACCESS_USER_ERROR; + } + return PT_ACCESS_OK; +} +/* + * 32 bit access checks + */ +pt_access_status_t inline v3_can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)]; + return can_access_pt(entry, access_type); +} +pt_access_status_t inline v3_can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pte[PTE32_INDEX(addr)]; + return can_access_pt(entry, access_type); +} -pt_access_status_t can_access_pde32(pde32_t * pde, addr_t addr, pf_error_t access_type) { - pde32_t * entry = &pde[PDE32_INDEX(addr)]; +/* + * 32 bit PAE access checks + */ +pt_access_status_t inline v3_can_access_pdpe32pae(pdpe32pae_t * pdpe, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE32PAE_INDEX(addr)]; + return can_access_pt(entry, access_type); +} - if (entry->present == 0) { - return PT_ACCESS_NOT_PRESENT; - } else if ((entry->writable == 0) && (access_type.write == 1)) { - return PT_ACCESS_WRITE_ERROR; - } else if ((entry->user_page == 0) && (access_type.user == 1)) { - // Check CR0.WP? - return PT_ACCESS_USER_ERROR; - } +pt_access_status_t inline v3_can_access_pde32pae(pde32pae_t * pde, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pde[PDE32PAE_INDEX(addr)]; + return can_access_pt(entry, access_type); +} - return PT_ACCESS_OK; +pt_access_status_t inline v3_can_access_pte32pae(pte32pae_t * pte, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pte[PTE32PAE_INDEX(addr)]; + return can_access_pt(entry, access_type); } +/* + * 64 Bit access checks + */ +pt_access_status_t inline v3_can_access_pml4e64(pml4e64_t * pmle, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pmle[PML4E64_INDEX(addr)]; + return can_access_pt(entry, access_type); +} -pt_access_status_t can_access_pte32(pte32_t * pte, addr_t addr, pf_error_t access_type) { - pte32_t * entry = &pte[PTE32_INDEX(addr)]; +pt_access_status_t inline v3_can_access_pdpe64(pdpe64_t * pdpe, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pdpe[PDPE64_INDEX(addr)]; + return can_access_pt(entry, access_type); +} - if (entry->present == 0) { - return PT_ACCESS_NOT_PRESENT; - } else if ((entry->writable == 0) && (access_type.write == 1)) { - return PT_ACCESS_WRITE_ERROR; - } else if ((entry->user_page == 0) && (access_type.user == 1)) { - // Check CR0.WP? - return PT_ACCESS_USER_ERROR; - } +pt_access_status_t inline v3_can_access_pde64(pde64_t * pde, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pde[PDE32_INDEX(addr)]; + return can_access_pt(entry, access_type); +} - return PT_ACCESS_OK; +pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_error_t access_type) { + gen_pt_t * entry = (gen_pt_t *)&pte[PTE64_INDEX(addr)]; + return can_access_pt(entry, access_type); } + + /* We generate a page table to correspond to a given memory layout * pulling pages from the mem_list when necessary * If there are any gaps in the layout, we add them as unmapped pages diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 287691e..d11f85f 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -462,10 +462,10 @@ static int handle_shadow_pagefault_32(struct guest_info * info, addr_t fault_add // Check the guest page permissions - guest_pde_access = can_access_pde32(guest_pd, fault_addr, error_code); + guest_pde_access = v3_can_access_pde32(guest_pd, fault_addr, error_code); // Check the shadow page permissions - shadow_pde_access = can_access_pde32(shadow_pd, fault_addr, error_code); + shadow_pde_access = v3_can_access_pde32(shadow_pd, fault_addr, error_code); /* Was the page fault caused by the Guest's page tables? */ if (is_guest_pf(guest_pde_access, shadow_pde_access) == 1) { @@ -585,7 +585,7 @@ static int handle_large_pagefault_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code, pte32_t * shadow_pt, pde32_4MB_t * large_guest_pde) { - pt_access_status_t shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code); + pt_access_status_t shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code); pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]); if (shadow_pte_access == PT_ACCESS_OK) { @@ -684,10 +684,10 @@ static int handle_shadow_pte32_fault(struct guest_info * info, // Check the guest page permissions - guest_pte_access = can_access_pte32(guest_pt, fault_addr, error_code); + guest_pte_access = v3_can_access_pte32(guest_pt, fault_addr, error_code); // Check the shadow page permissions - shadow_pte_access = can_access_pte32(shadow_pt, fault_addr, error_code); + shadow_pte_access = v3_can_access_pte32(shadow_pt, fault_addr, error_code); #ifdef DEBUG_SHADOW_PAGING PrintDebug("Guest PTE: (access=%d)\n\t", guest_pte_access);