hv: vacpi: add fadt table support

Add FADT table support to support guest S5 setting.

According to ACPI 6.3 Spec, OSPM must ignored the DSDT and FACS fields if them're zero.
However, Linux kernel seems not to abide by the protocol, it will check DSDT still.
So add an empty DSDT to meet it.

Tracked-On: #4623
Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
Li Fei1
2020-04-21 11:52:41 +08:00
committed by wenlingz
parent 9f036cff6a
commit 4eb3f5a0c7
3 changed files with 79 additions and 7 deletions

View File

@@ -8,6 +8,7 @@
#include <per_cpu.h>
#include <vacpi.h>
#include <pgtable.h>
#include <platform_acpi_info.h>
/* ACPI tables for pre-launched VM and SOS */
static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = {
@@ -20,9 +21,6 @@ static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = {
.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,
@@ -33,6 +31,35 @@ static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = {
.table_offset_entry[0] = ACPI_MADT_ADDR,
},
.fadt = {
.header.revision = 0x3U,
.header.length = 0xF4U,
.header.oem_revision = 0x1U,
.header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION,
.header.signature = ACPI_SIG_FADT,
.header.oem_id = ACPI_OEM_ID,
.header.oem_table_id = "ACRNMADT",
.header.asl_compiler_id = ACPI_ASL_COMPILER_ID,
.dsdt = ACPI_DSDT_ADDR,
.pm1a_event_block = PM1A_EVT_ADDRESS,
.pm1a_control_block = PM1A_CNT_ADDRESS,
.pm1_event_length = 0x4U,
.pm1_control_length = 0x02U,
.flags = 0x00001125U, /* HEADLESS | TMR_VAL_EXT | SLP_BUTTON | PROC_C1 | WBINVD */
},
.dsdt = {
.revision = 0x3U,
.length = sizeof(struct acpi_table_header),
.oem_revision = 0x1U,
.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION,
.signature = ACPI_SIG_DSDT,
.oem_id = ACPI_OEM_ID,
.oem_table_id = "ACRNMADT",
.asl_compiler_id = ACPI_ASL_COMPILER_ID,
},
.madt = {
.header.revision = 0x3U,
.header.oem_revision = 0x1U,
@@ -70,6 +97,8 @@ void build_vacpi(struct acrn_vm *vm)
{
struct acpi_table_rsdp *rsdp;
struct acpi_table_xsdt *xsdt;
struct acpi_table_fadt *fadp;
struct acpi_table_header *dsdt;
struct acpi_table_madt *madt;
struct acpi_madt_local_apic *lapic;
uint16_t i;
@@ -81,9 +110,28 @@ void build_vacpi(struct acrn_vm *vm)
(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);
(void)copy_to_gpa(vm, xsdt, ACPI_XSDT_ADDR, sizeof(struct acpi_table_header));
xsdt = (struct acpi_table_xsdt *)gpa2hva(vm, ACPI_XSDT_ADDR);
stac();
xsdt->table_offset_entry[0] = ACPI_FADT_ADDR;
xsdt->table_offset_entry[1] = ACPI_MADT_ADDR;
/* Currently XSDT table only pointers to 2 ACPI table entry (FADT/MADT) */
xsdt->header.length = sizeof(struct acpi_table_header) + (2U * sizeof(uint64_t));
xsdt->header.checksum = calculate_checksum8(xsdt, xsdt->header.length);
clac();
fadp = &acpi_table_template[vm->vm_id].fadt;
fadp->header.checksum = calculate_checksum8(fadp, fadp->header.length);
/* Copy FADT table to guest physical memory */
(void)copy_to_gpa(vm, fadp, ACPI_FADT_ADDR, fadp->header.length);
dsdt = &acpi_table_template[vm->vm_id].dsdt;
dsdt->checksum = calculate_checksum8(dsdt, dsdt->length);
/* Copy DSDT table and its subtables to guest physical memory */
(void)copy_to_gpa(vm, dsdt, ACPI_DSDT_ADDR, dsdt->length);
/* Fix up MADT LAPIC subtables */
for (i = 0U; i < vm->hw.created_vcpus; i++) {