Matt DeVillier has uploaded this change for review. ( https://review.coreboot.org/24983
Change subject: nb/intel/haswell;sb/intel/lynxpoint: Enable VT-d and X2APIC ......................................................................
nb/intel/haswell;sb/intel/lynxpoint: 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: Ib8f2fed9ae08491779e76f7d1ddc1bd3eed45ac7 Signed-off-by: Matt DeVillier matt.devillier@gmail.com --- M src/northbridge/intel/haswell/early_init.c M src/northbridge/intel/haswell/haswell.h M src/northbridge/intel/haswell/northbridge.c M src/southbridge/intel/lynxpoint/lpc.c M src/southbridge/intel/lynxpoint/pch.h 5 files changed, 81 insertions(+), 5 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/83/24983/1
diff --git a/src/northbridge/intel/haswell/early_init.c b/src/northbridge/intel/haswell/early_init.c index a2b0f7f..663812a 100644 --- a/src/northbridge/intel/haswell/early_init.c +++ b/src/northbridge/intel/haswell/early_init.c @@ -94,11 +94,39 @@ MCHBAR32(0x5418) = reg32; }
+static void haswell_setup_iommu(void) +{ + const u32 capid0_a = pci_read_config32(PCI_DEV(0, 0, 0), CAPID0_A); + + if (capid0_a & VTD_DISABLE) + return; + + /* 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 L3HIT2PEND_DIS, lock GFXVTBAR policy cfg registers */ + u32 reg32; + reg32 = read32((void *)(GFXVT_BASE_ADDRESS + ARCHDIS)); + write32((void *)(GFXVT_BASE_ADDRESS + ARCHDIS), + reg32 | DMAR_LCKDN | L3HIT2PEND_DIS); + /* clear SPCAPCTRL */ + reg32 = read32((void *)(VTVC0_BASE_ADDRESS + ARCHDIS)) & ~SPCAPCTRL; + /* set GLBIOTLBINV, GLBCTXTINV; lock VTVC0BAR policy cfg registers */ + write32((void *)(VTVC0_BASE_ADDRESS + ARCHDIS), + reg32 | DMAR_LCKDN | GLBIOTLBINV | GLBCTXTINV); +} + void haswell_early_initialization(int chipset_type) { /* Setup all BARs required for early PCIe and raminit */ haswell_setup_bars();
+ /* Setup IOMMU BARs */ + haswell_setup_iommu(); + /* Device Enable: IGD and Mini-HD Audio */ pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN); diff --git a/src/northbridge/intel/haswell/haswell.h b/src/northbridge/intel/haswell/haswell.h index b7954e8..97ee363 100644 --- a/src/northbridge/intel/haswell/haswell.h +++ b/src/northbridge/intel/haswell/haswell.h @@ -35,6 +35,12 @@ #endif #define DEFAULT_EPBAR 0xfed19000 /* 4 KB */
+#define GFXVT_BASE_ADDRESS 0xfed90000ULL +#define GFXVT_BASE_SIZE 0x1000 + +#define VTVC0_BASE_ADDRESS 0xfed91000ULL +#define VTVC0_BASE_SIZE 0x1000 + #include <southbridge/intel/lynxpoint/pch.h>
/* Everything below this line is ignored in the DSDT */ @@ -88,6 +94,16 @@
#define SKPAD 0xdc /* Scratchpad Data */
+#define CAPID0_A 0xe4 +#define VTD_DISABLE (1 << 23) +#define ARCHDIS 0xff0 /* DMA Remap Engine Policy Control */ +#define DMAR_LCKDN (1 << 31) +#define SPCAPCTRL (1 << 25) +#define L3HIT2PEND_DIS (1 << 20) +#define PRSCAPDIS (1 << 2) +#define GLBIOTLBINV (1 << 1) +#define GLBCTXTINV (1 << 0) + /* Device 0:1.0 PCI configuration space (PCI Express) */
#define BCTRL1 0x3e /* 16bit */ @@ -107,6 +123,8 @@ #define MCHBAR32_OR(x, or) MCHBAR32(x) = (MCHBAR32(x) | (or))
#define BIOS_RESET_CPL 0x5da8 /* 8bit */ +#define GFXVTBAR 0x5400 +#define VTVC0BAR 0x5410
/* Some power MSRs are also represented in MCHBAR */ #define MCH_PKG_POWER_LIMIT_LO 0x59a0 diff --git a/src/northbridge/intel/haswell/northbridge.c b/src/northbridge/intel/haswell/northbridge.c index 32be916..93e711d 100644 --- a/src/northbridge/intel/haswell/northbridge.c +++ b/src/northbridge/intel/haswell/northbridge.c @@ -289,7 +289,7 @@ 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; @@ -331,7 +331,7 @@ * 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; @@ -379,18 +379,31 @@ CONFIG_CHROMEOS_RAMOOPS_RAM_START >> 10, CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE >> 10); #endif + *resource_cnt = index; }
static void mc_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 intel_set_subsystem(device_t dev, unsigned vendor, unsigned device) diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c index a5c2351..03a77d9 100644 --- a/src/southbridge/intel/lynxpoint/lpc.c +++ b/src/southbridge/intel/lynxpoint/lpc.c @@ -51,6 +51,10 @@ { 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); + /* Enable ACPI I/O range decode */ pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
@@ -396,9 +400,15 @@ RCBA32_OR(0x33c8, (1 << 15)); }
-static void enable_hpet(void) +static void enable_hpet(struct device *const dev) { u32 reg32; + 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);
/* Move HPET to default address 0xfed00000 and enable it */ reg32 = RCBA32(HPTC); @@ -570,7 +580,7 @@ isa_dma_init();
/* Initialize the High Precision Event Timers, if present. */ - enable_hpet(); + enable_hpet(dev);
setup_i8259();
diff --git a/src/southbridge/intel/lynxpoint/pch.h b/src/southbridge/intel/lynxpoint/pch.h index af9e954..f14a339 100644 --- a/src/southbridge/intel/lynxpoint/pch.h +++ b/src/southbridge/intel/lynxpoint/pch.h @@ -282,6 +282,8 @@ #define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */ #define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */ #define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[2:0] */ +#define LPC_IBDF 0x6C /* I/O APIC bus/dev/fn */ +#define LPC_HnBDF(n) (0x70 + n * 2) /* HPET n bus/dev/fn */ #define LPC_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */ #define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */ #define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */ @@ -670,6 +672,11 @@ #define PCH_DISABLE_MEI1 (1 << 1) #define PCH_ENABLE_DBDF (1 << 0)
+#define PCH_IOAPIC_PCI_BUS 250 +#define PCH_IOAPIC_PCI_SLOT 31 +#define PCH_HPET_PCI_BUS 250 +#define PCH_HPET_PCI_SLOT 15 + /* ICH7 PMBASE */ #define PM1_STS 0x00 #define WAK_STS (1 << 15)