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 <victor.sun@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Victor Sun 2021-02-09 15:48:03 +08:00 committed by wenlingz
parent ae7eb25a7f
commit ce9d5e8779
14 changed files with 54 additions and 114 deletions

View File

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

View File

@ -5,14 +5,44 @@
*/
#include <vm.h>
#include <mmu.h>
#include <ept.h>
#include <vacpi.h>
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)
{
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);
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,
@ -23,6 +53,9 @@ void build_vrsdp(struct acrn_vm *vm)
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 */
/* 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);
}
}

View File

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

View File

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

View File

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

View File

@ -22,7 +22,6 @@
#ifndef ASSEMBLER
#include <efi.h>
#include <vm_configurations.h>
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);

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@
#include <ept.h>
#include <mmu.h>
#include <multiboot.h>
#include <vacpi.h>
#include <errno.h>
#include <sprintf.h>
#include <logmsg.h>
@ -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),

View File

@ -7,14 +7,13 @@
#ifndef ZEROPAGE_H
#define ZEROPAGE_H
#include <e820.h>
#include <efi.h>
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 */

View File

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

View File

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