From ce9d5e87791cfd135de8cd997274e2e03c75f5a1 Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Tue, 9 Feb 2021 15:48:03 +0800 Subject: [PATCH] HV: remove efi support for SOS Provide EFI support for SOS could cause weird issues. For example, hypervisor works based on E820 table whereras it's possible that the memory map from EFI table is not aligned with E820 table. The SOS kernel kaslr will try to find the random address for extracted kernel image in EFI table first. So it's possible that none-RAM in E820 is picked for extracted kernel image. This will make kernel boot fail. This patch removes EFI support for SOS by not passing struct boot_efi_info to SOS kernel zeropage, and reserve a memory to store RSDP table for SOS and pass the RSDP address to SOS kernel zeropage for SOS to locate ACPI table. The patch requires SOS kernel version be high than 4.20, otherwise the kernel might fail to find the RSDP. Tracked-On: #5626 Signed-off-by: Victor Sun Reviewed-by: Jason Chen CJ --- hypervisor/arch/x86/boot/cpu_primary.S | 2 - hypervisor/arch/x86/configs/vacpi.c | 55 +++++++++++++++++----- hypervisor/arch/x86/guest/vm.c | 6 +-- hypervisor/boot/acpi_base.c | 2 +- hypervisor/boot/include/acpi.h | 1 + hypervisor/boot/include/multiboot.h | 2 - hypervisor/boot/include/multiboot_std.h | 13 ----- hypervisor/boot/multiboot/multiboot.c | 14 ------ hypervisor/boot/multiboot/multiboot2.c | 31 ------------ hypervisor/boot/multiboot/multiboot_priv.h | 4 -- hypervisor/common/vm_load.c | 9 +--- hypervisor/include/arch/x86/zeropage.h | 7 ++- hypervisor/include/dm/vacpi.h | 1 + hypervisor/include/lib/efi.h | 21 --------- 14 files changed, 54 insertions(+), 114 deletions(-) delete mode 100644 hypervisor/include/lib/efi.h diff --git a/hypervisor/arch/x86/boot/cpu_primary.S b/hypervisor/arch/x86/boot/cpu_primary.S index 11d08155c..bcc7117c6 100644 --- a/hypervisor/arch/x86/boot/cpu_primary.S +++ b/hypervisor/arch/x86/boot/cpu_primary.S @@ -65,8 +65,6 @@ info_req_tag_start: .long MULTIBOOT2_TAG_TYPE_MMAP /* memory map */ .long MULTIBOOT2_TAG_TYPE_MODULE /* boot modules infomation */ .long MULTIBOOT2_TAG_TYPE_ACPI_NEW /* a copy of RSDP as defined per ACPI 2.0 or later specification */ - .long MULTIBOOT2_TAG_TYPE_EFI64 /* EFI system table, to be passed to guest Linux */ - .long MULTIBOOT2_TAG_TYPE_EFI_MMAP /* EFI memory map, to be passed to guest Linux */ info_req_tag_end: #ifdef CONFIG_RELOC diff --git a/hypervisor/arch/x86/configs/vacpi.c b/hypervisor/arch/x86/configs/vacpi.c index 9cda53b01..3b2c31f08 100644 --- a/hypervisor/arch/x86/configs/vacpi.c +++ b/hypervisor/arch/x86/configs/vacpi.c @@ -5,24 +5,57 @@ */ #include +#include +#include #include +static uint64_t sos_rsdp_gpa; + +uint64_t get_vrsdp_gpa(struct acrn_vm *vm) +{ + uint64_t gpa = 0UL; + + if (is_sos_vm(vm)) { + gpa = sos_rsdp_gpa; + } else if (is_prelaunched_vm(vm)) { + gpa = VIRT_RSDP_ADDR; + } + return gpa; +} + /** * @pre vm != NULL * @pre vm->vm_id < CONFIG_MAX_VM_NUM */ void build_vrsdp(struct acrn_vm *vm) { - struct acpi_table_rsdp rsdp = { - .signature = ACPI_SIG_RSDP, - .oem_id = ACPI_OEM_ID, - .revision = 0x2U, - .length = ACPI_RSDP_XCHECKSUM_LENGTH, - .xsdt_physical_address = VIRT_XSDT_ADDR, - }; + if (is_sos_vm(vm)) { + /* Reserve a memory area from host e820 space to store SOS VM ACPI RSDP info. + * This should be done before create_sos_vm_e820() because the SOS e820 + * need to be updated from host e820 table accordingly. + */ + uint64_t sos_rsdp_hpa = e820_alloc_memory(MEM_1K, MEM_2G * 2); - rsdp.checksum = calculate_checksum8(&rsdp, ACPI_RSDP_CHECKSUM_LENGTH); - rsdp.extended_checksum = calculate_checksum8(&rsdp, ACPI_RSDP_XCHECKSUM_LENGTH); - /* Copy RSDP table to guest physical memory F segment */ - (void)copy_to_gpa(vm, &rsdp, VIRT_RSDP_ADDR, ACPI_RSDP_XCHECKSUM_LENGTH); + stac(); + (void)memcpy_s(hpa2hva(sos_rsdp_hpa), sizeof(struct acpi_table_rsdp), + get_rsdp(), sizeof(struct acpi_table_rsdp)); + clac(); + sos_rsdp_gpa = sos_vm_hpa2gpa(sos_rsdp_hpa); + + } else if (is_prelaunched_vm(vm)) { + struct acpi_table_rsdp rsdp = { + .signature = ACPI_SIG_RSDP, + .oem_id = ACPI_OEM_ID, + .revision = 0x2U, + .length = ACPI_RSDP_XCHECKSUM_LENGTH, + .xsdt_physical_address = VIRT_XSDT_ADDR, + }; + + rsdp.checksum = calculate_checksum8(&rsdp, ACPI_RSDP_CHECKSUM_LENGTH); + rsdp.extended_checksum = calculate_checksum8(&rsdp, ACPI_RSDP_XCHECKSUM_LENGTH); + /* Copy RSDP table to guest physical memory F segment + * This should be done after prepare_prelaunched_vm_memmap() + */ + (void)copy_to_gpa(vm, &rsdp, VIRT_RSDP_ADDR, ACPI_RSDP_XCHECKSUM_LENGTH); + } } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index a7299b229..07684aae5 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -502,6 +502,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v if (is_sos_vm(vm)) { /* Only for SOS_VM */ + build_vrsdp(vm); create_sos_vm_e820(vm); prepare_sos_vm_memmap(vm); @@ -526,6 +527,7 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v if (vm_config->load_order == PRE_LAUNCHED_VM) { create_prelaunched_vm_e820(vm); prepare_prelaunched_vm_memmap(vm, vm_config); + build_vrsdp(vm); status = init_vm_boot_info(vm); } } @@ -866,10 +868,6 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config) err = create_vm(vm_id, vm_config->cpu_affinity, vm_config, &vm); if (err == 0) { - if (is_prelaunched_vm(vm)) { - build_vrsdp(vm); - } - (void)vm_sw_loader(vm); /* start vm BSP automatically */ diff --git a/hypervisor/boot/acpi_base.c b/hypervisor/boot/acpi_base.c index 45d2ab903..26a994106 100644 --- a/hypervisor/boot/acpi_base.c +++ b/hypervisor/boot/acpi_base.c @@ -62,7 +62,7 @@ static struct acpi_table_rsdp *found_rsdp(char *base, uint64_t length) /* RSDP parsed from BIOS region should exist. * If it is NULL, the hypervisor can't be booted */ -static struct acpi_table_rsdp *get_rsdp(void) +struct acpi_table_rsdp *get_rsdp(void) { return acpi_rsdp; } diff --git a/hypervisor/boot/include/acpi.h b/hypervisor/boot/include/acpi.h index 550563151..50bdd9d9a 100644 --- a/hypervisor/boot/include/acpi.h +++ b/hypervisor/boot/include/acpi.h @@ -237,6 +237,7 @@ struct acpi_table_tpm2 { } __packed; void init_acpi(void); +struct acpi_table_rsdp *get_rsdp(void); void *get_acpi_tbl(const char *signature); struct ioapic_info; diff --git a/hypervisor/boot/include/multiboot.h b/hypervisor/boot/include/multiboot.h index a0bb78b26..e2af3aae7 100644 --- a/hypervisor/boot/include/multiboot.h +++ b/hypervisor/boot/include/multiboot.h @@ -22,7 +22,6 @@ #ifndef ASSEMBLER -#include #include struct acrn_multiboot_info { @@ -43,7 +42,6 @@ struct acrn_multiboot_info { struct multiboot_mmap mi_mmap_entry[MAX_MMAP_ENTRIES]; const void *mi_acpi_rsdp_va; - struct efi_info mi_efi_info; }; void init_acrn_multiboot_info(uint32_t magic, uint32_t info); diff --git a/hypervisor/boot/include/multiboot_std.h b/hypervisor/boot/include/multiboot_std.h index 76cfb09d9..d8a284e59 100644 --- a/hypervisor/boot/include/multiboot_std.h +++ b/hypervisor/boot/include/multiboot_std.h @@ -209,19 +209,6 @@ struct multiboot2_tag_new_acpi { uint8_t rsdp[0]; }; -struct multiboot2_tag_efi64 { - uint32_t type; - uint32_t size; - uint64_t pointer; -}; - -struct multiboot2_tag_efi_mmap { - uint32_t type; - uint32_t size; - uint32_t descr_size; - uint32_t descr_vers; - uint8_t efi_mmap[0]; -}; #endif #endif /* CONFIG_MULTIBOOT2 */ diff --git a/hypervisor/boot/multiboot/multiboot.c b/hypervisor/boot/multiboot/multiboot.c index 45cbcede4..9a0691c92 100644 --- a/hypervisor/boot/multiboot/multiboot.c +++ b/hypervisor/boot/multiboot/multiboot.c @@ -93,20 +93,6 @@ int32_t sanitize_acrn_multiboot_info(uint32_t magic, uint32_t info) mbi_status = -EINVAL; } -#ifdef CONFIG_MULTIBOOT2 - if (boot_from_multiboot2(magic)) { - if (acrn_mbi.mi_efi_info.efi_memmap_hi != 0U) { - pr_err("the EFI mmap address should be less than 4G!"); - acrn_mbi.mi_flags &= ~MULTIBOOT_INFO_HAS_EFI_MMAP; - mbi_status = -EINVAL; - } - - if ((acrn_mbi.mi_flags & (MULTIBOOT_INFO_HAS_EFI64 | MULTIBOOT_INFO_HAS_EFI_MMAP)) == 0U) { - pr_err("no multiboot2 uefi info found!"); - } - } -#endif - if (acrn_mbi.mi_loader_name[0] == '\0') { pr_err("no bootloader name found!"); mbi_status = -EINVAL; diff --git a/hypervisor/boot/multiboot/multiboot2.c b/hypervisor/boot/multiboot/multiboot2.c index e3611ac90..375b2196b 100644 --- a/hypervisor/boot/multiboot/multiboot2.c +++ b/hypervisor/boot/multiboot/multiboot2.c @@ -33,31 +33,6 @@ static void mb2_mods_to_mbi(struct acrn_multiboot_info *mbi, } } -/** - * @pre mbi != NULL && mb2_tag_efi64 != 0 - */ -static void mb2_efi64_to_mbi(struct acrn_multiboot_info *mbi, const struct multiboot2_tag_efi64 *mb2_tag_efi64) -{ - const uint32_t efiloader_sig = 0x34364c45; /* "EL64" */ - mbi->mi_efi_info.efi_systab = (uint32_t)(uint64_t)mb2_tag_efi64->pointer; - mbi->mi_efi_info.efi_loader_signature = efiloader_sig; - mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI64; -} - -/** - * @pre mbi != NULL && mb2_tag_efimmap != 0 - */ -static void mb2_efimmap_to_mbi(struct acrn_multiboot_info *mbi, - const struct multiboot2_tag_efi_mmap *mb2_tag_efimmap) -{ - mbi->mi_efi_info.efi_memdesc_size = mb2_tag_efimmap->descr_size; - mbi->mi_efi_info.efi_memdesc_version = mb2_tag_efimmap->descr_vers; - mbi->mi_efi_info.efi_memmap = (uint32_t)(uint64_t)mb2_tag_efimmap->efi_mmap; - mbi->mi_efi_info.efi_memmap_size = mb2_tag_efimmap->size - 16U; - mbi->mi_efi_info.efi_memmap_hi = (uint32_t)(((uint64_t)mb2_tag_efimmap->efi_mmap) >> 32U); - mbi->mi_flags |= MULTIBOOT_INFO_HAS_EFI_MMAP; -} - /** * @pre mbi != NULL */ @@ -91,12 +66,6 @@ int32_t multiboot2_to_acrn_mbi(struct acrn_multiboot_info *mbi, void *mb2_info) case MULTIBOOT2_TAG_TYPE_ACPI_NEW: mbi->mi_acpi_rsdp_va = ((struct multiboot2_tag_new_acpi *)mb2_tag)->rsdp; break; - case MULTIBOOT2_TAG_TYPE_EFI64: - mb2_efi64_to_mbi(mbi, (const struct multiboot2_tag_efi64 *)mb2_tag); - break; - case MULTIBOOT2_TAG_TYPE_EFI_MMAP: - mb2_efimmap_to_mbi(mbi, (const struct multiboot2_tag_efi_mmap *)mb2_tag); - break; default: if (mb2_tag->type > MULTIBOOT2_TAG_TYPE_LOAD_BASE_ADDR) { ret = -EINVAL; diff --git a/hypervisor/boot/multiboot/multiboot_priv.h b/hypervisor/boot/multiboot/multiboot_priv.h index 8d114816c..404de6ab7 100644 --- a/hypervisor/boot/multiboot/multiboot_priv.h +++ b/hypervisor/boot/multiboot/multiboot_priv.h @@ -7,10 +7,6 @@ #ifndef MULTIBOOT_PRIV_H #define MULTIBOOT_PRIV_H -/* extended flags for acrn multiboot info from multiboot2 */ -#define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U -#define MULTIBOOT_INFO_HAS_EFI64 0x00020000U - #ifdef CONFIG_MULTIBOOT2 /* * @post boot_regs[1] stores the address pointer that point to a valid multiboot2 info diff --git a/hypervisor/common/vm_load.c b/hypervisor/common/vm_load.c index 5e14dbedb..300c10052 100644 --- a/hypervisor/common/vm_load.c +++ b/hypervisor/common/vm_load.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,14 +75,8 @@ static uint64_t create_zero_page(struct acrn_vm *vm) /* clear the zeropage */ (void)memset(zeropage, 0U, MEM_2K); -#ifdef CONFIG_MULTIBOOT2 - if (is_sos_vm(vm)) { - struct acrn_multiboot_info *mbi = get_acrn_multiboot_info(); + zeropage->acpi_rsdp_addr = get_vrsdp_gpa(vm); - (void)memcpy_s(&(zeropage->boot_efi_info), sizeof(zeropage->boot_efi_info), - &(mbi->mi_efi_info), sizeof(mbi->mi_efi_info)); - } -#endif /* copy part of the header into the zero page */ hva = (struct zero_page *)gpa2hva(vm, (uint64_t)sw_kernel->kernel_load_addr); (void)memcpy_s(&(zeropage->hdr), sizeof(zeropage->hdr), diff --git a/hypervisor/include/arch/x86/zeropage.h b/hypervisor/include/arch/x86/zeropage.h index 746ce29ef..5efe8cf07 100644 --- a/hypervisor/include/arch/x86/zeropage.h +++ b/hypervisor/include/arch/x86/zeropage.h @@ -7,14 +7,13 @@ #ifndef ZEROPAGE_H #define ZEROPAGE_H #include -#include struct zero_page { - uint8_t pad0[0x1c0]; /* 0x000 */ + uint8_t pad0[0x70]; /* 0x000 */ - struct efi_info boot_efi_info; + uint64_t acpi_rsdp_addr; /* 0x070 */ - uint8_t pad1[0x8]; /* 0x1e0 */ + uint8_t pad1[0x170]; /* 0x78 */ uint8_t e820_nentries; /* 0x1e8 */ uint8_t pad2[0x8]; /* 0x1e9 */ diff --git a/hypervisor/include/dm/vacpi.h b/hypervisor/include/dm/vacpi.h index a5d57af8c..ebeaa3dcb 100644 --- a/hypervisor/include/dm/vacpi.h +++ b/hypervisor/include/dm/vacpi.h @@ -27,6 +27,7 @@ #define UOS_VIRT_PCI_MMCFG_START_BUS 0x0U #define UOS_VIRT_PCI_MMCFG_END_BUS 0xFFU +uint64_t get_vrsdp_gpa(struct acrn_vm *vm); void build_vrsdp(struct acrn_vm *vm); #endif /* VACPI_H */ diff --git a/hypervisor/include/lib/efi.h b/hypervisor/include/lib/efi.h deleted file mode 100644 index ab35da076..000000000 --- a/hypervisor/include/lib/efi.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2020 Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef EFI_H -#define EFI_H - -struct efi_info { - uint32_t efi_loader_signature; /* 0x1c0 */ - uint32_t efi_systab; /* 0x1c4 */ - uint32_t efi_memdesc_size; /* 0x1c8 */ - uint32_t efi_memdesc_version; /* 0x1cc */ - uint32_t efi_memmap; /* 0x1d0 */ - uint32_t efi_memmap_size; /* 0x1d4 */ - uint32_t efi_systab_hi; /* 0x1d8 */ - uint32_t efi_memmap_hi; /* 0x1dc */ -} __packed; - -#endif