diff --git a/hypervisor/Makefile b/hypervisor/Makefile index f38c74e66..9c6b21f0b 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -157,6 +157,7 @@ C_SRCS += arch/x86/mtrr.c C_SRCS += arch/x86/pm.c S_SRCS += arch/x86/wakeup.S C_SRCS += arch/x86/static_checks.c +C_SRCS += arch/x86/trampoline.c C_SRCS += arch/x86/guest/vcpu.c C_SRCS += arch/x86/guest/vm.c C_SRCS += arch/x86/guest/vlapic.c diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index ab672c4bb..c4b9c53d9 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include spinlock_t trampoline_spinlock = { .head = 0U, diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index 0957709a1..f90cdc0f4 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ #include -#include +#include struct cpu_context cpu_ctx; diff --git a/hypervisor/arch/x86/trampoline.c b/hypervisor/arch/x86/trampoline.c new file mode 100644 index 000000000..d440ac4ce --- /dev/null +++ b/hypervisor/arch/x86/trampoline.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +uint64_t trampoline_start16_paddr; + +/* + * Because trampoline code is relocated in different way, if HV code + * accesses trampoline using relative addressing, it needs to take + * out the HV relocation delta + * + * This function is valid if: + * - The hpa of HV code is always higher than trampoline code + * - The HV code is always relocated to higher address, compared + * with CONFIG_HV_RAM_START + */ +static uint64_t trampoline_relo_addr(const void *addr) +{ + return (uint64_t)addr - get_hv_image_delta(); +} + +uint64_t read_trampoline_sym(const void *sym) +{ + uint64_t *hva; + + hva = hpa2hva(trampoline_start16_paddr) + trampoline_relo_addr(sym); + return *hva; +} + +void write_trampoline_sym(const void *sym, uint64_t val) +{ + uint64_t *hva; + + hva = hpa2hva(trampoline_start16_paddr) + trampoline_relo_addr(sym); + *hva = val; + clflush(hva); +} + +static void update_trampoline_code_refs(uint64_t dest_pa) +{ + void *ptr; + uint64_t val; + int i; + + /* + * calculate the fixup CS:IP according to fixup target address + * dynamically. + * + * trampoline code starts in real mode, + * so the target addres is HPA + */ + val = dest_pa + trampoline_relo_addr(&trampoline_fixup_target); + + ptr = hpa2hva(dest_pa + trampoline_relo_addr(&trampoline_fixup_cs)); + *(uint16_t *)(ptr) = (uint16_t)((val >> 4U) & 0xFFFFU); + + 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 + trampoline_relo_addr(&cpu_boot_page_tables_ptr)); + *(uint32_t *)(ptr) += (uint32_t)dest_pa; + + ptr = hpa2hva(dest_pa + trampoline_relo_addr(&cpu_boot_page_tables_start)); + *(uint64_t *)(ptr) += dest_pa; + + 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 + trampoline_relo_addr(&trampoline_gdt_ptr)); + *(uint64_t *)(ptr + 2) += dest_pa; + + /* update trampoline jump pointer with relocated offset */ + 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(); +} + +uint64_t prepare_trampoline(void) +{ + uint64_t size, dest_pa, i; + + size = (uint64_t)(&ld_trampoline_end - &ld_trampoline_start); +#ifndef CONFIG_EFI_STUB + dest_pa = e820_alloc_low_memory(CONFIG_LOW_RAM_SIZE); +#else + dest_pa = (uint64_t)get_ap_trampoline_buf(); +#endif + + pr_dbg("trampoline code: %llx size %x", dest_pa, size); + + /* Copy segment for AP initialization code below 1MB */ + (void)memcpy_s(hpa2hva(dest_pa), (size_t)size, &ld_trampoline_load, + (size_t)size); + update_trampoline_code_refs(dest_pa); + + for (i = 0UL; i < size; i = i + CACHE_LINE_SIZE) { + clflush(hpa2hva(dest_pa + i)); + } + + trampoline_start16_paddr = dest_pa; + + return dest_pa; +} diff --git a/hypervisor/boot/include/reloc.h b/hypervisor/boot/include/reloc.h index e34fbebdd..b6a1e3128 100644 --- a/hypervisor/boot/include/reloc.h +++ b/hypervisor/boot/include/reloc.h @@ -9,30 +9,12 @@ extern void relocate(void); extern uint64_t get_hv_image_delta(void); extern uint64_t get_hv_image_base(void); -extern uint64_t read_trampoline_sym(const void *sym); -extern void write_trampoline_sym(const void *sym, uint64_t val); -extern uint64_t prepare_trampoline(void); /* external symbols that are helpful for relocation */ extern uint8_t _DYNAMIC[1]; -extern const uint8_t ld_trampoline_load; -extern uint8_t ld_trampoline_start; extern uint8_t ld_trampoline_end; -extern const uint64_t ld_trampoline_size; extern uint8_t cpu_primary_start_32; extern uint8_t cpu_primary_start_64; -extern uint8_t trampoline_fixup_cs; -extern uint8_t trampoline_fixup_ip; -extern uint8_t trampoline_fixup_target; -extern uint8_t cpu_boot_page_tables_start; -extern uint8_t cpu_boot_page_tables_ptr; -extern uint8_t trampoline_pdpt_addr; -extern uint8_t trampoline_gdt_ptr; -extern uint8_t trampoline_start64_fixup; -extern uint8_t trampoline_spinlock_ptr; - -extern uint64_t trampoline_start16_paddr; - #endif /* RELOCATE_H */ diff --git a/hypervisor/boot/reloc.c b/hypervisor/boot/reloc.c index 3fda34dc9..ff6fcb90a 100644 --- a/hypervisor/boot/reloc.c +++ b/hypervisor/boot/reloc.c @@ -4,9 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include +#include #include -#include #ifdef CONFIG_RELOC #define DT_NULL 0 /* end of .dynamic section */ @@ -33,8 +32,6 @@ static inline uint64_t elf64_r_type(uint64_t i) #define R_X86_64_RELATIVE 8UL -uint64_t trampoline_start16_paddr; - /* get the delta between CONFIG_HV_RAM_START and the actual load address */ uint64_t get_hv_image_delta(void) { @@ -57,21 +54,6 @@ uint64_t get_hv_image_base(void) return (get_hv_image_delta() + CONFIG_HV_RAM_START); } -/* - * Because trampoline code is relocated in different way, if HV code - * accesses trampoline using relative addressing, it needs to take - * out the HV relocation delta - * - * This function is valid if: - * - The hpa of HV code is always higher than trampoline code - * - The HV code is always relocated to higher address, compared - * with CONFIG_HV_RAM_START - */ -static uint64_t trampoline_relo_addr(const void *addr) -{ - return (uint64_t)addr - get_hv_image_delta(); -} - void relocate(void) { #ifdef CONFIG_RELOC @@ -144,97 +126,3 @@ void relocate(void) } #endif } - -uint64_t read_trampoline_sym(const void *sym) -{ - uint64_t *hva; - - hva = hpa2hva(trampoline_start16_paddr) + trampoline_relo_addr(sym); - return *hva; -} - -void write_trampoline_sym(const void *sym, uint64_t val) -{ - uint64_t *hva; - - hva = hpa2hva(trampoline_start16_paddr) + trampoline_relo_addr(sym); - *hva = val; - clflush(hva); -} - -static void update_trampoline_code_refs(uint64_t dest_pa) -{ - void *ptr; - uint64_t val; - int i; - - /* - * calculate the fixup CS:IP according to fixup target address - * dynamically. - * - * trampoline code starts in real mode, - * so the target addres is HPA - */ - val = dest_pa + trampoline_relo_addr(&trampoline_fixup_target); - - ptr = hpa2hva(dest_pa + trampoline_relo_addr(&trampoline_fixup_cs)); - *(uint16_t *)(ptr) = (uint16_t)((val >> 4U) & 0xFFFFU); - - 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 + trampoline_relo_addr(&cpu_boot_page_tables_ptr)); - *(uint32_t *)(ptr) += (uint32_t)dest_pa; - - ptr = hpa2hva(dest_pa + trampoline_relo_addr(&cpu_boot_page_tables_start)); - *(uint64_t *)(ptr) += dest_pa; - - 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 + trampoline_relo_addr(&trampoline_gdt_ptr)); - *(uint64_t *)(ptr + 2) += dest_pa; - - /* update trampoline jump pointer with relocated offset */ - 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(); -} - -uint64_t prepare_trampoline(void) -{ - uint64_t size, dest_pa, i; - - size = (uint64_t)(&ld_trampoline_end - &ld_trampoline_start); -#ifndef CONFIG_EFI_STUB - dest_pa = e820_alloc_low_memory(CONFIG_LOW_RAM_SIZE); -#else - dest_pa = (uint64_t)get_ap_trampoline_buf(); -#endif - - pr_dbg("trampoline code: %llx size %x", dest_pa, size); - - /* Copy segment for AP initialization code below 1MB */ - (void)memcpy_s(hpa2hva(dest_pa), (size_t)size, &ld_trampoline_load, - (size_t)size); - update_trampoline_code_refs(dest_pa); - - for (i = 0UL; i < size; i = i + CACHE_LINE_SIZE) { - clflush(hpa2hva(dest_pa + i)); - } - - trampoline_start16_paddr = dest_pa; - - return dest_pa; -} diff --git a/hypervisor/include/arch/x86/trampoline.h b/hypervisor/include/arch/x86/trampoline.h new file mode 100644 index 000000000..a28f427a7 --- /dev/null +++ b/hypervisor/include/arch/x86/trampoline.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) <2018> Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRAMPOLINE_H +#define TRAMPOLINE_H + +extern uint64_t read_trampoline_sym(const void *sym); +extern void write_trampoline_sym(const void *sym, uint64_t val); +extern uint64_t prepare_trampoline(void); + +/* external symbols that are helpful for relocation */ +extern const uint8_t ld_trampoline_load; +extern uint8_t ld_trampoline_start; + +extern uint8_t trampoline_fixup_cs; +extern uint8_t trampoline_fixup_ip; +extern uint8_t trampoline_fixup_target; +extern uint8_t cpu_boot_page_tables_start; +extern uint8_t cpu_boot_page_tables_ptr; +extern uint8_t trampoline_pdpt_addr; +extern uint8_t trampoline_gdt_ptr; +extern uint8_t trampoline_start64_fixup; +extern uint8_t trampoline_spinlock_ptr; + +extern uint64_t trampoline_start16_paddr; + +#endif /* TRAMPOLINE_H */