From 81a6f109bab8f58984603fbd534e2548be290480 Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 19 Feb 2018 17:33:48 -0600 Subject: soc/intel/broadwell: Enable VT-d and X2APIC We use the usual static addresses 0xfed90000/0xfed91000 for the GFX IOMMU and the general IOMMU respectively. These addresses have to be configured in MCHBAR registers and reserved from the OS. Change-Id: I7afcce0da028a160174db2cf6b4b6735bcd59165 Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/23820 Tested-by: build bot (Jenkins) Reviewed-by: Youness Alaoui Reviewed-by: Nico Huber --- src/soc/intel/broadwell/include/soc/iomap.h | 6 ++++++ src/soc/intel/broadwell/include/soc/lpc.h | 3 +++ src/soc/intel/broadwell/include/soc/pci_devs.h | 5 +++++ src/soc/intel/broadwell/include/soc/systemagent.h | 7 +++++++ src/soc/intel/broadwell/lpc.c | 15 +++++++++++++++ src/soc/intel/broadwell/romstage/systemagent.c | 21 +++++++++++++++++++++ src/soc/intel/broadwell/systemagent.c | 20 +++++++++++++++++--- 7 files changed, 74 insertions(+), 3 deletions(-) (limited to 'src/soc/intel') diff --git a/src/soc/intel/broadwell/include/soc/iomap.h b/src/soc/intel/broadwell/include/soc/iomap.h index fe8e78b1e2..96b2c1fa45 100644 --- a/src/soc/intel/broadwell/include/soc/iomap.h +++ b/src/soc/intel/broadwell/include/soc/iomap.h @@ -39,6 +39,12 @@ #define HPET_BASE_ADDRESS 0xfed00000 +#define GFXVT_BASE_ADDRESS 0xfed90000ULL +#define GFXVT_BASE_SIZE 0x1000 + +#define VTVC0_BASE_ADDRESS 0xfed91000ULL +#define VTVC0_BASE_SIZE 0x1000 + #define ACPI_BASE_ADDRESS 0x1000 #define ACPI_BASE_SIZE 0x100 diff --git a/src/soc/intel/broadwell/include/soc/lpc.h b/src/soc/intel/broadwell/include/soc/lpc.h index 4fb0d903f2..5cca961bfe 100644 --- a/src/soc/intel/broadwell/include/soc/lpc.h +++ b/src/soc/intel/broadwell/include/soc/lpc.h @@ -86,4 +86,7 @@ #define PMIR_CF9LOCK (1 << 31) #define PMIR_CF9GR (1 << 20) +#define LPC_IBDF 0x6C /* I/O APIC bus/dev/fn */ +#define LPC_HnBDF(n) (0x70 + n * 2) /* HPET n bus/dev/fn */ + #endif diff --git a/src/soc/intel/broadwell/include/soc/pci_devs.h b/src/soc/intel/broadwell/include/soc/pci_devs.h index 59c64ce6c5..0880353999 100644 --- a/src/soc/intel/broadwell/include/soc/pci_devs.h +++ b/src/soc/intel/broadwell/include/soc/pci_devs.h @@ -112,4 +112,9 @@ #define PCH_DEV_SATA2 _PCH_DEV(LPC, 5) #define PCH_DEV_THERMAL _PCH_DEV(LPC, 6) +#define PCH_IOAPIC_PCI_BUS 250 +#define PCH_IOAPIC_PCI_SLOT 31 +#define PCH_HPET_PCI_BUS 250 +#define PCH_HPET_PCI_SLOT 15 + #endif diff --git a/src/soc/intel/broadwell/include/soc/systemagent.h b/src/soc/intel/broadwell/include/soc/systemagent.h index 125ba47f4c..92e79cc99a 100644 --- a/src/soc/intel/broadwell/include/soc/systemagent.h +++ b/src/soc/intel/broadwell/include/soc/systemagent.h @@ -74,6 +74,11 @@ #define D_LCK (1 << 4) #define G_SMRAME (1 << 3) #define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) +#define CAPID0_A 0xe4 +#define VTD_DISABLE (1 << 23) +#define ARCHDIS 0xff0 /* DMA Remap Engine Policy Control */ +#define DMAR_LCKDN (1 << 31) +#define PRSCAPDIS (1 << 2) #define MESEG_BASE 0x70 /* Management Engine Base. */ #define MESEG_LIMIT 0x78 /* Management Engine Limit. */ @@ -95,7 +100,9 @@ #define MCHBAR_PEI_VERSION 0x5034 #define BIOS_RESET_CPL 0x5da8 +#define GFXVTBAR 0x5400 #define EDRAMBAR 0x5408 +#define VTVC0BAR 0x5410 #define MCH_PAIR 0x5418 #define GDXCBAR 0x5420 diff --git a/src/soc/intel/broadwell/lpc.c b/src/soc/intel/broadwell/lpc.c index d1c42423ae..8e7f4de931 100644 --- a/src/soc/intel/broadwell/lpc.c +++ b/src/soc/intel/broadwell/lpc.c @@ -49,6 +49,10 @@ static void pch_enable_ioapic(struct device *dev) { u32 reg32; + /* Assign unique bus/dev/fn for I/O APIC */ + pci_write_config16(dev, LPC_IBDF, + PCH_IOAPIC_PCI_BUS << 8 | PCH_IOAPIC_PCI_SLOT << 3); + set_ioapic_id(VIO_APIC_VADDR, 0x02); /* affirm full set of redirection table entries ("write once") */ @@ -67,6 +71,16 @@ static void pch_enable_ioapic(struct device *dev) io_apic_write(VIO_APIC_VADDR, 0x03, 0x01); } +static void enable_hpet(struct device *dev) +{ + size_t i; + + /* Assign unique bus/dev/fn for each HPET */ + for (i = 0; i < 8; ++i) + pci_write_config16(dev, LPC_HnBDF(i), + PCH_HPET_PCI_BUS << 8 | PCH_HPET_PCI_SLOT << 3 | i); +} + /* PIRQ[n]_ROUT[3:0] - PIRQ Routing Control * 0x00 - 0000 = Reserved * 0x01 - 0001 = Reserved @@ -436,6 +450,7 @@ static void lpc_init(struct device *dev) pch_pirq_init(dev); setup_i8259(); i8259_configure_irq_trigger(9, 1); + enable_hpet(dev); /* Initialize power management */ pch_power_options(dev); diff --git a/src/soc/intel/broadwell/romstage/systemagent.c b/src/soc/intel/broadwell/romstage/systemagent.c index e7dbbc8602..153dfdfe13 100644 --- a/src/soc/intel/broadwell/romstage/systemagent.c +++ b/src/soc/intel/broadwell/romstage/systemagent.c @@ -47,5 +47,26 @@ static const struct reg_script systemagent_early_init_script[] = { void systemagent_early_init(void) { + const bool vtd_capable = + !(pci_read_config32(SA_DEV_ROOT, CAPID0_A) & VTD_DISABLE); + reg_script_run_on_dev(SA_DEV_ROOT, systemagent_early_init_script); + + if (vtd_capable) { + /* setup BARs: zeroize top 32 bits; set enable bit */ + MCHBAR32(GFXVTBAR + 4) = GFXVT_BASE_ADDRESS >> 32; + MCHBAR32(GFXVTBAR) = GFXVT_BASE_ADDRESS | 1; + MCHBAR32(VTVC0BAR + 4) = VTVC0_BASE_ADDRESS >> 32; + MCHBAR32(VTVC0BAR) = VTVC0_BASE_ADDRESS | 1; + + /* set PRSCAPDIS, lock GFXVTBAR policy cfg registers */ + u32 reg32; + reg32 = read32((void *)(GFXVT_BASE_ADDRESS + ARCHDIS)); + write32((void *)(GFXVT_BASE_ADDRESS + ARCHDIS), + reg32 | DMAR_LCKDN | PRSCAPDIS); + /* lock VTVC0BAR policy cfg registers */ + reg32 = read32((void *)(VTVC0_BASE_ADDRESS + ARCHDIS)); + write32((void *)(VTVC0_BASE_ADDRESS + ARCHDIS), + reg32 | DMAR_LCKDN); + } } diff --git a/src/soc/intel/broadwell/systemagent.c b/src/soc/intel/broadwell/systemagent.c index f46f5eac35..d9dbfe93c6 100644 --- a/src/soc/intel/broadwell/systemagent.c +++ b/src/soc/intel/broadwell/systemagent.c @@ -271,7 +271,7 @@ static void mc_report_map_entries(device_t dev, uint64_t *values) printk(BIOS_DEBUG, "MC MAP: GGC: 0x%x\n", pci_read_config16(dev, GGC)); } -static void mc_add_dram_resources(device_t dev) +static void mc_add_dram_resources(device_t dev, int *resource_cnt) { unsigned long base_k, size_k; unsigned long touud_k; @@ -327,7 +327,7 @@ static void mc_add_dram_resources(device_t dev) * The resource index starts low and should not meet or exceed * PCI_BASE_ADDRESS_0. */ - index = 0; + index = *resource_cnt; /* 0 - > 0xa0000 */ base_k = 0; @@ -373,18 +373,32 @@ static void mc_add_dram_resources(device_t dev) (0x100000 - 0xc0000) >> 10); chromeos_reserve_ram_oops(dev, index++); + + *resource_cnt = index; } static void systemagent_read_resources(device_t dev) { + int index = 0; + const bool vtd_capable = + !(pci_read_config32(dev, CAPID0_A) & VTD_DISABLE); + /* Read standard PCI resources. */ pci_dev_read_resources(dev); /* Add all fixed MMIO resources. */ mc_add_fixed_mmio_resources(dev); + /* Add VT-d MMIO resources if capable */ + if (vtd_capable) { + mmio_resource(dev, index++, GFXVT_BASE_ADDRESS / KiB, + GFXVT_BASE_SIZE / KiB); + mmio_resource(dev, index++, VTVC0_BASE_ADDRESS / KiB, + VTVC0_BASE_SIZE / KiB); + } + /* Calculate and add DRAM resources. */ - mc_add_dram_resources(dev); + mc_add_dram_resources(dev, &index); } static void systemagent_init(struct device *dev) -- cgit v1.2.3