Skip to content

Commit b447ce3

Browse files
donshengwenlingz
authored andcommitted
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>
1 parent 96b422c commit b447ce3

File tree

7 files changed

+191
-4
lines changed

7 files changed

+191
-4
lines changed

hypervisor/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ VP_BASE_C_SRCS += common/hv_main.c
247247
VP_BASE_C_SRCS += common/vm_load.c
248248
VP_BASE_C_SRCS += arch/x86/configs/vmptable.c
249249
VP_BASE_C_SRCS += arch/x86/configs/pci_dev.c
250+
VP_BASE_C_SRCS += arch/x86/configs/vacpi.c
250251
VP_BASE_C_SRCS += arch/x86/configs/$(CONFIG_BOARD)/ve820.c
251252

252253
# virtual platform device model

hypervisor/arch/x86/configs/vacpi.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <vm.h>
8+
#include <per_cpu.h>
9+
#include <vacpi.h>
10+
#include <pgtable.h>
11+
12+
/* ACPI tables for pre-launched VM and SOS */
13+
static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = {
14+
[0U ... (CONFIG_MAX_VM_NUM - 1U)] = {
15+
.rsdp = {
16+
.signature = ACPI_SIG_RSDP,
17+
.oem_id = ACPI_OEM_ID,
18+
.revision = 0x2U,
19+
.length = ACPI_RSDP_XCHECKSUM_LENGTH,
20+
.xsdt_physical_address = ACPI_XSDT_ADDR,
21+
},
22+
.xsdt = {
23+
/* Currently XSDT table only pointers to 1 ACPI table entry (MADT) */
24+
.header.length = sizeof(struct acpi_table_header) + sizeof(uint64_t),
25+
26+
.header.revision = 0x1U,
27+
.header.oem_revision = 0x1U,
28+
.header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION,
29+
.header.signature = ACPI_SIG_XSDT,
30+
.header.oem_id = ACPI_OEM_ID,
31+
.header.oem_table_id = "ACRNXSDT",
32+
.header.asl_compiler_id = ACPI_ASL_COMPILER_ID,
33+
34+
.table_offset_entry[0] = ACPI_MADT_ADDR,
35+
},
36+
.madt = {
37+
.header.revision = 0x3U,
38+
.header.oem_revision = 0x1U,
39+
.header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION,
40+
.header.signature = ACPI_SIG_MADT,
41+
.header.oem_id = ACPI_OEM_ID,
42+
.header.oem_table_id = "ACRNMADT",
43+
.header.asl_compiler_id = ACPI_ASL_COMPILER_ID,
44+
45+
.address = 0xFEE00000U, /* Local APIC Address */
46+
.flags = 0x1U, /* PC-AT Compatibility=1 */
47+
},
48+
.lapic_nmi = {
49+
.header.type = ACPI_MADT_TYPE_LOCAL_APIC_NMI,
50+
.header.length = sizeof(struct acpi_madt_local_apic_nmi),
51+
.processor_id = 0xFFU,
52+
.flags = 0x5U,
53+
.lint = 0x1U,
54+
},
55+
.lapic_array = {
56+
[0U ... (CONFIG_MAX_PCPU_NUM - 1U)] = {
57+
.header.type = ACPI_MADT_TYPE_LOCAL_APIC,
58+
.header.length = sizeof(struct acpi_madt_local_apic),
59+
.lapic_flags = 0x1U, /* Processor Enabled=1, Runtime Online Capable=0 */
60+
}
61+
},
62+
}
63+
};
64+
65+
/**
66+
* @pre vm != NULL
67+
* @pre vm->vm_id < CONFIG_MAX_VM_NUM
68+
*/
69+
void build_vacpi(struct acrn_vm *vm)
70+
{
71+
struct acpi_table_rsdp *rsdp;
72+
struct acpi_table_xsdt *xsdt;
73+
struct acpi_table_madt *madt;
74+
struct acpi_madt_local_apic *lapic;
75+
uint16_t i;
76+
77+
rsdp = &acpi_table_template[vm->vm_id].rsdp;
78+
rsdp->checksum = calculate_checksum8(rsdp, ACPI_RSDP_CHECKSUM_LENGTH);
79+
rsdp->extended_checksum = calculate_checksum8(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH);
80+
/* Copy RSDP table to guest physical memory */
81+
(void)copy_to_gpa(vm, rsdp, ACPI_RSDP_ADDR, ACPI_RSDP_XCHECKSUM_LENGTH);
82+
83+
xsdt = &acpi_table_template[vm->vm_id].xsdt;
84+
xsdt->header.checksum = calculate_checksum8(xsdt, xsdt->header.length);
85+
/* Copy XSDT table to guest physical memory */
86+
(void)copy_to_gpa(vm, xsdt, ACPI_XSDT_ADDR, xsdt->header.length);
87+
88+
/* Fix up MADT LAPIC subtables */
89+
for (i = 0U; i < vm->hw.created_vcpus; i++) {
90+
lapic = &acpi_table_template[vm->vm_id].lapic_array[i];
91+
lapic->processor_id = (uint8_t)i;
92+
lapic->id = (uint8_t)i;
93+
}
94+
95+
madt = &acpi_table_template[vm->vm_id].madt;
96+
madt->header.length = sizeof(struct acpi_table_madt)
97+
+ sizeof(struct acpi_madt_local_apic_nmi)
98+
+ (sizeof(struct acpi_madt_local_apic) * (size_t)vm->hw.created_vcpus);
99+
madt->header.checksum = calculate_checksum8(madt, madt->header.length);
100+
101+
/* Copy MADT table and its subtables to guest physical memory */
102+
(void)copy_to_gpa(vm, madt, ACPI_MADT_ADDR, madt->header.length);
103+
}

