From 15da33d8af9c63ade5c34c0966cf799e73e24627 Mon Sep 17 00:00:00 2001 From: Victor Sun Date: Wed, 27 Nov 2019 13:39:52 +0800 Subject: [PATCH] HV: parse default pci mmcfg base The default PCI mmcfg base is stored in ACPI MCFG table, when CONFIG_ACPI_PARSE_ENABLED is set, acpi_fixup() function will parse and fix up the platform mmcfg base in ACRN boot stage; when it is not set, platform mmcfg base will be initialized to DEFAULT_PCI_MMCFG_BASE which generated by acrn-config tool; Please note we will not support platform which has multiple PCI segment groups. Tracked-On: #4157 Signed-off-by: Victor Sun Acked-by: Eddie Dong --- hypervisor/acpi_parser/acpi_ext.c | 37 +++++++++++++++++-- .../configs/nuc7i7dnb/platform_acpi_info.h | 3 ++ .../arch/x86/configs/platform_acpi_info.h | 3 ++ hypervisor/arch/x86/cpu.c | 6 +++ hypervisor/boot/guest/vboot_wrapper.c | 3 -- hypervisor/boot/include/acpi.h | 10 ++++- hypervisor/hw/pci.c | 14 +++++++ hypervisor/include/hw/pci.h | 5 +++ 8 files changed, 72 insertions(+), 9 deletions(-) diff --git a/hypervisor/acpi_parser/acpi_ext.c b/hypervisor/acpi_parser/acpi_ext.c index dccb90ca6..35cedb4c8 100644 --- a/hypervisor/acpi_parser/acpi_ext.c +++ b/hypervisor/acpi_parser/acpi_ext.c @@ -33,6 +33,7 @@ #include #include #include +#include #include /* Per ACPI spec: @@ -111,15 +112,30 @@ static void *get_facs_table(const uint8_t *facp_addr) return (void *)facs_addr; } -/* put all ACPI fix up code here */ -void acpi_fixup(void) +/* @pre mcfg_addr != NULL */ +static uint64_t parse_mmcfg_base(const uint8_t *mcfg_addr) { - uint8_t *facp_addr, *facs_addr; + uint64_t base = 0UL; + uint32_t length = get_acpi_dt_dword(mcfg_addr, OFFSET_MCFG_LENGTH); + + if (length > OFFSET_MCFG_ENTRY1) { + pr_fatal("Multiple PCI segment groups is not supported!"); + } else { + base = get_acpi_dt_qword(mcfg_addr, OFFSET_MCFG_ENTRY0_BASE); + } + return base; +} + +/* put all ACPI fix up code here */ +int32_t acpi_fixup(void) +{ + uint8_t *facp_addr = NULL, *facs_addr = NULL, *mcfg_addr = NULL; + uint64_t def_mmcfg_base = 0UL; + int32_t ret = 0; struct acpi_generic_address pm1a_cnt, pm1a_evt; struct pm_s_state_data *sx_data = get_host_sstate_data(); facp_addr = (uint8_t *)get_acpi_tbl(ACPI_SIG_FADT); - if (facp_addr != NULL) { get_acpi_dt_gas(facp_addr, OFFSET_PM1A_EVT, &pm1a_evt); get_acpi_dt_gas(facp_addr, OFFSET_PM1A_CNT, &pm1a_cnt); @@ -143,4 +159,17 @@ void acpi_fixup(void) rr_data->val = *(facp_addr + OFFSET_RESET_VALUE); } } + + mcfg_addr = (uint8_t *)get_acpi_tbl(ACPI_SIG_MCFG); + if (mcfg_addr != NULL) { + def_mmcfg_base = parse_mmcfg_base(mcfg_addr); + set_mmcfg_base(def_mmcfg_base); + } + + if ((facp_addr == NULL) || (facs_addr == NULL) + || (mcfg_addr == NULL) || (def_mmcfg_base == 0UL)) { + ret = -1; + } + + return ret; } diff --git a/hypervisor/arch/x86/configs/nuc7i7dnb/platform_acpi_info.h b/hypervisor/arch/x86/configs/nuc7i7dnb/platform_acpi_info.h index 45270fa66..38ca0a947 100644 --- a/hypervisor/arch/x86/configs/nuc7i7dnb/platform_acpi_info.h +++ b/hypervisor/arch/x86/configs/nuc7i7dnb/platform_acpi_info.h @@ -39,6 +39,9 @@ #define RESET_REGISTER_SPACE_ID SPACE_SYSTEM_IO #define RESET_REGISTER_VALUE 0x6U +/* PCI mmcfg base of MCFG */ +#define DEFAULT_PCI_MMCFG_BASE 0xE0000000UL + /* DRHD of DMAR */ #define DRHD_COUNT 2U diff --git a/hypervisor/arch/x86/configs/platform_acpi_info.h b/hypervisor/arch/x86/configs/platform_acpi_info.h index 6588296bc..4f98b6682 100644 --- a/hypervisor/arch/x86/configs/platform_acpi_info.h +++ b/hypervisor/arch/x86/configs/platform_acpi_info.h @@ -24,6 +24,9 @@ #define RESET_REGISTER_VALUE 0UL #define RESET_REGISTER_SPACE_ID 0UL +/* PCI mmcfg base of MCFG, pre-assumption is platform only has one PCI segment group */ +#define DEFAULT_PCI_MMCFG_BASE 0UL + /* DRHD of DMAR */ #define DRHD_COUNT 8U diff --git a/hypervisor/arch/x86/cpu.c b/hypervisor/arch/x86/cpu.c index ecbdc8a83..c40d64622 100644 --- a/hypervisor/arch/x86/cpu.c +++ b/hypervisor/arch/x86/cpu.c @@ -144,6 +144,12 @@ void init_pcpu_pre(bool is_bsp) early_init_lapic(); init_vboot(); +#ifdef CONFIG_ACPI_PARSE_ENABLED + ret = acpi_fixup(); + if (ret != 0) { + panic("failed to parse/fix up ACPI table!"); + } +#endif if (!init_percpu_lapic_id()) { panic("failed to init_percpu_lapic_id!"); diff --git a/hypervisor/boot/guest/vboot_wrapper.c b/hypervisor/boot/guest/vboot_wrapper.c index d1c1c10c5..f46be2a6a 100644 --- a/hypervisor/boot/guest/vboot_wrapper.c +++ b/hypervisor/boot/guest/vboot_wrapper.c @@ -68,9 +68,6 @@ void init_vboot(void) * initialized before calling other vboot_ops interface. */ vboot_ops->init(); -#ifdef CONFIG_ACPI_PARSE_ENABLED - acpi_fixup(); -#endif } /* @pre: vboot_ops != NULL */ diff --git a/hypervisor/boot/include/acpi.h b/hypervisor/boot/include/acpi.h index 92d793df8..e0a269260 100644 --- a/hypervisor/boot/include/acpi.h +++ b/hypervisor/boot/include/acpi.h @@ -36,13 +36,19 @@ #define OFFSET_WAKE_VECTOR_32 12U #define OFFSET_WAKE_VECTOR_64 24U +/* MCFG field offsets */ +#define OFFSET_MCFG_LENGTH 4U +#define OFFSET_MCFG_ENTRY0 44U +#define OFFSET_MCFG_ENTRY0_BASE 44U +#define OFFSET_MCFG_ENTRY1 60U + #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" - +#define ACPI_SIG_MCFG "MCFG" /* Memory Mapped Configuration table */ struct packed_gas { uint8_t space_id; @@ -200,7 +206,7 @@ uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM]); uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array); #ifdef CONFIG_ACPI_PARSE_ENABLED -void acpi_fixup(void); +int32_t acpi_fixup(void); #endif #endif /* !ACPI_H */ diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index af395f00f..ea3013382 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -41,13 +41,27 @@ #include #include #include +#include static spinlock_t pci_device_lock; static uint32_t num_pci_pdev; static struct pci_pdev pci_pdev_array[CONFIG_MAX_PCI_DEV_NUM]; +static uint64_t pci_mmcfg_base = DEFAULT_PCI_MMCFG_BASE; static void init_pdev(uint16_t pbdf, uint32_t drhd_index); +#ifdef CONFIG_ACPI_PARSE_ENABLED +void set_mmcfg_base(uint64_t mmcfg_base) +{ + pci_mmcfg_base = mmcfg_base; +} +#endif + +uint64_t get_mmcfg_base(void) +{ + return pci_mmcfg_base; +} + /* @brief: Find the DRHD index corresponding to a PCI device * Runs through the pci_pdev_array and returns the value in drhd_idx * member from pdev structure that matches matches B:D.F diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 17d0991cb..42fc3f9da 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -233,6 +233,11 @@ static inline bool bdf_is_equal(union pci_bdf a, union pci_bdf b) return (a.value == b.value); } +#ifdef CONFIG_ACPI_PARSE_ENABLED +void set_mmcfg_base(uint64_t mmcfg_base); +#endif +uint64_t get_mmcfg_base(void); + uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes); void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val); void enable_disable_pci_intx(union pci_bdf bdf, bool enable);