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 <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91631
Reviewed-by: Alicja Michalska <ahplka19@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
This commit is contained in:
Angel Pons 2026-03-09 21:28:26 +01:00 committed by Matt DeVillier
commit a0be26ef5f
3 changed files with 56 additions and 16 deletions

View file

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

View file

@ -1,10 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <stdint.h>
#include <console/console.h>
#include <cpu/intel/haswell/haswell.h>
#include <device/mmio.h>
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <types.h>
#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();

View file

@ -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 */