diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 286d72a72..ccf78b3a3 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -247,6 +247,7 @@ VP_BASE_C_SRCS += common/hv_main.c VP_BASE_C_SRCS += common/vm_load.c VP_BASE_C_SRCS += arch/x86/configs/vmptable.c VP_BASE_C_SRCS += arch/x86/configs/pci_dev.c +VP_BASE_C_SRCS += arch/x86/configs/vacpi.c VP_BASE_C_SRCS += arch/x86/configs/$(CONFIG_BOARD)/ve820.c # virtual platform device model diff --git a/hypervisor/arch/x86/configs/vacpi.c b/hypervisor/arch/x86/configs/vacpi.c new file mode 100644 index 000000000..ece3969c3 --- /dev/null +++ b/hypervisor/arch/x86/configs/vacpi.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* ACPI tables for pre-launched VM and SOS */ +static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = { + [0U ... (CONFIG_MAX_VM_NUM - 1U)] = { + .rsdp = { + .signature = ACPI_SIG_RSDP, + .oem_id = ACPI_OEM_ID, + .revision = 0x2U, + .length = ACPI_RSDP_XCHECKSUM_LENGTH, + .xsdt_physical_address = ACPI_XSDT_ADDR, + }, + .xsdt = { + /* Currently XSDT table only pointers to 1 ACPI table entry (MADT) */ + .header.length = sizeof(struct acpi_table_header) + sizeof(uint64_t), + + .header.revision = 0x1U, + .header.oem_revision = 0x1U, + .header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION, + .header.signature = ACPI_SIG_XSDT, + .header.oem_id = ACPI_OEM_ID, + .header.oem_table_id = "ACRNXSDT", + .header.asl_compiler_id = ACPI_ASL_COMPILER_ID, + + .table_offset_entry[0] = ACPI_MADT_ADDR, + }, + .madt = { + .header.revision = 0x3U, + .header.oem_revision = 0x1U, + .header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION, + .header.signature = ACPI_SIG_MADT, + .header.oem_id = ACPI_OEM_ID, + .header.oem_table_id = "ACRNMADT", + .header.asl_compiler_id = ACPI_ASL_COMPILER_ID, + + .address = 0xFEE00000U, /* Local APIC Address */ + .flags = 0x1U, /* PC-AT Compatibility=1 */ + }, + .lapic_nmi = { + .header.type = ACPI_MADT_TYPE_LOCAL_APIC_NMI, + .header.length = sizeof(struct acpi_madt_local_apic_nmi), + .processor_id = 0xFFU, + .flags = 0x5U, + .lint = 0x1U, + }, + .lapic_array = { + [0U ... (CONFIG_MAX_PCPU_NUM - 1U)] = { + .header.type = ACPI_MADT_TYPE_LOCAL_APIC, + .header.length = sizeof(struct acpi_madt_local_apic), + .lapic_flags = 0x1U, /* Processor Enabled=1, Runtime Online Capable=0 */ + } + }, + } +}; + +/** + * @pre vm != NULL + * @pre vm->vm_id < CONFIG_MAX_VM_NUM + */ +void build_vacpi(struct acrn_vm *vm) +{ + struct acpi_table_rsdp *rsdp; + struct acpi_table_xsdt *xsdt; + struct acpi_table_madt *madt; + struct acpi_madt_local_apic *lapic; + uint16_t i; + + rsdp = &acpi_table_template[vm->vm_id].rsdp; + 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 */ + (void)copy_to_gpa(vm, rsdp, ACPI_RSDP_ADDR, ACPI_RSDP_XCHECKSUM_LENGTH); + + xsdt = &acpi_table_template[vm->vm_id].xsdt; + xsdt->header.checksum = calculate_checksum8(xsdt, xsdt->header.length); + /* Copy XSDT table to guest physical memory */ + (void)copy_to_gpa(vm, xsdt, ACPI_XSDT_ADDR, xsdt->header.length); + + /* Fix up MADT LAPIC subtables */ + for (i = 0U; i < vm->hw.created_vcpus; i++) { + lapic = &acpi_table_template[vm->vm_id].lapic_array[i]; + lapic->processor_id = (uint8_t)i; + lapic->id = (uint8_t)i; + } + + madt = &acpi_table_template[vm->vm_id].madt; + madt->header.length = sizeof(struct acpi_table_madt) + + sizeof(struct acpi_madt_local_apic_nmi) + + (sizeof(struct acpi_madt_local_apic) * (size_t)vm->hw.created_vcpus); + madt->header.checksum = calculate_checksum8(madt, madt->header.length); + + /* Copy MADT table and its subtables to guest physical memory */ + (void)copy_to_gpa(vm, madt, ACPI_MADT_ADDR, madt->header.length); +} diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index ca857667a..9469ade99 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -743,6 +743,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config) if (err == 0) { if (is_prelaunched_vm(vm)) { (void)mptable_build(vm); + build_vacpi(vm); } (void )vm_sw_loader(vm); diff --git a/hypervisor/boot/include/acpi.h b/hypervisor/boot/include/acpi.h index f4e67d090..92d793df8 100644 --- a/hypervisor/boot/include/acpi.h +++ b/hypervisor/boot/include/acpi.h @@ -11,6 +11,7 @@ #define ACPI_RSDP_CHECKSUM_LENGTH 20U +#define ACPI_RSDP_XCHECKSUM_LENGTH 36U #define ACPI_NAME_SIZE 4U #define ACPI_OEM_ID_SIZE 6U @@ -19,6 +20,7 @@ #define ACPI_MADT_TYPE_LOCAL_APIC 0U #define ACPI_MADT_TYPE_IOAPIC 1U #define ACPI_MADT_ENABLED 1U +#define ACPI_MADT_TYPE_LOCAL_APIC_NMI 4U /* FACP field offsets */ #define OFFSET_FACS_ADDR 36U @@ -37,6 +39,7 @@ #define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */ #define ACPI_SIG_FACS 0x53434146U /* "FACS" */ #define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Ptr */ +#define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */ #define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ #define ACPI_SIG_DMAR "DMAR" @@ -127,13 +130,20 @@ struct acpi_madt_local_apic { uint32_t lapic_flags; } __packed; +struct acpi_madt_local_apic_nmi { + struct acpi_subtable_header header; + uint8_t processor_id; + uint16_t flags; + uint8_t lint; +} __packed; + struct acpi_madt_ioapic { struct acpi_subtable_header header; /* IOAPIC id */ - uint8_t id; - uint8_t rsvd; - uint32_t addr; - uint32_t gsi_base; + uint8_t id; + uint8_t rsvd; + uint32_t addr; + uint32_t gsi_base; } __packed; enum acpi_dmar_type { diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 5ffa97bde..c4d21e29f 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/hypervisor/include/dm/vacpi.h b/hypervisor/include/dm/vacpi.h new file mode 100644 index 000000000..83247ff31 --- /dev/null +++ b/hypervisor/include/dm/vacpi.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************ + * + * FILE NAME + * + * vacpi.h + * + * DESCRIPTION + * + * This file defines API and extern variable for virtual ACPI + * + ************************************************************************/ +/**********************************/ +/* EXTERNAL VARIABLES */ +/**********************************/ +#ifndef VACPI_H +#define VACPI_H + +#include + +/* + * + * Create the minimal set of ACPI tables required to boot pre-launched VM + * + * The tables are placed in the guest's ROM area just below 1MB physical, + * above the MPTable. + * + * Layout + * ------ + * RSDP -> 0xf2400 (36 bytes fixed) + * XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used) + * MADT -> 0xf2500 (depends on #CPUs) + */ +#define ACPI_BASE 0xf2400U + +#define ACPI_RSDP_ADDR (ACPI_BASE + 0x0U) +#define ACPI_XSDT_ADDR (ACPI_BASE + 0x080U) +#define ACPI_MADT_ADDR (ACPI_BASE + 0x100U) + +#define ACPI_OEM_ID "ACRN " +#define ACPI_ASL_COMPILER_ID "INTL" +#define ACPI_ASL_COMPILER_VERSION 0x20190802U + + +struct acpi_table_info { + struct acpi_table_rsdp rsdp; + struct acpi_table_xsdt xsdt; + + struct { + struct acpi_table_madt madt; + struct acpi_madt_local_apic_nmi lapic_nmi; + struct acpi_madt_local_apic lapic_array[CONFIG_MAX_PCPU_NUM]; + } __packed; +}; + +void build_vacpi(struct acrn_vm *vm); + +#endif /* VACPI_H */ diff --git a/hypervisor/include/lib/util.h b/hypervisor/include/lib/util.h index 13394692b..5f4a96e5f 100644 --- a/hypervisor/include/lib/util.h +++ b/hypervisor/include/lib/util.h @@ -46,4 +46,12 @@ static inline uint8_t calculate_sum8(const void *buf, uint32_t length) return sum; } +/** + * @pre buf != NULL + */ +static inline uint8_t calculate_checksum8(const void *buf, uint32_t len) +{ + return (uint8_t)(0x100U - calculate_sum8(buf, len)); +} + #endif /* UTIL_H */