hypervisor/arch/x86/guest/vm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ void prepare_vm(uint16_t vm_id, struct acrn_vm_config *vm_config)
743743
if (err == 0) {
744744
if (is_prelaunched_vm(vm)) {
745745
(void)mptable_build(vm);
746+
build_vacpi(vm);
746747
}
747748

748749
(void )vm_sw_loader(vm);

hypervisor/boot/include/acpi.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212

1313
#define ACPI_RSDP_CHECKSUM_LENGTH 20U
14+
#define ACPI_RSDP_XCHECKSUM_LENGTH 36U
1415

1516
#define ACPI_NAME_SIZE 4U
1617
#define ACPI_OEM_ID_SIZE 6U
@@ -19,6 +20,7 @@
1920
#define ACPI_MADT_TYPE_LOCAL_APIC 0U
2021
#define ACPI_MADT_TYPE_IOAPIC 1U
2122
#define ACPI_MADT_ENABLED 1U
23+
#define ACPI_MADT_TYPE_LOCAL_APIC_NMI 4U
2224

2325
/* FACP field offsets */
2426
#define OFFSET_FACS_ADDR 36U
@@ -37,6 +39,7 @@
3739
#define ACPI_SIG_FADT "FACP" /* Fixed ACPI Description Table */
3840
#define ACPI_SIG_FACS 0x53434146U /* "FACS" */
3941
#define ACPI_SIG_RSDP "RSD PTR " /* Root System Description Ptr */
42+
#define ACPI_SIG_XSDT "XSDT" /* Extended System Description Table */
4043
#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
4144
#define ACPI_SIG_DMAR "DMAR"
4245

@@ -127,13 +130,20 @@ struct acpi_madt_local_apic {
127130
uint32_t lapic_flags;
128131
} __packed;
129132

133+
struct acpi_madt_local_apic_nmi {
134+
struct acpi_subtable_header header;
135+
uint8_t processor_id;
136+
uint16_t flags;
137+
uint8_t lint;
138+
} __packed;
139+
130140
struct acpi_madt_ioapic {
131141
struct acpi_subtable_header header;
132142
/* IOAPIC id */
133-
uint8_t id;
134-
uint8_t rsvd;
135-
uint32_t addr;
136-
uint32_t gsi_base;
143+
uint8_t id;
144+
uint8_t rsvd;
145+
uint32_t addr;
146+
uint32_t gsi_base;
137147
} __packed;
138148

139149
enum acpi_dmar_type {

hypervisor/include/arch/x86/vm_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <multiboot.h>
1313
#include <acrn_common.h>
1414
#include <mptable.h>
15+
#include <vacpi.h>
1516
#include <vm_configurations.h>
1617
#include <sgx.h>
1718

hypervisor/include/dm/vacpi.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
/************************************************************************
8+
*
9+
* FILE NAME
10+
*
11+
* vacpi.h
12+
*
13+
* DESCRIPTION
14+
*
15+
* This file defines API and extern variable for virtual ACPI
16+
*
17+
************************************************************************/
18+
/**********************************/
19+
/* EXTERNAL VARIABLES */
20+
/**********************************/
21+
#ifndef VACPI_H
22+
#define VACPI_H
23+
24+
#include <acpi.h>
25+
26+
/*
27+
*
28+
* Create the minimal set of ACPI tables required to boot pre-launched VM
29+
*
30+
* The tables are placed in the guest's ROM area just below 1MB physical,
31+
* above the MPTable.
32+
*
33+
* Layout
34+
* ------
35+
* RSDP -> 0xf2400 (36 bytes fixed)
36+
* XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used)
37+
* MADT -> 0xf2500 (depends on #CPUs)
38+
*/
39+
#define ACPI_BASE 0xf2400U
40+
41+
#define ACPI_RSDP_ADDR (ACPI_BASE + 0x0U)
42+
#define ACPI_XSDT_ADDR (ACPI_BASE + 0x080U)
43+
#define ACPI_MADT_ADDR (ACPI_BASE + 0x100U)
44+
45+
#define ACPI_OEM_ID "ACRN "
46+
#define ACPI_ASL_COMPILER_ID "INTL"
47+
#define ACPI_ASL_COMPILER_VERSION 0x20190802U
48+
49+
50+
struct acpi_table_info {
51+
struct acpi_table_rsdp rsdp;
52+
struct acpi_table_xsdt xsdt;
53+
54+
struct {
55+
struct acpi_table_madt madt;
56+
struct acpi_madt_local_apic_nmi lapic_nmi;
57+
struct acpi_madt_local_apic lapic_array[CONFIG_MAX_PCPU_NUM];
58+
} __packed;
59+
};
60+
61+
void build_vacpi(struct acrn_vm *vm);
62+
63+
#endif /* VACPI_H */

hypervisor/include/lib/util.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,12 @@ static inline uint8_t calculate_sum8(const void *buf, uint32_t length)
4646
return sum;
4747
}
4848

49+
/**
50+
* @pre buf != NULL
51+
*/
52+
static inline uint8_t calculate_checksum8(const void *buf, uint32_t len)
53+
{
54+
return (uint8_t)(0x100U - calculate_sum8(buf, len));
55+
}
56+
4957
#endif /* UTIL_H */

0 commit comments

Comments
 (0)