From a8715330d18d856cd30d5ab866c16966c46039a0 Mon Sep 17 00:00:00 2001 From: Jiaqing Zhao Date: Wed, 18 Sep 2024 05:33:17 +0000 Subject: [PATCH 1/2] hv: refactor hypervisor image size helper function The hypervisor image size is determined at link time, but now it is calculated and stored in a global variable during mmu initialization, and the helper function reads from that variable. Change to calculate it inside helper function to avoid inconsistency. Tracked-On: #8738 Signed-off-by: Jiaqing Zhao Reviewed-by: Fei Li --- hypervisor/arch/x86/cpu.c | 2 +- hypervisor/arch/x86/guest/optee.c | 2 +- hypervisor/arch/x86/guest/ve820.c | 2 +- hypervisor/arch/x86/guest/vm.c | 2 +- hypervisor/arch/x86/mmu.c | 9 +-------- hypervisor/boot/include/reloc.h | 1 + hypervisor/boot/reloc.c | 5 +++++ hypervisor/common/hypercall.c | 2 +- hypervisor/include/arch/x86/asm/mmu.h | 2 -- 9 files changed, 12 insertions(+), 15 deletions(-) diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index a8ecd0d4d..931e4efa9 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -503,7 +503,7 @@ void cpu_dead(void) vmx_off(); stac(); - flush_cache_range((void *)get_hv_image_base(), get_hv_ram_size()); + flush_cache_range((void *)get_hv_image_base(), get_hv_image_size()); clac(); /* Set state to show CPU is dead */ diff --git a/hypervisor/arch/x86/guest/optee.c b/hypervisor/arch/x86/guest/optee.c index 91f6a4c14..437f5e0ed 100644 --- a/hypervisor/arch/x86/guest/optee.c +++ b/hypervisor/arch/x86/guest/optee.c @@ -45,7 +45,7 @@ void prepare_tee_vm_memmap(struct acrn_vm *vm, const struct acrn_vm_config *vm_c prepare_vm_identical_memmap(vm, E820_TYPE_RAM, EPT_WB | EPT_RWX); hv_hpa = hva2hpa((void *)(get_hv_image_base())); - ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, hv_hpa, get_hv_ram_size()); + ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, hv_hpa, get_hv_image_size()); } } diff --git a/hypervisor/arch/x86/guest/ve820.c b/hypervisor/arch/x86/guest/ve820.c index 0049f92ab..1b937529c 100644 --- a/hypervisor/arch/x86/guest/ve820.c +++ b/hypervisor/arch/x86/guest/ve820.c @@ -139,7 +139,7 @@ void create_service_vm_e820(struct acrn_vm *vm) uint16_t vm_id; uint32_t i; uint64_t hv_start_pa = hva2hpa((void *)(get_hv_image_base())); - uint64_t hv_end_pa = hv_start_pa + get_hv_ram_size(); + uint64_t hv_end_pa = hv_start_pa + get_hv_image_size(); uint32_t entries_count = get_e820_entries_count(); struct acrn_vm_config *service_vm_config = get_vm_config(vm->vm_id); diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 5a4075f23..bc47f6d54 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -528,7 +528,7 @@ static void prepare_service_vm_memmap(struct acrn_vm *vm) * will cause EPT violation if Service VM accesses hv memory */ hv_hpa = hva2hpa((void *)(get_hv_image_base())); - ept_del_mr(vm, pml4_page, hv_hpa, get_hv_ram_size()); + ept_del_mr(vm, pml4_page, hv_hpa, get_hv_image_size()); /* unmap prelaunch VM memory */ for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) { vm_config = get_vm_config(vm_id); diff --git a/hypervisor/arch/x86/mmu.c b/hypervisor/arch/x86/mmu.c index 42d34ba54..f4ed7a0f6 100644 --- a/hypervisor/arch/x86/mmu.c +++ b/hypervisor/arch/x86/mmu.c @@ -39,7 +39,6 @@ #include #include -static uint64_t hv_ram_size; static void *ppt_mmu_pml4_addr; /** * @brief The sanitized page @@ -147,11 +146,6 @@ void invept(const void *eptp) } } -uint64_t get_hv_ram_size(void) -{ - return hv_ram_size; -} - void enable_paging(void) { uint64_t tmp64 = 0UL; @@ -265,7 +259,6 @@ void init_paging(void) const struct abi_mmap *p_mmap = abi->mmap_entry; pr_dbg("HV MMU Initialization"); - hv_ram_size = (uint64_t)(&ld_ram_end - &ld_ram_start); init_sanitized_page((uint64_t *)sanitized_page, hva2hpa_early(sanitized_page)); @@ -314,7 +307,7 @@ void init_paging(void) */ hv_hva = get_hv_image_base(); pgtable_modify_or_del_map((uint64_t *)ppt_mmu_pml4_addr, hv_hva & PDE_MASK, - hv_ram_size + (((hv_hva & (PDE_SIZE - 1UL)) != 0UL) ? PDE_SIZE : 0UL), + get_hv_image_size() + (((hv_hva & (PDE_SIZE - 1UL)) != 0UL) ? PDE_SIZE : 0UL), PAGE_CACHE_WB, PAGE_CACHE_MASK | PAGE_USER, &ppt_pgtable, MR_MODIFY); /* diff --git a/hypervisor/boot/include/reloc.h b/hypervisor/boot/include/reloc.h index 73f97addf..42c7bca00 100644 --- a/hypervisor/boot/include/reloc.h +++ b/hypervisor/boot/include/reloc.h @@ -9,6 +9,7 @@ extern void relocate(void); extern uint64_t get_hv_image_delta(void); extern uint64_t get_hv_image_base(void); +extern uint64_t get_hv_image_size(void); /* external symbols that are helpful for relocation */ extern uint8_t _DYNAMIC[1]; diff --git a/hypervisor/boot/reloc.c b/hypervisor/boot/reloc.c index 1df75b7bd..108213858 100644 --- a/hypervisor/boot/reloc.c +++ b/hypervisor/boot/reloc.c @@ -55,6 +55,11 @@ uint64_t get_hv_image_base(void) return (get_hv_image_delta() + CONFIG_HV_RAM_START); } +inline uint64_t get_hv_image_size(void) +{ + return (uint64_t)(&ld_ram_end - &ld_ram_start); +} + void relocate(void) { #ifdef CONFIG_RELOC diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 9fae4744b..4dc58788e 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -764,7 +764,7 @@ static int32_t write_protect_page(struct acrn_vm *vm,const struct wp_data *wp) base_paddr = hva2hpa((void *)(get_hv_image_base())); if (((hpa <= base_paddr) && ((hpa + PAGE_SIZE) > base_paddr)) || ((hpa >= base_paddr) && - (hpa < (base_paddr + get_hv_ram_size())))) { + (hpa < (base_paddr + get_hv_image_size())))) { pr_err("%s: overlap the HV memory region.", __func__); } else { prot_set = (wp->set != 0U) ? 0UL : EPT_WR; diff --git a/hypervisor/include/arch/x86/asm/mmu.h b/hypervisor/include/arch/x86/asm/mmu.h index e35ebba39..1900448a7 100644 --- a/hypervisor/include/arch/x86/asm/mmu.h +++ b/hypervisor/include/arch/x86/asm/mmu.h @@ -169,8 +169,6 @@ void flush_vpid_global(void); */ void invept(const void *eptp); -uint64_t get_hv_ram_size(void); - /* get PDPT address from CR3 vaule in PAE mode */ static inline uint64_t get_pae_pdpt_addr(uint64_t cr3) { From d0213fdf39f6323712a9abed767643aab7c852f3 Mon Sep 17 00:00:00 2001 From: Jiaqing Zhao Date: Wed, 18 Sep 2024 08:18:29 +0000 Subject: [PATCH 2/2] hv: reserve hypervisor region in e820 table Mark hypervisor memory region as unusable in its e820 table to avoid being overlapped by e820_alloc_memory(). As it is already filtered out in hypervisor e820 table, there is no longer need to filter it out in service VM e820. Tracked-On: #8738 Signed-off-by: Jiaqing Zhao Reviewed-by: Fei Li --- hypervisor/arch/x86/e820.c | 70 ++++++++++++++++++++----------- hypervisor/arch/x86/guest/ve820.c | 4 -- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/hypervisor/arch/x86/e820.c b/hypervisor/arch/x86/e820.c index 86d8f5a77..7a2c18396 100644 --- a/hypervisor/arch/x86/e820.c +++ b/hypervisor/arch/x86/e820.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -232,6 +233,47 @@ static void calculate_e820_ram_size(void) dev_dbg(DBG_LEVEL_E820, "ram size: 0x%016lx ",hv_e820_ram_size); } +static void reserve_e820_region(uint64_t start_hpa, uint64_t end_hpa) +{ + uint32_t e820_index; + uint64_t entry_start, entry_end; + + for (e820_index = 0; e820_index < hv_e820_entries_nr; e820_index++) { + entry_start = hv_e820[e820_index].baseaddr; + entry_end = hv_e820[e820_index].baseaddr + hv_e820[e820_index].length; + + /* No need handle in these cases*/ + if ((hv_e820[e820_index].type != E820_TYPE_RAM) || (entry_end <= start_hpa) || (entry_start >= end_hpa)) { + continue; + } + + if ((entry_start <= start_hpa) && (entry_end >= end_hpa)) { + hv_e820[e820_index].length = start_hpa - entry_start; + + if (end_hpa < entry_end) { + /* + * .......|start_hpa......................end_hpa|..... + * |entry_start..............................entry_end| + */ + insert_e820_entry(e820_index + 1, end_hpa, entry_end - end_hpa, E820_TYPE_RAM); + } + } else { + panic("%s: region 0x%016x-0x%016x crosses multiple e820 entries, check your bootloader!", + __func__, entry_start, entry_end); + } + } +} + +static void alloc_hv_memory(void) +{ + uint64_t hv_start = hva2hpa((void *)(get_hv_image_base())); + uint64_t hv_end = hv_start + get_hv_image_size(); + + pr_err("%s: hv start: 0x%016x, end: 0x%016x", __func__, hv_start, hv_end); + + reserve_e820_region(hv_start, hv_end); +} + static void alloc_mods_memory(void) { uint32_t mod_index, e820_index, target_index; @@ -242,32 +284,11 @@ static void alloc_mods_memory(void) /* 1st pass: remove the exact region */ for (mod_index = 0; mod_index < abi->mods_count; mod_index++) { mod_start = hva2hpa(abi->mods[mod_index].start); - mod_end = hva2hpa(abi->mods[mod_index].start) + abi->mods[mod_index].size; + mod_end = mod_start + abi->mods[mod_index].size; - for (e820_index = 0; e820_index < hv_e820_entries_nr; e820_index++) { - entry_start = hv_e820[e820_index].baseaddr; - entry_end = hv_e820[e820_index].baseaddr + hv_e820[e820_index].length; + pr_err("%s: mod %d, start: 0x%016x, end: 0x%016x", __func__, mod_index, mod_start, mod_end); - /* No need handle in these cases*/ - if ((hv_e820[e820_index].type != E820_TYPE_RAM) || (entry_end <= mod_start) || (entry_start >= mod_end)) { - continue; - } - - if ((entry_start <= mod_start) && (entry_end >= mod_end)) { - hv_e820[e820_index].length = mod_start - entry_start; - - if (mod_end < entry_end) { - /* - * .......|start_pa... ....................end_pa|..... - * |entry_start..............................entry_end| - */ - insert_e820_entry(e820_index + 1, mod_end, entry_end - mod_end, E820_TYPE_RAM); - } - } else { - panic("%s: region 0x%016x-0x%016x crosses multiple e820 entries, check your bootloader!", - __func__, entry_start, entry_end); - } - } + reserve_e820_region(mod_start, mod_end); } /* 2nd pass: shrink the entries to page boundary */ @@ -300,6 +321,7 @@ void init_e820(void) } calculate_e820_ram_size(); + alloc_hv_memory(); /* reserve multiboot modules memory */ alloc_mods_memory(); } diff --git a/hypervisor/arch/x86/guest/ve820.c b/hypervisor/arch/x86/guest/ve820.c index 1b937529c..e2d86fd86 100644 --- a/hypervisor/arch/x86/guest/ve820.c +++ b/hypervisor/arch/x86/guest/ve820.c @@ -138,8 +138,6 @@ void create_service_vm_e820(struct acrn_vm *vm) { uint16_t vm_id; uint32_t i; - uint64_t hv_start_pa = hva2hpa((void *)(get_hv_image_base())); - uint64_t hv_end_pa = hv_start_pa + get_hv_image_size(); uint32_t entries_count = get_e820_entries_count(); struct acrn_vm_config *service_vm_config = get_vm_config(vm->vm_id); @@ -148,8 +146,6 @@ void create_service_vm_e820(struct acrn_vm *vm) vm->e820_entry_num = entries_count; vm->e820_entries = service_vm_e820; - /* filter out hv memory from e820 table */ - filter_mem_from_service_vm_e820(vm, hv_start_pa, hv_end_pa); /* filter out prelaunched vm memory from e820 table */ for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {