HV: add acpi module support for pre-launched VM

Previously we use a pre-defined structure as vACPI table for pre-launched
VM, the structure is initialized by HV code. Now change the method to use a
pre-loaded multiboot module instead. The module file will be generated by
acrn-config tool and loaded to GPA 0x7ff00000, a hardcoded RSDP table at
GPA 0x000f2400 will point to the XSDT table which at GPA 0x7ff00080;

Tracked-On: #5266

Signed-off-by: Victor Sun <victor.sun@intel.com>
Signed-off-by: Shuang Zheng <shuang.zheng@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Victor Sun 2020-09-02 15:42:20 +08:00 committed by Fuzhong Liu
parent 4290a79951
commit 34547e1e19
8 changed files with 67 additions and 3 deletions

View File

@ -205,3 +205,23 @@ void build_vacpi(struct acrn_vm *vm)
(void)copy_to_gpa(vm, &tpm2, ACPI_TPM2_ADDR, tpm2.header.length); (void)copy_to_gpa(vm, &tpm2, ACPI_TPM2_ADDR, tpm2.header.length);
} }
} }
/**
* @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,
};
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);
}

View File

@ -774,7 +774,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
if (err == 0) { if (err == 0) {
if (is_prelaunched_vm(vm)) { if (is_prelaunched_vm(vm)) {
build_vacpi(vm); build_vrsdp(vm);
} }
(void)vm_sw_loader(vm); (void)vm_sw_loader(vm);

View File

@ -19,6 +19,7 @@
#include <logmsg.h> #include <logmsg.h>
#include <deprivilege_boot.h> #include <deprivilege_boot.h>
#include <vboot_info.h> #include <vboot_info.h>
#include <vacpi.h>
#define DBG_LEVEL_BOOT 6U #define DBG_LEVEL_BOOT 6U
@ -37,6 +38,16 @@ static void init_vm_ramdisk_info(struct acrn_vm *vm, const struct multiboot_modu
} }
} }
/**
* @pre vm != NULL && mod != NULL
*/
static void init_vm_acpi_info(struct acrn_vm *vm, const struct multiboot_module *mod)
{
vm->sw.acpi_info.src_addr = hpa2hva((uint64_t)mod->mm_mod_start);
vm->sw.acpi_info.load_addr = (void *)VIRT_ACPI_DATA_ADDR;
vm->sw.acpi_info.size = ACPI_MODULE_SIZE;
}
/** /**
* @pre vm != NULL * @pre vm != NULL
*/ */
@ -222,6 +233,16 @@ static int32_t init_vm_sw_load(struct acrn_vm *vm, const struct acrn_multiboot_i
if (mod != NULL) { if (mod != NULL) {
init_vm_ramdisk_info(vm, mod); init_vm_ramdisk_info(vm, mod);
} }
if (is_prelaunched_vm(vm)) {
mod = get_mod_by_tag(mbi, vm_config->acpi_config.acpi_mod_tag);
if ((mod != NULL) && ((mod->mm_mod_end - mod->mm_mod_start) == ACPI_MODULE_SIZE)) {
init_vm_acpi_info(vm, mod);
} else {
pr_err("failed to load VM %d acpi module", vm->vm_id);
}
}
} else { } else {
pr_err("failed to load VM %d kernel module", vm->vm_id); pr_err("failed to load VM %d kernel module", vm->vm_id);
} }

View File

@ -16,8 +16,11 @@
#include <vm_configurations.h> #include <vm_configurations.h>
#define MAX_BOOTARGS_SIZE 2048U #define MAX_BOOTARGS_SIZE 2048U
/* The modules in multiboot are for kernel and ramdisk of pre-launched VMs and SOS VM */ /* The modules in multiboot are: Pre-launched VM: kernel/ramdisk/acpi; SOS VM: kernel/ramdisk */
#define MAX_MODULE_NUM (2U * PRE_VM_NUM + 2U * SOS_VM_NUM) #define MAX_MODULE_NUM (3U * PRE_VM_NUM + 2U * SOS_VM_NUM)
/* The vACPI module size is fixed to 1MB */
#define ACPI_MODULE_SIZE MEM_1M
/* extended flags for acrn multiboot info from multiboot2 */ /* extended flags for acrn multiboot info from multiboot2 */
#define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U #define MULTIBOOT_INFO_HAS_EFI_MMAP 0x00010000U

View File

