mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-30 06:54:48 +00:00
hv: add ACPI support for pre-launched VMs
Statically define the per vm RSDP/XSDT/MADT ACPI template tables in vacpi.c, RSDP/XSDT tables are copied to guest physical memory after checksum is calculated. For MADT table, first fix up process id/lapic id in its lapic subtable, then the MADT table's checksum is calculated before it is copies to guest physical memory. Add 8-bit checksum function in util.h Tracked-On: #3601 Signed-off-by: dongshen <dongsheng.x.zhang@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
96b422ce9d
commit
b447ce3d86
@ -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
|
||||
|
103
hypervisor/arch/x86/configs/vacpi.c
Normal file
103
hypervisor/arch/x86/configs/vacpi.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <vm.h>
|
||||
#include <per_cpu.h>
|
||||
#include <vacpi.h>
|
||||
#include <pgtable.h>
|
||||
|
||||
/* 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);
|
||||
}
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <multiboot.h>
|
||||
#include <acrn_common.h>
|
||||
#include <mptable.h>
|
||||
#include <vacpi.h>
|
||||
#include <vm_configurations.h>
|
||||
#include <sgx.h>
|
||||
|
||||
|
63
hypervisor/include/dm/vacpi.h
Normal file
63
hypervisor/include/dm/vacpi.h
Normal file
@ -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 <acpi.h>
|
||||
|
||||
/*
|
||||
*
|
||||
* 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 */
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user