From 1dccbdbaa2f587f0b6adc86b5daa47de1701f9bb Mon Sep 17 00:00:00 2001 From: Li Fei1 Date: Tue, 14 Apr 2020 15:36:26 +0800 Subject: [PATCH] hv: vapic: add mcfg table support Add MCFG table support to allow guest access PCIe external CFG space by ECAM Tracked-On: #4623 Signed-off-by: Li Fei1 --- hypervisor/arch/x86/configs/vacpi.c | 31 ++++++++++++++++++++++++++--- hypervisor/boot/include/acpi.h | 13 ++++++++++++ hypervisor/dm/vpci/vpci.c | 11 +++++----- hypervisor/include/dm/vacpi.h | 7 +++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/hypervisor/arch/x86/configs/vacpi.c b/hypervisor/arch/x86/configs/vacpi.c index 949a7c992..aeb52edb4 100644 --- a/hypervisor/arch/x86/configs/vacpi.c +++ b/hypervisor/arch/x86/configs/vacpi.c @@ -60,6 +60,21 @@ static struct acpi_table_info acpi_table_template[CONFIG_MAX_VM_NUM] = { .oem_table_id = "ACRNMADT", .asl_compiler_id = ACPI_ASL_COMPILER_ID, }, + .mcfg = { + .header.revision = 0x3U, + .header.oem_revision = 0x1U, + .header.asl_compiler_revision = ACPI_ASL_COMPILER_VERSION, + .header.signature = ACPI_SIG_MCFG, + .header.oem_id = ACPI_OEM_ID, + .header.oem_table_id = "ACRNMADT", + .header.asl_compiler_id = ACPI_ASL_COMPILER_ID, + }, + .mcfg_entry = { + .address = VIRT_PCI_MMCFG_BASE, + .pci_segment = 0U, + .start_bus_number = 0x0U, + .end_bus_number = 0xFFU, + }, .madt = { .header.revision = 0x3U, .header.oem_revision = 0x1U, @@ -99,6 +114,7 @@ void build_vacpi(struct acrn_vm *vm) struct acpi_table_xsdt *xsdt; struct acpi_table_fadt *fadp; struct acpi_table_header *dsdt; + struct acpi_table_mcfg *mcfg; struct acpi_table_madt *madt; struct acpi_madt_local_apic *lapic; uint16_t i; @@ -115,9 +131,10 @@ void build_vacpi(struct acrn_vm *vm) 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->table_offset_entry[1] = ACPI_MCFG_ADDR; + xsdt->table_offset_entry[2] = ACPI_MADT_ADDR; + /* Currently XSDT table only pointers to 3 ACPI table entry (FADT/MCFG/MADT) */ + xsdt->header.length = sizeof(struct acpi_table_header) + (3U * sizeof(uint64_t)); xsdt->header.checksum = calculate_checksum8(xsdt, xsdt->header.length); clac(); @@ -133,6 +150,14 @@ void build_vacpi(struct acrn_vm *vm) /* Copy DSDT table and its subtables to guest physical memory */ (void)copy_to_gpa(vm, dsdt, ACPI_DSDT_ADDR, dsdt->length); + mcfg = &acpi_table_template[vm->vm_id].mcfg; + mcfg->header.length = sizeof(struct acpi_table_mcfg) + + (1U * sizeof(struct acpi_mcfg_allocation)); /* We only support one mcfg allocation structure */ + mcfg->header.checksum = calculate_checksum8(mcfg, mcfg->header.length); + + /* Copy MCFG table and its subtables to guest physical memory */ + (void)copy_to_gpa(vm, mcfg, ACPI_MCFG_ADDR, mcfg->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]; diff --git a/hypervisor/boot/include/acpi.h b/hypervisor/boot/include/acpi.h index a247c0363..070d43a6a 100644 --- a/hypervisor/boot/include/acpi.h +++ b/hypervisor/boot/include/acpi.h @@ -139,6 +139,19 @@ struct acpi_table_fadt { uint8_t unused3[128]; /* ACRN doesn't use these fields */ } __packed; +struct acpi_table_mcfg { + struct acpi_table_header header; /* Common ACPI table header */ + uint8_t reserved[8]; +} __packed; + +struct acpi_mcfg_allocation { + uint64_t address; /* Base address, processor-relative */ + uint16_t pci_segment; /* PCI segment group number */ + uint8_t start_bus_number; /* Starting PCI Bus number */ + uint8_t end_bus_number; /* Final PCI Bus number */ + uint32_t reserved; +} __packed; + struct acpi_table_madt { /* Common ACPI table header */ struct acpi_table_header header; diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index e09f8caea..8546cae8a 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "vpci_priv.h" #include "pci_dev.h" @@ -248,13 +249,11 @@ void init_vpci(struct acrn_vm *vm) vpci_init_vdevs(vm); vm_config = get_vm_config(vm->vm_id); - if (vm_config->load_order != PRE_LAUNCHED_VM) { - /* PCI MMCONFIG for post-launched VM is fixed to 0xE0000000 */ - pci_mmcfg_base = (vm_config->load_order == SOS_VM) ? get_mmcfg_base() : 0xE0000000UL; - vm->vpci.pci_mmcfg_base = pci_mmcfg_base; - register_mmio_emulation_handler(vm, vpci_mmio_cfg_access, + /* virtual PCI MMCONFIG for SOS is same with the physical value */ + pci_mmcfg_base = (vm_config->load_order == SOS_VM) ? get_mmcfg_base() : VIRT_PCI_MMCFG_BASE; + vm->vpci.pci_mmcfg_base = pci_mmcfg_base; + register_mmio_emulation_handler(vm, vpci_mmio_cfg_access, pci_mmcfg_base, pci_mmcfg_base + PCI_MMCONFIG_SIZE, &vm->vpci, false); - } /* Intercept and handle I/O ports CF8h */ register_pio_emulation_handler(vm, PCI_CFGADDR_PIO_IDX, &pci_cfgaddr_range, diff --git a/hypervisor/include/dm/vacpi.h b/hypervisor/include/dm/vacpi.h index 0c67b3dc5..6581d1116 100644 --- a/hypervisor/include/dm/vacpi.h +++ b/hypervisor/include/dm/vacpi.h @@ -36,6 +36,7 @@ * XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used) * FADT -> 0xf2500 (244 bytes fixed for ACPI 2.0) * DSDT -> 0xf2600 (36 bytes fixed for an empty DSDT) + * MCFG -> 0xf2700 (36 bytes fixed + 8 bytes reserved + 1 * 16 bytes) * MADT -> 0xf2740 (depends on #CPUs) */ #define ACPI_BASE 0xf2400U @@ -44,12 +45,16 @@ #define ACPI_XSDT_ADDR (ACPI_BASE + 0x080U) #define ACPI_FADT_ADDR (ACPI_BASE + 0x100U) #define ACPI_DSDT_ADDR (ACPI_BASE + 0x200U) +#define ACPI_MCFG_ADDR (ACPI_BASE + 0x300U) #define ACPI_MADT_ADDR (ACPI_BASE + 0x340U) #define ACPI_OEM_ID "ACRN " #define ACPI_ASL_COMPILER_ID "INTL" #define ACPI_ASL_COMPILER_VERSION 0x20190802U +/* virtual PCI MMCFG address base for pre/post-launched VM. */ +#define VIRT_PCI_MMCFG_BASE 0xE0000000UL + struct acrn_vm; struct acpi_table_info { struct acpi_table_rsdp rsdp; @@ -58,6 +63,8 @@ struct acpi_table_info { struct { struct acpi_table_fadt fadt; struct acpi_table_header dsdt; /* an empty DSDT */ + struct acpi_table_mcfg mcfg; + struct acpi_mcfg_allocation mcfg_entry; /* mcfg_entry msut be declared fellowing mcfg */ struct acpi_table_madt madt; struct acpi_madt_local_apic_nmi lapic_nmi; struct acpi_madt_local_apic lapic_array[MAX_PCPU_NUM];