@ -187,6 +187,7 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm)
struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info); struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info);
struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info); struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info);
struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info); struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info);
struct sw_module_info *acpi_info = &(vm->sw.acpi_info);
/* get primary vcpu */ /* get primary vcpu */
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BSP_CPU_ID); struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BSP_CPU_ID);
@ -216,6 +217,10 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm)
(uint64_t)bootargs_info->load_addr, (uint64_t)bootargs_info->load_addr,
(strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U)); (strnlen_s((char *)bootargs_info->src_addr, MAX_BOOTARGS_SIZE) + 1U));
} }
/* Copy Guest OS ACPI to its load location */
if (acpi_info->size == ACPI_MODULE_SIZE) {
(void)copy_to_gpa(vm, acpi_info->src_addr, (uint64_t)acpi_info->load_addr, ACPI_MODULE_SIZE);
}
switch (vm->sw.kernel_type) { switch (vm->sw.kernel_type) {
case KERNEL_BZIMAGE: case KERNEL_BZIMAGE:
prepare_loading_bzimage(vm, vcpu); prepare_loading_bzimage(vm, vcpu);

View File

@ -65,6 +65,7 @@ struct vm_sw_info {
struct sw_kernel_info kernel_info; struct sw_kernel_info kernel_info;
struct sw_module_info bootargs_info; struct sw_module_info bootargs_info;
struct sw_module_info ramdisk_info; struct sw_module_info ramdisk_info;
struct sw_module_info acpi_info;
/* HVA to IO shared page */ /* HVA to IO shared page */
void *io_shared_page; void *io_shared_page;
/* If enable IO completion polling mode */ /* If enable IO completion polling mode */

View File

@ -140,6 +140,10 @@ struct acrn_vm_os_config {
uint64_t kernel_ramdisk_addr; uint64_t kernel_ramdisk_addr;
} __aligned(8); } __aligned(8);
struct acrn_vm_acpi_config {
char acpi_mod_tag[MAX_MOD_TAG_LEN]; /* multiboot module tag for ACPI */
} __aligned(8);
/* the vbdf is assgined by device model */ /* the vbdf is assgined by device model */
#define UNASSIGNED_VBDF 0xFFFFU #define UNASSIGNED_VBDF 0xFFFFU
@ -180,6 +184,7 @@ struct acrn_vm_config {
uint16_t pci_dev_num; /* indicate how many PCI devices in VM */ uint16_t pci_dev_num; /* indicate how many PCI devices in VM */
struct acrn_vm_pci_dev_config *pci_devs; /* point to PCI devices BDF list */ struct acrn_vm_pci_dev_config *pci_devs; /* point to PCI devices BDF list */
struct acrn_vm_os_config os_config; /* OS information the VM */ struct acrn_vm_os_config os_config; /* OS information the VM */
struct acrn_vm_acpi_config acpi_config; /* ACPI config for the VM */
/* /*
* below are variable length members (per build). * below are variable length members (per build).

View File

@ -53,8 +53,16 @@
#define ACPI_ASL_COMPILER_ID "INTL" #define ACPI_ASL_COMPILER_ID "INTL"
#define ACPI_ASL_COMPILER_VERSION 0x20190802U #define ACPI_ASL_COMPILER_VERSION 0x20190802U
/* Use a pre-loaded multiboot module as pre-launched VM ACPI table.
* The module file size is fixed to 1MB and loaded to GPA 0x7ff00000.
* A hardcoded RSDP table at GPA 0x000f2400 will point to the XSDT
* table which at GPA 0x7ff00080;
* The module file should be generated by acrn-config tool;
*/
#define VIRT_ACPI_DATA_ADDR 0x7ff00000UL #define VIRT_ACPI_DATA_ADDR 0x7ff00000UL
#define VIRT_ACPI_NVS_ADDR 0x7fff0000UL #define VIRT_ACPI_NVS_ADDR 0x7fff0000UL
#define VIRT_RSDP_ADDR 0x000f2400UL
#define VIRT_XSDT_ADDR 0x7ff00080UL
/* virtual PCI MMCFG address base for pre/post-launched VM. */ /* virtual PCI MMCFG address base for pre/post-launched VM. */
#define VIRT_PCI_MMCFG_BASE 0xE0000000UL #define VIRT_PCI_MMCFG_BASE 0xE0000000UL
@ -77,5 +85,6 @@ struct acpi_table_info {
}; };
void build_vacpi(struct acrn_vm *vm); void build_vacpi(struct acrn_vm *vm);
void build_vrsdp(struct acrn_vm *vm);
#endif /* VACPI_H */ #endif /* VACPI_H */