From 92cd2612fc919c52a480d2472e30077d6100a050 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Fri, 22 Jun 2018 10:16:17 -0700 Subject: [PATCH] hv: fixup addresses in the c code for relocation - Trampoline code doesn't have the same relocation delta with HV, Need to manually patch them when referenced from HV - replace all references to CONFIG_RAM_START with the actual HV load address Signed-off-by: Zheng Gen Signed-off-by: Zide Chen Reviewed-by: Yin Fengwei --- hypervisor/arch/x86/cpu.c | 27 ++++++++++++++++++--------- hypervisor/arch/x86/guest/guest.c | 8 +++++--- hypervisor/arch/x86/mmu.c | 6 ++++-- hypervisor/arch/x86/pm.c | 16 +++++----------- hypervisor/boot/include/reloc.h | 2 ++ hypervisor/boot/reloc.c | 16 ++++++++++++++++ hypervisor/common/hypercall.c | 12 +++++++----- 7 files changed, 57 insertions(+), 30 deletions(-) diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 0224c3575..734d6bfd1 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef CONFIG_EFI_STUB #include @@ -662,39 +663,47 @@ static void update_trampoline_code_refs(uint64_t dest_pa) * trampoline code starts in real mode, * so the target addres is HPA */ - val = dest_pa + (uint64_t)trampoline_fixup_target; + val = dest_pa + trampoline_relo_addr(trampoline_fixup_target); - ptr = HPA2HVA(dest_pa + (uint64_t)trampoline_fixup_cs); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_fixup_cs)); *(uint16_t *)(ptr) = (uint16_t)((val >> 4) & 0xFFFFU); - ptr = HPA2HVA(dest_pa + (uint64_t)trampoline_fixup_ip); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_fixup_ip)); *(uint16_t *)(ptr) = (uint16_t)(val & 0xfU); /* Update temporary page tables */ - ptr = HPA2HVA(dest_pa + (uint64_t)CPU_Boot_Page_Tables_ptr); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(CPU_Boot_Page_Tables_ptr)); *(uint32_t *)(ptr) += dest_pa; - ptr = HPA2HVA(dest_pa + (uint64_t)CPU_Boot_Page_Tables_Start); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(CPU_Boot_Page_Tables_Start)); *(uint64_t *)(ptr) += dest_pa; - ptr = HPA2HVA(dest_pa + (uint64_t)trampoline_pdpt_addr); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_pdpt_addr)); for (i = 0; i < 4; i++) *(uint64_t *)(ptr + sizeof(uint64_t) * i) += dest_pa; /* update the gdt base pointer with relocated offset */ - ptr = HPA2HVA(dest_pa + (uint64_t)trampoline_gdt_ptr); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_gdt_ptr)); *(uint64_t *)(ptr + 2) += dest_pa; /* update trampoline jump pointer with relocated offset */ - ptr = HPA2HVA(dest_pa + (uint64_t)trampoline_start64_fixup); + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_start64_fixup)); *(uint32_t *)ptr += (uint32_t)dest_pa; + + /* update trampoline's main entry pointer */ + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(main_entry)); + *(uint64_t *)ptr += get_hv_image_delta(); + + /* update trampoline's spinlock pointer */ + ptr = HPA2HVA(dest_pa + trampoline_relo_addr(trampoline_spinlock_ptr)); + *(uint64_t *)ptr += get_hv_image_delta(); } static uint64_t prepare_trampoline(void) { uint64_t size, dest_pa; - size = (uint64_t)_ld_trampoline_end - (uint64_t)trampoline_start16; + size = (uint64_t)_ld_trampoline_end - (uint64_t)_ld_trampoline_start; #ifndef CONFIG_EFI_STUB dest_pa = e820_alloc_low_memory(CONFIG_LOW_RAM_SIZE); #else diff --git a/hypervisor/arch/x86/guest/guest.c b/hypervisor/arch/x86/guest/guest.c index 5f143093a..a5d7df4b5 100644 --- a/hypervisor/arch/x86/guest/guest.c +++ b/hypervisor/arch/x86/guest/guest.c @@ -7,6 +7,7 @@ #include #include #include +#include #define ACRN_DBG_GUEST 6 @@ -496,7 +497,7 @@ static void rebuild_vm0_e820(void) uint32_t i; uint64_t entry_start; uint64_t entry_end; - uint64_t hv_start = CONFIG_RAM_START; + uint64_t hv_start = get_hv_image_base(); uint64_t hv_end = hv_start + CONFIG_RAM_SIZE; struct e820_entry *entry, new_entry = {0}; @@ -577,6 +578,7 @@ int prepare_vm0_memmap_and_e820(struct vm *vm) IA32E_EPT_X_BIT | IA32E_EPT_UNCACHED); struct e820_entry *entry; + uint64_t hv_hpa; rebuild_vm0_e820(); dev_dbg(ACRN_DBG_GUEST, @@ -610,8 +612,8 @@ int prepare_vm0_memmap_and_e820(struct vm *vm) /* unmap hypervisor itself for safety * will cause EPT violation if sos accesses hv memory */ - ept_mmap(vm, CONFIG_RAM_START, CONFIG_RAM_START, - CONFIG_RAM_SIZE, MAP_UNMAP, 0); + hv_hpa = get_hv_image_base(); + ept_mmap(vm, hv_hpa, hv_hpa, CONFIG_RAM_SIZE, MAP_UNMAP, 0); return 0; } diff --git a/hypervisor/arch/x86/mmu.c b/hypervisor/arch/x86/mmu.c index a52d8a436..5c6112728 100644 --- a/hypervisor/arch/x86/mmu.c +++ b/hypervisor/arch/x86/mmu.c @@ -28,6 +28,7 @@ */ #include +#include static void *mmu_pml4_addr; @@ -593,6 +594,7 @@ void init_paging(void) { struct map_params map_params; struct e820_entry *entry; + uint64_t hv_hpa; uint32_t i; int attr_wb = (MMU_MEM_ATTR_BIT_READ_WRITE | MMU_MEM_ATTR_BIT_USER_ACCESSIBLE | @@ -632,8 +634,8 @@ void init_paging(void) /* set the paging-structure entries' U/S flag * to supervisor-mode for hypervisor owned memroy. */ - modify_mem(&map_params, (void *)CONFIG_RAM_START, - (void *)CONFIG_RAM_START, + hv_hpa = get_hv_image_base(); + modify_mem(&map_params, (void *)hv_hpa, (void *)hv_hpa, CONFIG_RAM_SIZE, attr_wb & (~MMU_MEM_ATTR_BIT_USER_ACCESSIBLE)); pr_dbg("Enabling MMU "); diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index 08edcaacf..ffc825e12 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ #include +#include struct run_context cpu_ctx; @@ -78,7 +79,6 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, uint32_t pcpu_id; uint64_t pmain_entry_saved; uint32_t guest_wakeup_vec32; - uint64_t *pmain_entry; /* We assume enter s3 success by default */ host_enter_s3_success = 1; @@ -104,20 +104,14 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, /* offline all APs */ stop_cpus(); - /* Trampoline code is relocatable now. We have to calculate - * main_entry address with relocation base address - */ - pmain_entry = - (uint64_t *)(HPA2HVA(trampoline_start16_paddr) + - (uint64_t) main_entry); - /* Save default main entry and we will restore it after * back from S3. So the AP online could jmp to correct * main entry. */ - pmain_entry_saved = *pmain_entry; + pmain_entry_saved = read_trampoline_sym(main_entry); + /* Set the main entry for resume from S3 state */ - *pmain_entry = (uint64_t)restore_s3_context; + write_trampoline_sym(main_entry, (uint64_t)restore_s3_context); CPU_IRQ_DISABLE(); vmx_off(pcpu_id); @@ -141,7 +135,7 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, CPU_IRQ_ENABLE(); /* restore the default main entry */ - *pmain_entry = pmain_entry_saved; + write_trampoline_sym(main_entry, pmain_entry_saved); /* online all APs again */ start_cpus(); diff --git a/hypervisor/boot/include/reloc.h b/hypervisor/boot/include/reloc.h index 0b420a868..367af155d 100755 --- a/hypervisor/boot/include/reloc.h +++ b/hypervisor/boot/include/reloc.h @@ -10,6 +10,8 @@ extern void _relocate(void); extern uint64_t get_hv_image_delta(void); extern uint64_t get_hv_image_base(void); extern uint64_t trampoline_relo_addr(void *addr); +extern uint64_t read_trampoline_sym(void *sym); +extern void write_trampoline_sym(void *sym, uint64_t val); /* external symbols that are helpful for relocation */ extern uint8_t _DYNAMIC[]; diff --git a/hypervisor/boot/reloc.c b/hypervisor/boot/reloc.c index c6ec0aea2..3cbc4d8a9 100644 --- a/hypervisor/boot/reloc.c +++ b/hypervisor/boot/reloc.c @@ -131,3 +131,19 @@ void _relocate(void) start = (struct Elf64_Rel *)((char *)start + size); } } + +uint64_t read_trampoline_sym(void *sym) +{ + uint64_t *hva; + + hva = HPA2HVA(trampoline_start16_paddr) + trampoline_relo_addr(sym); + return *hva; +} + +void write_trampoline_sym(void *sym, uint64_t val) +{ + uint64_t *hva; + + hva = HPA2HVA(trampoline_start16_paddr) + trampoline_relo_addr(sym); + *hva = val; +} diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index 507959200..b15303f6e 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -8,6 +8,7 @@ #include #include #include +#include #define ACRN_DBG_HYCALL 6 @@ -393,7 +394,7 @@ int64_t hcall_notify_req_finish(uint64_t vmid, uint64_t vcpu_id) int64_t _set_vm_memmap(struct vm *vm, struct vm *target_vm, struct vm_set_memmap *memmap) { - uint64_t hpa; + uint64_t hpa, base_paddr; uint32_t attr, prot; if ((memmap->length & 0xFFFUL) != 0UL) { @@ -406,10 +407,11 @@ int64_t _set_vm_memmap(struct vm *vm, struct vm *target_vm, dev_dbg(ACRN_DBG_HYCALL, "[vm%d] gpa=0x%x hpa=0x%x size=0x%x", target_vm->attr.id, memmap->remote_gpa, hpa, memmap->length); - if (((hpa <= CONFIG_RAM_START) && - (hpa + memmap->length > CONFIG_RAM_START)) || - ((hpa >= CONFIG_RAM_START) && - (hpa < CONFIG_RAM_START + CONFIG_RAM_SIZE))) { + base_paddr = get_hv_image_base(); + if (((hpa <= base_paddr) && + (hpa + memmap->length > base_paddr)) || + ((hpa >= base_paddr) && + (hpa < base_paddr + CONFIG_RAM_SIZE))) { pr_err("%s: ERROR! overlap the HV memory region.", __func__); return -1; }