From c5537ec4d4a2c0d24c8665ea396109e7c07e134e Mon Sep 17 00:00:00 2001 From: Yuanyuan Zhao Date: Wed, 27 Oct 2021 20:41:28 +0800 Subject: [PATCH] dm: get lapic id from madt The GET_PLATFORM_INFO will be removed from hypervisor. The acrn-dm can only refer to Service VM's resources from now, all the resources out of Service VM are not awared by acrn-dm. The original info got from GET_PLATFORM_INFO needs to changed to Service VM's perspective like lapic id. The pcpu_id is the index of lapic instance in MADT table. This patch parses the Service VM's MADT table to convert the pcpu_id to lapic_id instead of GET_PLATFORM_INFO. Tracked-On: #6690 Signed-off-by: Yuanyuan Zhao Acked-by: Wang, Yu1 --- devicemodel/Makefile | 1 + devicemodel/core/main.c | 5 + devicemodel/hw/platform/acpi/acpi.c | 11 +- devicemodel/hw/platform/acpi/acpi_parser.c | 151 +++++++++++++++++++++ devicemodel/hw/platform/vssram/vssram.c | 2 +- devicemodel/include/acpi.h | 32 ++++- 6 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 devicemodel/hw/platform/acpi/acpi_parser.c diff --git a/devicemodel/Makefile b/devicemodel/Makefile index 39dc1cd55..e0b59958e 100644 --- a/devicemodel/Makefile +++ b/devicemodel/Makefile @@ -108,6 +108,7 @@ SRCS += hw/platform/pty_vuart.c SRCS += hw/platform/acpi/acpi.c SRCS += hw/platform/vssram/vssram.c SRCS += hw/platform/acpi/acpi_pm.c +SRCS += hw/platform/acpi/acpi_parser.c SRCS += hw/platform/rpmb/rpmb_sim.c SRCS += hw/platform/rpmb/rpmb_backend.c SRCS += hw/platform/rpmb/att_keybox.c diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index 84d432948..90fd6b738 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -836,6 +836,11 @@ main(int argc, char *argv[]) if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) fprintf(stderr, "cannot register handler for SIGPIPE\n"); + if (parse_madt()) { + pr_err("Failed to parse the MADT table\n"); + exit(1); + } + while ((c = getopt_long(argc, argv, optstr, long_options, &option_idx)) != -1) { switch (c) { diff --git a/devicemodel/hw/platform/acpi/acpi.c b/devicemodel/hw/platform/acpi/acpi.c index b2e15463d..b7099aaef 100644 --- a/devicemodel/hw/platform/acpi/acpi.c +++ b/devicemodel/hw/platform/acpi/acpi.c @@ -272,11 +272,6 @@ int pcpuid_from_vcpuid(uint64_t guest_pcpu_bitmask, int vcpu_id) return find_nth_set_bit_index(guest_pcpu_bitmask, vcpu_id); } -int lapicid_from_pcpuid(struct acrn_platform_info *plat_info, int pcpu_id) -{ - return plat_info->hw.lapic_ids[pcpu_id]; -} - static int basl_fwrite_madt(FILE *fp, struct vmctx *ctx) { @@ -343,7 +338,11 @@ basl_fwrite_madt(FILE *fp, struct vmctx *ctx) return -1; } - lapic_id = lapicid_from_pcpuid(&plat_info, pcpu_id); + lapic_id = lapicid_from_pcpuid(pcpu_id); + if (lapic_id == -1) { + pr_err("Failed to retrieve the local APIC ID for pCPU %u\n", pcpu_id); + return -1; + } EFPRINTF(fp, "[0001]\t\tSubtable Type : 00\n"); EFPRINTF(fp, "[0001]\t\tLength : 08\n"); diff --git a/devicemodel/hw/platform/acpi/acpi_parser.c b/devicemodel/hw/platform/acpi/acpi_parser.c new file mode 100644 index 000000000..0f06f8004 --- /dev/null +++ b/devicemodel/hw/platform/acpi/acpi_parser.c @@ -0,0 +1,151 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2003 John Baldwin + * Copyright (c) 2022 Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm.h" +#include "log.h" +#include "hsm_ioctl_defs.h" +#include "acpi.h" + +static int lapic_ids[ACRN_PLATFORM_LAPIC_IDS_MAX] = {0xff}; + +/* pcpuid is the processor local APIC instance index in MADT */ +int lapicid_from_pcpuid(int pcpu_id) +{ + if (pcpu_id < 0 || pcpu_id >= ACRN_PLATFORM_LAPIC_IDS_MAX || + lapic_ids[pcpu_id] == 0xff) { + return -1; + } + return (int)lapic_ids[pcpu_id]; +} + +int lapic_to_pcpu(int lapic) +{ + int j; + + for (j = 0; j < ACRN_PLATFORM_LAPIC_IDS_MAX; j++) { + if (lapic == lapicid_from_pcpuid(j)) { + return j; + } + } + return ACRN_PLATFORM_LAPIC_IDS_MAX - 1; +} + +static int +local_parse_madt(struct acpi_table_madt *madt) +{ + uint16_t pcpu_num = 0U; + int ret = 0; + struct acpi_madt_local_apic *processor; + struct acpi_table_madt *madt_ptr; + void *first, *end, *iterator; + struct acpi_subtable_header *entry; + + madt_ptr = madt; + + first = madt_ptr + 1; + end = (void *)madt_ptr + madt_ptr->header.length; + + for (iterator = first; (iterator) < (end); iterator += entry->length) { + entry = (struct acpi_subtable_header *)iterator; + if (entry->length < sizeof(struct acpi_subtable_header)) { + break; + } + + if (entry->type == ACPI_MADT_TYPE_LOCAL_APIC) { + processor = (struct acpi_madt_local_apic *)iterator; + if ((processor->lapic_flags & ACPI_MADT_ENABLED) != 0U) { + if (pcpu_num < ACRN_PLATFORM_LAPIC_IDS_MAX) { + lapic_ids[pcpu_num] = processor->id; + } + pcpu_num++; + } + } + } + + if (pcpu_num == 0) { + ret = -1; + } + return ret; +} + +/* + * There has an assumption. The Service VM owned pcpu starts from physical cpu 0, + * otherwise Service VM doesn't know the mapping relationship between its vcpu0 + * and pcpu_id. + */ +int parse_madt(void) +{ + int ret = 0U; + ssize_t size; + struct acpi_table_madt *madt; + struct stat file_state; + + int fd = open("/sys/firmware/acpi/tables/APIC", O_RDONLY); + if (fd < 0) { + pr_err("Failed to open the Service VM APIC file.\n"); + return -1; + } + + if (fstat(fd, &file_state) == -1) { + pr_err("Failed to get APIC file state.\n"); + close(fd); + return -1; + } + + madt = (struct acpi_table_madt *)malloc(file_state.st_size); + if (madt == NULL) { + pr_err("Failed to malloc %d bytes to store the MADT table.\n", file_state.st_size); + close(fd); + return -1; + } + size = read(fd, madt, file_state.st_size); + if (size == file_state.st_size) { + ret = local_parse_madt(madt); + } else { + pr_err("Failed to read Service VM MADT table.\n"); + ret = -1; + } + + free(madt); + close(fd); + return ret; +} diff --git a/devicemodel/hw/platform/vssram/vssram.c b/devicemodel/hw/platform/vssram/vssram.c index 7a10a9a3a..3bae62db4 100644 --- a/devicemodel/hw/platform/vssram/vssram.c +++ b/devicemodel/hw/platform/vssram/vssram.c @@ -441,7 +441,7 @@ static int init_guest_lapicid_tbl(struct acrn_platform_info *platform_info, uint if (pcpu_id < 0) return -1; - guest_lapicid_tbl[vcpu_id] = lapicid_from_pcpuid(platform_info, pcpu_id); + guest_lapicid_tbl[vcpu_id] = lapicid_from_pcpuid(pcpu_id); } return 0; } diff --git a/devicemodel/include/acpi.h b/devicemodel/include/acpi.h index 04a939905..52130d220 100644 --- a/devicemodel/include/acpi.h +++ b/devicemodel/include/acpi.h @@ -41,6 +41,11 @@ #define IO_PMTMR 0x0 /* PM Timer is disabled in ACPI */ +#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 + struct acpi_table_hdr { /* ASCII table signature */ char signature[4]; @@ -62,6 +67,29 @@ struct acpi_table_hdr { uint32_t asl_compiler_revision; } __attribute__((packed)); +struct acpi_table_madt { + /* Common ACPI table header */ + struct acpi_table_hdr header; + /* Physical address of local APIC */ + uint32_t address; + uint32_t flags; +} __packed; + +struct acpi_subtable_header { + uint8_t type; + uint8_t length; +} __packed; + +struct acpi_madt_local_apic { + struct acpi_subtable_header header; + /* ACPI processor id */ + uint8_t processor_id; + /* Processor's local APIC id */ + uint8_t id; + uint32_t lapic_flags; +} __packed; + + /* All dynamic table entry no. */ #define NHLT_ENTRY_NO 8 @@ -89,6 +117,8 @@ void power_button_init(struct vmctx *ctx); void power_button_deinit(struct vmctx *ctx); int pcpuid_from_vcpuid(uint64_t guest_pcpu_bitmask, int vcpu_id); -int lapicid_from_pcpuid(struct acrn_platform_info *plat_info, int pcpu_id); +int lapicid_from_pcpuid(int pcpu_id); +int lapic_to_pcpu(int lapic); +int parse_madt(void); #endif /* _ACPI_H_ */