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 <fei1.li@intel.com>
This commit is contained in:
Li Fei1 2020-04-14 15:36:26 +08:00 committed by wenlingz
parent 4eb3f5a0c7
commit 1dccbdbaa2
4 changed files with 53 additions and 9 deletions

View File

@ -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];

View File

@ -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;

View File

@ -33,6 +33,7 @@
#include <vtd.h>
#include <io.h>
#include <mmu.h>
#include <vacpi.h>
#include <logmsg.h>
#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,

View File

@ -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];