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 <gen.zheng@intel.com>
Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong>
Acked-by: Xu, Anthony <anthony.xu@intel.com>
This commit is contained in:
Zide Chen 2018-05-02 23:39:57 -07:00 committed by Jack Ren
parent ceb3076b69
commit fe6397d9d8
6 changed files with 79 additions and 18 deletions

View File

@ -30,6 +30,7 @@
#include <hypervisor.h>
#include <hv_lib.h>
#include <acrn_hv_defs.h>
#include <acrn_common.h>
#include <bsp_extern.h>
#include <hv_arch.h>
@ -38,9 +39,12 @@
#include <hv_debug.h>
#ifdef CONFIG_EFI_STUB
#include <acrn_efi.h>
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

View File

@ -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++) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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*/