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.

GFXVTBAR/VTVC0BAR policy registers set to be consistent with
proprietary vendor firmwares on hardware of same platform 
(2 different vendor firmwares compared, found to be identical).

Change-Id: Ib8f2fed9ae08491779e76f7d1ddc1bd3eed45ac7
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/24983
Reviewed-by: Youness Alaoui <snifikino@gmail.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Matt DeVillier 2018-03-04 01:44:15 -06:00 committed by Patrick Georgi
parent 8a6377ec24
commit a51e379eaf
5 changed files with 81 additions and 5 deletions

View File

@ -94,11 +94,39 @@ static void haswell_setup_graphics(void)
MCHBAR32(0x5418) = reg32; 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) void haswell_early_initialization(int chipset_type)
{ {
/* Setup all BARs required for early PCIe and raminit */ /* Setup all BARs required for early PCIe and raminit */
haswell_setup_bars(); haswell_setup_bars();
/* Setup IOMMU BARs */
haswell_setup_iommu();
/* Device Enable: IGD and Mini-HD Audio */ /* Device Enable: IGD and Mini-HD Audio */
pci_write_config32(PCI_DEV(0, 0, 0), DEVEN, pci_write_config32(PCI_DEV(0, 0, 0), DEVEN,
DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN); DEVEN_D0EN | DEVEN_D2EN | DEVEN_D3EN);

View File

@ -35,6 +35,12 @@
#endif #endif
#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */ #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> #include <southbridge/intel/lynxpoint/pch.h>
/* Everything below this line is ignored in the DSDT */ /* Everything below this line is ignored in the DSDT */
@ -88,6 +94,16 @@
#define SKPAD 0xdc /* Scratchpad Data */ #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) */ /* Device 0:1.0 PCI configuration space (PCI Express) */
#define BCTRL1 0x3e /* 16bit */ #define BCTRL1 0x3e /* 16bit */
@ -107,6 +123,8 @@
#define MCHBAR32_OR(x, or) MCHBAR32(x) = (MCHBAR32(x) | (or)) #define MCHBAR32_OR(x, or) MCHBAR32(x) = (MCHBAR32(x) | (or))
#define BIOS_RESET_CPL 0x5da8 /* 8bit */ #define BIOS_RESET_CPL 0x5da8 /* 8bit */
#define GFXVTBAR 0x5400
#define VTVC0BAR 0x5410
/* Some power MSRs are also represented in MCHBAR */ /* Some power MSRs are also represented in MCHBAR */
#define MCH_PKG_POWER_LIMIT_LO 0x59a0 #define MCH_PKG_POWER_LIMIT_LO 0x59a0

View File

@ -290,7 +290,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)); 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 base_k, size_k;
unsigned long touud_k; unsigned long touud_k;
@ -332,7 +332,7 @@ static void mc_add_dram_resources(device_t dev)
* The resource index starts low and should not meet or exceed * The resource index starts low and should not meet or exceed
* PCI_BASE_ADDRESS_0. * PCI_BASE_ADDRESS_0.
*/ */
index = 0; index = *resource_cnt;
/* 0 - > 0xa0000 */ /* 0 - > 0xa0000 */
base_k = 0; base_k = 0;
@ -380,18 +380,31 @@ static void mc_add_dram_resources(device_t dev)
CONFIG_CHROMEOS_RAMOOPS_RAM_START >> 10, CONFIG_CHROMEOS_RAMOOPS_RAM_START >> 10,
CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE >> 10); CONFIG_CHROMEOS_RAMOOPS_RAM_SIZE >> 10);
#endif #endif
*resource_cnt = index;
} }
static void mc_read_resources(device_t dev) 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. */ /* Read standard PCI resources. */
pci_dev_read_resources(dev); pci_dev_read_resources(dev);
/* Add all fixed MMIO resources. */ /* Add all fixed MMIO resources. */
mc_add_fixed_mmio_resources(dev); 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. */ /* 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) static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)

View File

@ -51,6 +51,10 @@ static void pch_enable_ioapic(struct device *dev)
{ {
u32 reg32; 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 */ /* Enable ACPI I/O range decode */
pci_write_config8(dev, ACPI_CNTL, ACPI_EN); pci_write_config8(dev, ACPI_CNTL, ACPI_EN);
@ -396,9 +400,15 @@ static void lpt_lp_pm_init(struct device *dev)
RCBA32_OR(0x33c8, (1 << 15)); RCBA32_OR(0x33c8, (1 << 15));
} }
static void enable_hpet(void) static void enable_hpet(struct device *const dev)
{ {
u32 reg32; 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 */ /* Move HPET to default address 0xfed00000 and enable it */
reg32 = RCBA32(HPTC); reg32 = RCBA32(HPTC);
@ -570,7 +580,7 @@ static void lpc_init(struct device *dev)
isa_dma_init(); isa_dma_init();
/* Initialize the High Precision Event Timers, if present. */ /* Initialize the High Precision Event Timers, if present. */
enable_hpet(); enable_hpet(dev);
setup_i8259(); setup_i8259();

View File

@ -282,6 +282,8 @@ void pch_enable_lpc(void);
#define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */ #define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */
#define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */ #define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */
#define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[2:0] */ #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_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */
#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */ #define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */
#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */ #define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */
@ -670,6 +672,11 @@ void pch_enable_lpc(void);
#define PCH_DISABLE_MEI1 (1 << 1) #define PCH_DISABLE_MEI1 (1 << 1)
#define PCH_ENABLE_DBDF (1 << 0) #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 */ /* ICH7 PMBASE */
#define PM1_STS 0x00 #define PM1_STS 0x00
#define WAK_STS (1 << 15) #define WAK_STS (1 << 15)