From 5d2ab4d9efd497227af44637cef936b019ba7c59 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 6 Jun 2018 09:13:33 -0700 Subject: [PATCH] hv: add APIs to allow updating EPT mem type - Add PAGING_REQUEST_TYPE_MODIFY_MT memory map request type - Update map_mem_region() to allow modifying the memory type related fields in a page table entry - Add ept_update_mt() - add modify_mem_mt() for both EPT and MMU Signed-off-by: Zide Chen Reviewed-by: Jason Chen CJ Acked-by: Eddie Dong --- hypervisor/arch/x86/ept.c | 21 +++++++++++++++ hypervisor/arch/x86/mmu.c | 43 +++++++++++++++++++++++++++++++ hypervisor/include/arch/x86/mmu.h | 8 ++++++ 3 files changed, 72 insertions(+) diff --git a/hypervisor/arch/x86/ept.c b/hypervisor/arch/x86/ept.c index b40683063..d0f152273 100644 --- a/hypervisor/arch/x86/ept.c +++ b/hypervisor/arch/x86/ept.c @@ -489,3 +489,24 @@ int ept_mmap(struct vm *vm, uint64_t hpa, return 0; } + +int ept_update_mt(struct vm *vm, uint64_t hpa, + uint64_t gpa, uint64_t size, uint32_t prot) +{ + struct map_params map_params; + struct vcpu *vcpu; + int i; + + /* Setup memory map parameters */ + map_params.page_table_type = PTT_EPT; + map_params.pml4_base = HPA2HVA(vm->arch_vm.nworld_eptp); + map_params.pml4_inverted = HPA2HVA(vm->arch_vm.m2p); + + modify_mem_mt(&map_params, (void *)hpa, (void *)gpa, size, prot); + + foreach_vcpu(i, vm, vcpu) { + vcpu_make_request(vcpu, ACRN_REQUEST_EPT_FLUSH); + } + + return 0; +} diff --git a/hypervisor/arch/x86/mmu.c b/hypervisor/arch/x86/mmu.c index 9af2d21cd..d3581d387 100644 --- a/hypervisor/arch/x86/mmu.c +++ b/hypervisor/arch/x86/mmu.c @@ -35,6 +35,7 @@ enum mem_map_request_type { PAGING_REQUEST_TYPE_MAP = 0, /* Creates a new mapping. */ PAGING_REQUEST_TYPE_UNMAP = 1, /* Removes a pre-existing entry */ PAGING_REQUEST_TYPE_MODIFY = 2, + PAGING_REQUEST_TYPE_MODIFY_MT = 3, /* Update the memory type fields */ /* Modifies a pre-existing entries attributes. */ PAGING_REQUEST_TYPE_UNKNOWN, }; @@ -375,6 +376,28 @@ static uint32_t map_mem_region(void *vaddr, void *paddr, mmu_need_invtlb = true; break; } + case PAGING_REQUEST_TYPE_MODIFY_MT: + { + if (prev_entry_present) { + /* modify the memory type related fields only */ + if (table_type == PTT_EPT) + table_entry = entry & ~IA32E_EPT_MT_MASK; + else + table_entry = entry & ~MMU_MEM_ATTR_TYPE_MASK; + + table_entry |= attr; + + /* Write the table entry to map this memory */ + MEM_WRITE64(table_base + table_offset, table_entry); + + /* Modify, need to invalidate TLB and + * page-structure cache + */ + if (table_type == PTT_HOST) + mmu_need_invtlb = true; + } + break; + } default: ASSERT(0, "Bad memory map request type"); return 0; @@ -1124,3 +1147,23 @@ int modify_mem(struct map_params *map_params, void *paddr, void *vaddr, } return ret; } + +int modify_mem_mt(struct map_params *map_params, void *paddr, void *vaddr, + uint64_t size, uint32_t flags) +{ + int ret = 0; + + /* used for MMU and EPT*/ + ret = modify_paging(map_params, paddr, vaddr, size, flags, + PAGING_REQUEST_TYPE_MODIFY_MT, true); + if (ret < 0) + return ret; + + /* only for EPT */ + if (map_params->page_table_type == PTT_EPT) { + ret = modify_paging(map_params, vaddr, paddr, size, flags, + PAGING_REQUEST_TYPE_MODIFY_MT, false); + } + return ret; +} + diff --git a/hypervisor/include/arch/x86/mmu.h b/hypervisor/include/arch/x86/mmu.h index 326346a55..81ce62052 100644 --- a/hypervisor/include/arch/x86/mmu.h +++ b/hypervisor/include/arch/x86/mmu.h @@ -28,6 +28,7 @@ #define IA32E_EPT_WT (4<<3) #define IA32E_EPT_WP (5<<3) #define IA32E_EPT_WB (6<<3) +#define IA32E_EPT_MT_MASK (7<<3) #define IA32E_EPT_PAT_IGNORE 0x0000000000000040 #define IA32E_EPT_ACCESS_FLAG 0x0000000000000100 #define IA32E_EPT_DIRTY_FLAG 0x0000000000000200 @@ -216,6 +217,9 @@ /* Selects PAT7 WP */ #define MMU_MEM_ATTR_TYPE_WRITE_PROTECTED \ (IA32E_PDPTE_PAT_BIT | IA32E_COMM_PCD_BIT | IA32E_COMM_PWT_BIT) +/* memory type bits mask */ +#define MMU_MEM_ATTR_TYPE_MASK \ + (IA32E_PDPTE_PAT_BIT | IA32E_COMM_PCD_BIT | IA32E_COMM_PWT_BIT) #define ROUND_PAGE_UP(addr) (((addr) + CPU_PAGE_SIZE - 1) & CPU_PAGE_MASK) #define ROUND_PAGE_DOWN(addr) ((addr) & CPU_PAGE_MASK) @@ -302,6 +306,8 @@ int unmap_mem(struct map_params *map_params, void *paddr, void *vaddr, uint64_t size, uint32_t flags); int modify_mem(struct map_params *map_params, void *paddr, void *vaddr, uint64_t size, uint32_t flags); +int modify_mem_mt(struct map_params *map_params, void *paddr, void *vaddr, + uint64_t size, uint32_t flags); int check_vmx_mmu_cap(void); int allocate_vpid(void); void flush_vpid_single(int vpid); @@ -375,6 +381,8 @@ uint64_t _gpa2hpa(struct vm *vm, uint64_t gpa, uint32_t *size); uint64_t hpa2gpa(struct vm *vm, uint64_t hpa); int ept_mmap(struct vm *vm, uint64_t hpa, uint64_t gpa, uint64_t size, uint32_t type, uint32_t prot); +int ept_update_mt(struct vm *vm, uint64_t hpa, + uint64_t gpa, uint64_t size, uint32_t prot); int ept_violation_vmexit_handler(struct vcpu *vcpu); int ept_misconfig_vmexit_handler(struct vcpu *vcpu);