From fe6397d9d8e5164be2cce32447df69d619435a92 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Wed, 2 May 2018 23:39:57 -0700 Subject: [PATCH] HV: Make AP trampoline code relocatable V3->V4: Updated function/variable names for accurancy V2->V3: Changed a few function/variable names to make it less confusing V1->V2: removed the unneccesary cache flushing - For UEFI boot, allocate memory for trampoline code in ACRN EFI, and pass the pointer to HV through efi_ctx - For other boot, scan E820 to allocate memory in HV run time - update_trampoline_code_refs() updates all the references that need the absolute PA with the actual load address Signed-off-by: Zheng, Gen Signed-off-by: Jason Chen CJ Signed-off-by: Zide Chen Acked-by: Eddie Dong Acked-by: Xu, Anthony --- hypervisor/arch/x86/cpu.c | 66 +++++++++++++++++++++++----- hypervisor/bsp/uefi/efi/boot.c | 13 +++--- hypervisor/bsp/uefi/efi/boot.h | 1 + hypervisor/bsp/uefi/uefi.c | 7 ++- hypervisor/include/arch/x86/cpu.h | 8 +++- hypervisor/include/common/acrn_efi.h | 2 + 6 files changed, 79 insertions(+), 18 deletions(-) diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index 02fb4b6f4..9d947be82 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -38,9 +39,12 @@ #include #ifdef CONFIG_EFI_STUB +#include extern uint32_t efi_physical_available_ap_bitmap; #endif +uint64_t trampoline_code_paddr = 0; + spinlock_t cpu_secondary_spinlock = { .head = 0, .tail = 0 @@ -88,6 +92,7 @@ int cpu_find_logical_id(uint32_t lapic_id); #ifndef CONFIG_EFI_STUB static void start_cpus(void); #endif +static uint64_t relocate_trampoline_code(void); static void pcpu_sync_sleep(unsigned long *sync, int mask_bit); int ibrs_type; @@ -548,10 +553,7 @@ void bsp_boot_init(void) /* Trigger event to allow secondary CPUs to continue */ bitmap_set(0, &pcpu_sync); #else - memcpy_s(_ld_cpu_secondary_reset_start, - (unsigned long)&_ld_cpu_secondary_reset_size, - _ld_cpu_secondary_reset_load, - (unsigned long)&_ld_cpu_secondary_reset_size); + relocate_trampoline_code(); #endif ASSERT(get_cpu_id() == CPU_BOOT_ID, ""); @@ -660,12 +662,9 @@ static void start_cpus() { uint32_t timeout; uint32_t expected_up; + uint64_t startup_paddr; - /*Copy segment for AP initialization code below 1MB */ - memcpy_s(_ld_cpu_secondary_reset_start, - (unsigned long)&_ld_cpu_secondary_reset_size, - _ld_cpu_secondary_reset_load, - (unsigned long)&_ld_cpu_secondary_reset_size); + startup_paddr = relocate_trampoline_code(); /* Set flag showing number of CPUs expected to be up to all * cpus @@ -674,7 +673,7 @@ static void start_cpus() /* Broadcast IPIs to all other CPUs */ send_startup_ipi(INTR_CPU_STARTUP_ALL_EX_SELF, - -1U, ((uint64_t) cpu_secondary_reset)); + -1U, startup_paddr); /* Wait until global count is equal to expected CPU up count or * configured time-out has expired @@ -700,6 +699,53 @@ static void start_cpus() } #endif +static void update_trampoline_code_refs(uint64_t dest_pa) +{ + void *ptr; + int i; + + if (dest_pa == 0) + return; + + /* Update temporary page tables */ + ptr = HPA2HVA(dest_pa + (uint64_t)CPU_Boot_Page_Tables_ptr); + *(uint32_t *)(ptr) += dest_pa; + + ptr = HPA2HVA(dest_pa + (uint64_t)CPU_Boot_Page_Tables_Start); + *(uint64_t *)(ptr) += dest_pa; + + ptr = HPA2HVA(dest_pa + (uint64_t)cpu_secondary_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)cpu_secondary_gdt_ptr); + *(uint64_t *)(ptr + 2) += dest_pa; + + /* update trampoline jump pointer with relocated offset */ + ptr = HPA2HVA(dest_pa + (uint64_t)ap_long_mode_jump_ref); + *(uint32_t *)ptr += dest_pa; +} + +static uint64_t relocate_trampoline_code(void) +{ + uint64_t size, dest_pa; + + size = (uint64_t)_ld_cpu_secondary_reset_end - (uint64_t)cpu_secondary_reset; +#ifndef CONFIG_EFI_STUB + dest_pa = e820_alloc_low_memory(CONFIG_LOW_RAM_SIZE); +#else + dest_pa = (uint64_t)get_ap_trampoline_buf(); +#endif + + /* printf("AP trampoline code: %llx size %x\n", dest_pa, size); */ + memcpy_s(HPA2HVA(dest_pa), size, _ld_cpu_secondary_reset_load, size); + update_trampoline_code_refs(dest_pa); + trampoline_code_paddr = dest_pa; + return dest_pa; +} + void cpu_dead(uint32_t logical_id) { /* For debug purposes, using a stack variable in the while loop enables diff --git a/hypervisor/bsp/uefi/efi/boot.c b/hypervisor/bsp/uefi/efi/boot.c index 7a6721103..6baf70ce7 100644 --- a/hypervisor/bsp/uefi/efi/boot.c +++ b/hypervisor/bsp/uefi/efi/boot.c @@ -189,12 +189,6 @@ again: mmap[j].mm_type = E820_RAM; j++; - /* reserve secondary memory region(0x1000 ~ 0x10000) for hv */ - err = __emalloc(CONFIG_LOW_RAM_SIZE, CONFIG_LOW_RAM_START, - &addr, EfiReservedMemoryType); - if (err != EFI_SUCCESS) - goto out; - mbi->mi_flags |= MULTIBOOT_INFO_HAS_MMAP | MULTIBOOT_INFO_HAS_CMDLINE; mbi->mi_mmap_length = j*sizeof(struct multiboot_mmap); @@ -228,6 +222,13 @@ switch_to_guest_mode(EFI_HANDLE image) efi_ctx = (struct efi_ctx *)(UINTN)addr; + /* reserve secondary memory region for hv */ + err = emalloc_for_low_mem(&addr, CONFIG_LOW_RAM_SIZE); + if (err != EFI_SUCCESS) + goto out; + + efi_ctx->ap_trampoline_buf = (void *)addr; + config_table = sys_table->ConfigurationTable; for (i = 0; i < sys_table->NumberOfTableEntries; i++) { diff --git a/hypervisor/bsp/uefi/efi/boot.h b/hypervisor/bsp/uefi/efi/boot.h index 2968a4c84..bc4382dba 100644 --- a/hypervisor/bsp/uefi/efi/boot.h +++ b/hypervisor/bsp/uefi/efi/boot.h @@ -96,6 +96,7 @@ struct e820_entry { struct efi_ctx { uint64_t rip; VOID *rsdp; + VOID *ap_trampoline_buf; dt_addr_t gdt; dt_addr_t idt; uint16_t tr_sel; diff --git a/hypervisor/bsp/uefi/uefi.c b/hypervisor/bsp/uefi/uefi.c index 88514f6bb..7d95a4cae 100644 --- a/hypervisor/bsp/uefi/uefi.c +++ b/hypervisor/bsp/uefi/uefi.c @@ -100,6 +100,11 @@ int sipi_from_efi_boot_service_exit(uint32_t dest, uint32_t mode, uint32_t vec) return 0; } +void *get_ap_trampoline_buf(void) +{ + return efi_ctx->ap_trampoline_buf; +} + void efi_deferred_wakeup_pcpu(int cpu_id) { uint32_t timeout; @@ -114,7 +119,7 @@ void efi_deferred_wakeup_pcpu(int cpu_id) expected_up = up_count + 1; send_startup_ipi(INTR_CPU_STARTUP_USE_DEST, - cpu_id, (uint64_t)cpu_secondary_reset); + cpu_id, (uint64_t)get_ap_trampoline_buf()); timeout = CPU_UP_TIMEOUT * 1000; diff --git a/hypervisor/include/arch/x86/cpu.h b/hypervisor/include/arch/x86/cpu.h index dc4a41e30..29975ff0e 100644 --- a/hypervisor/include/arch/x86/cpu.h +++ b/hypervisor/include/arch/x86/cpu.h @@ -157,11 +157,17 @@ int cpu_find_logical_id(uint32_t lapic_id); /**********************************/ extern const uint8_t _ld_cpu_secondary_reset_load[]; extern uint8_t _ld_cpu_secondary_reset_start[]; +extern uint8_t _ld_cpu_secondary_reset_end[]; extern const uint64_t _ld_cpu_secondary_reset_size; extern uint8_t _ld_bss_start[]; extern uint8_t _ld_bss_end[]; -extern uint8_t _ld_cpu_data_start[]; +extern uint8_t _ld_cpu_data_start[]; extern uint8_t _ld_cpu_data_end[]; +extern uint8_t CPU_Boot_Page_Tables_Start[]; +extern uint8_t CPU_Boot_Page_Tables_ptr[]; +extern uint8_t cpu_secondary_pdpt_addr[]; +extern uint8_t cpu_secondary_gdt_ptr[]; +extern uint8_t ap_long_mode_jump_ref[]; extern int ibrs_type; diff --git a/hypervisor/include/common/acrn_efi.h b/hypervisor/include/common/acrn_efi.h index 2a7cba451..966445530 100644 --- a/hypervisor/include/common/acrn_efi.h +++ b/hypervisor/include/common/acrn_efi.h @@ -39,6 +39,7 @@ typedef struct { struct efi_ctx { uint64_t rip; void *rsdp; + void *ap_trampoline_buf; dt_addr_t gdt; dt_addr_t idt; uint16_t tr_sel; @@ -74,5 +75,6 @@ struct efi_ctx { }__attribute__((packed)); void *get_rsdp_from_uefi(void); +void *get_ap_trampoline_buf(void); #endif /* UEFI_H*/