From a0be26ef5f9a536f90dfbfadb1f30d4f9f9d2704 Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Mon, 9 Mar 2026 21:28:26 +0100 Subject: [PATCH] nb/intel/haswell: Fix IOMMU early init Intel Document 492662 (Haswell System Agent BIOS Spec), Rev 1.6.0 states that `ARCHDIS` (VT engine BAR, offset 0xff0) has to be written fully, as well as several other things that were not done properly in coreboot. As these steps are Haswell-specific, introduce two helper functions to test if the CPU is Haswell or Broadwell. Intel Document 535094 (Broadwell BIOS Spec), Rev 2.2.0 contains the same steps for Broadwell. To permit unifying Haswell and Broadwell, implement the Broadwell steps as well. Change-Id: I077e064754720d9f9f627733c954712a2b24b5b7 Signed-off-by: Angel Pons Reviewed-on: https://review.coreboot.org/c/coreboot/+/91631 Reviewed-by: Alicja Michalska Tested-by: build bot (Jenkins) Reviewed-by: Matt DeVillier --- src/cpu/intel/haswell/haswell.h | 23 +++++++++++ src/northbridge/intel/haswell/early_init.c | 46 ++++++++++++++++------ src/northbridge/intel/haswell/haswell.h | 3 -- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index 1625329b37..b8cc98a570 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -192,4 +192,27 @@ static inline bool haswell_is_ult(void) return CONFIG(INTEL_LYNXPOINT_LP); } +static inline bool cpu_is_haswell(void) +{ + switch (cpu_family_model()) { + case HASWELL_FAMILY_TRAD: + case HASWELL_FAMILY_ULT: + case CRYSTALWELL_FAMILY: + return true; + default: + return false; + } +} + +static inline bool cpu_is_broadwell(void) +{ + switch (cpu_family_model()) { + case BROADWELL_FAMILY_TRAD: + case BROADWELL_FAMILY_ULT: + return true; + default: + return false; + } +} + #endif diff --git a/src/northbridge/intel/haswell/early_init.c b/src/northbridge/intel/haswell/early_init.c index d52a9d1b85..1b5059adb8 100644 --- a/src/northbridge/intel/haswell/early_init.c +++ b/src/northbridge/intel/haswell/early_init.c @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#include #include +#include #include #include #include +#include #include "haswell.h" @@ -80,10 +81,9 @@ static void haswell_setup_misc(void) mchbar_write32(INTRDIRCTL, reg32); } -static void haswell_setup_iommu(void) +static void northbridge_setup_iommu(void) { const u32 capid0_a = pci_read_config32(HOST_BRIDGE, CAPID0_A); - if (capid0_a & VTD_DISABLE) return; @@ -93,17 +93,37 @@ static void haswell_setup_iommu(void) mchbar_write32(VTVC0BAR + 4, VTVC0_BASE_ADDRESS >> 32); mchbar_write32(VTVC0BAR + 0, VTVC0_BASE_ADDRESS | 1); - /* Set L3HIT2PEND_DIS, lock GFXVTBAR policy config registers */ - u32 reg32; - reg32 = read32p(GFXVT_BASE_ADDRESS + ARCHDIS); - write32p(GFXVT_BASE_ADDRESS + ARCHDIS, reg32 | DMAR_LCKDN | L3HIT2PEND_DIS); + if (cpu_is_haswell()) { + /* + * Intel Document 492662 (Haswell System Agent BIOS Spec), Rev 1.6.0 + * Section 11.3 - DMA Remapping Engine Configuration + */ + const u32 gfxvt_archdis = 0x02100000 | DMAR_LCKDN; + write32p(GFXVT_BASE_ADDRESS + ARCHDIS, gfxvt_archdis); - /* Clear SPCAPCTRL */ - reg32 = read32p(VTVC0_BASE_ADDRESS + ARCHDIS) & ~SPCAPCTRL; + clrsetbits32p(VTVC0_BASE_ADDRESS + 0xf04, 0xf << 15, 1 << 15); - /* Set GLBIOTLBINV, GLBCTXTINV; lock VTVC0BAR policy config registers */ - write32p(VTVC0_BASE_ADDRESS + ARCHDIS, - reg32 | DMAR_LCKDN | GLBIOTLBINV | GLBCTXTINV); + u32 vtvc0_archdis = 0x000a5003 | DMAR_LCKDN; + if (pci_read_config16(PCI_DEV(0, 2, 0), PCI_DEVICE_ID) == 0xffff) { + vtvc0_archdis |= SPCAPCTRL; + } + write32p(VTVC0_BASE_ADDRESS + ARCHDIS, vtvc0_archdis); + } + if (cpu_is_broadwell()) { + /* + * Intel Document 535094 (Broadwell BIOS Spec), Rev 2.2.0 + * Section 17.3 - DMA Remapping Engine Configuration + */ + + /* TODO: For steppings <= D0 (pre-production), also clear bit 0 */ + setbits32p(GFXVT_BASE_ADDRESS + ARCHDIS, DMAR_LCKDN | PRSCAPDIS); + + write32p(GFXVT_BASE_ADDRESS + 0x100, 0x50a); + + clrsetbits32p(VTVC0_BASE_ADDRESS + 0xf04, 0xf << 15, 1 << 15); + + setbits32p(VTVC0_BASE_ADDRESS + ARCHDIS, DMAR_LCKDN); + } } void haswell_early_initialization(void) @@ -112,7 +132,7 @@ void haswell_early_initialization(void) haswell_setup_bars(); /* Setup IOMMU BARs */ - haswell_setup_iommu(); + northbridge_setup_iommu(); if (!CONFIG(INTEL_LYNXPOINT_LP)) northbridge_setup_peg(); diff --git a/src/northbridge/intel/haswell/haswell.h b/src/northbridge/intel/haswell/haswell.h index aeedd421e1..4d2da01788 100644 --- a/src/northbridge/intel/haswell/haswell.h +++ b/src/northbridge/intel/haswell/haswell.h @@ -28,10 +28,7 @@ #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) void mb_late_romstage_setup(void); /* optional */