Matt DeVillier has uploaded this change for review. ( https://review.coreboot.org/27270
Change subject: soc/intel/skylake: Generate ACPI RMRR table ......................................................................
soc/intel/skylake: Generate ACPI RMRR table
An ACPI RMRR table is requried for IOMMU to work properly with an iGPU (without using passthrough mode), so create one along with the DRHD DMAR table if the iGPU is present and enabled.
Test: build/boot google/chell and purism/librem13v2 with kernel parameter 'intel_iommu=on' but without 'iommu=pt;' observe integrated graphics functional without corruption.
Change-Id: I202fb3eb8618f99d41f3d1c5bbb83b2ec982aca4 Signed-off-by: Matt DeVillier matt.devillier@gmail.com --- M src/soc/intel/skylake/acpi.c M src/soc/intel/skylake/include/soc/systemagent.h M src/soc/intel/skylake/systemagent.c 3 files changed, 72 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/27270/1
diff --git a/src/soc/intel/skylake/acpi.c b/src/soc/intel/skylake/acpi.c index 4ad4831..e0516ab 100644 --- a/src/soc/intel/skylake/acpi.c +++ b/src/soc/intel/skylake/acpi.c @@ -551,15 +551,34 @@ const u32 gfx_vtbar = MCHBAR32(GFXVTBAR) & ~0xfff; const bool gfxvten = MCHBAR32(GFXVTBAR) & 1;
+ const u32 tolud_addr = sa_get_tolud_addr(); + const u32 igd_rmrr_base = tolud_addr - + (sa_get_igd_mem_sz() + sa_get_gtt_mem_sz()); + const u32 igd_rmrr_limit = tolud_addr - 1; + /* iGFX has to be enabled, GFXVTBAR set and in 32-bit space. */ if (igfx_dev && igfx_dev->enabled && gfxvten && gfx_vtbar && !MCHBAR32(GFXVTBAR + 4)) { - const unsigned long tmp = current; + unsigned long tmp = current;
current += acpi_create_dmar_drhd(current, 0, 0, gfx_vtbar); current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
acpi_dmar_drhd_fixup(tmp, current); + + /* + * Add RMRR entry + * Address calculations taken from edk2 reference implementation + */ + if (tolud_addr > 0) { + tmp = current; + + current += acpi_create_dmar_rmrr(current, 0, + igd_rmrr_base, igd_rmrr_limit); + current += acpi_create_dmar_ds_pci(current, 0, + SA_DEV_SLOT_IGD, 0); + acpi_dmar_rmrr_fixup(tmp, current); + } }
struct device *const p2sb_dev = dev_find_slot(0, PCH_DEVFN_P2SB); diff --git a/src/soc/intel/skylake/include/soc/systemagent.h b/src/soc/intel/skylake/include/soc/systemagent.h index 8e53f54..9724b03 100644 --- a/src/soc/intel/skylake/include/soc/systemagent.h +++ b/src/soc/intel/skylake/include/soc/systemagent.h @@ -25,6 +25,12 @@ /* Device 0:0.0 PCI configuration space */
#define EPBAR 0x40 +#define GGC_REG 0x50 +#define GGC_GMS_MASK 0xff00 +#define GGC_GMS_OFST 0x08 +#define GGC_GGMS_MASK 0xc0 +#define GGC_GGMS_OFST 0x06 +#define GGC_GGMS_8MB 0x03 #define DMIBAR 0x68 #define SMRAM 0x88 /* System Management RAM Control */ #define D_OPEN (1 << 6) @@ -47,6 +53,9 @@ #define MCH_DDR_POWER_LIMIT_HI 0x58e4
bool soc_is_vtd_capable(void); +u32 sa_get_tolud_addr(void); +u32 sa_get_igd_mem_sz(void); +u32 sa_get_gtt_mem_sz(void);
static const struct sa_mmio_descriptor soc_vtd_resources[] = { { GFXVTBAR, GFXVT_BASE_ADDRESS, GFXVT_BASE_SIZE, "GFXVTBAR" }, diff --git a/src/soc/intel/skylake/systemagent.c b/src/soc/intel/skylake/systemagent.c index 2c4408fe..3911e80 100644 --- a/src/soc/intel/skylake/systemagent.c +++ b/src/soc/intel/skylake/systemagent.c @@ -36,6 +36,49 @@ !(pci_read_config32(root_dev, CAPID0_A) & VTD_DISABLE); }
+u32 sa_get_tolud_addr(void) +{ + struct device *const root_dev = SA_DEV_ROOT; + + return root_dev ? pci_read_config32(root_dev, TOLUD) & ~(0x01) : 0x0; +} + +u32 sa_get_igd_mem_sz(void) +{ + struct device *const root_dev = SA_DEV_ROOT; + u16 igd_mode; + u32 igd_mem_sz; + + if (!root_dev) + return 0x0; + + igd_mode = (pci_read_config16(root_dev, GGC_REG) & GGC_GMS_MASK) + >> GGC_GMS_OFST; + if (igd_mode < 0xF0) + igd_mem_sz = igd_mode * 32 * (1024) * (1024); + else + igd_mem_sz = 4 * (igd_mode - 0xF0 + 1) * (1024) * (1024); + + return igd_mem_sz; +} + +u32 sa_get_gtt_mem_sz(void) +{ + struct device *const root_dev = SA_DEV_ROOT; + u16 gtt_mode; + u32 gtt_mem_sz = 0; + + if (!root_dev) + return 0x0; + + gtt_mode = (pci_read_config16(root_dev, GGC_REG) & GGC_GGMS_MASK) + >> GGC_GGMS_OFST; + if (gtt_mode <= GGC_GGMS_8MB) + gtt_mem_sz = (1 << gtt_mode) * (1024) * (1024); + + return gtt_mem_sz; +} + /* * SoC implementation *