John Zhao has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/31917
Change subject: soc/intel/cnl: Generate ACPI DMAR table ......................................................................
soc/intel/cnl: Generate ACPI DMAR table
SoC is detected Vt-d capable. ACPI DMAR table is created and DMA-remapping hardware units entries are programmed. Device scope like IOAPIC and HPET will be added once cnl fsp upd update is available.
Change-Id: I4e1ee5244c67affb13947436d81628c5dc665c9e Signed-off-by: John Zhao john.zhao@intel.com --- M src/soc/intel/cannonlake/acpi.c M src/soc/intel/cannonlake/chip.c M src/soc/intel/cannonlake/chip.h M src/soc/intel/cannonlake/include/soc/iomap.h M src/soc/intel/cannonlake/include/soc/systemagent.h M src/soc/intel/cannonlake/romstage/fsp_params.c M src/soc/intel/cannonlake/romstage/systemagent.c M src/soc/intel/cannonlake/systemagent.c 8 files changed, 157 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/17/31917/1
diff --git a/src/soc/intel/cannonlake/acpi.c b/src/soc/intel/cannonlake/acpi.c index 639f6c6..864cbe9 100644 --- a/src/soc/intel/cannonlake/acpi.c +++ b/src/soc/intel/cannonlake/acpi.c @@ -17,19 +17,22 @@
#include <arch/acpi.h> #include <arch/acpigen.h> -#include <device/mmio.h> #include <arch/smp/mpspec.h> #include <cbmem.h> #include <chip.h> +#include <device/mmio.h> +#include <device/pci_ops.h> #include <ec/google/chromeec/ec.h> #include <intelblocks/cpulib.h> #include <intelblocks/pmclib.h> #include <intelblocks/acpi.h> +#include <intelblocks/p2sb.h> #include <soc/cpu.h> #include <soc/iomap.h> #include <soc/nvs.h> #include <soc/pci_devs.h> #include <soc/pm.h> +#include <soc/systemagent.h> #include <string.h> #include <vendorcode/google/chromeos/gnvs.h> #include <wrdd.h> @@ -285,3 +288,78 @@ { return acpigen_soc_gpio_op("\_SB.PCI0.CTXS", gpio_num); } + +static unsigned long acpi_fill_dmar(unsigned long current) +{ + struct device *const igfx_dev = dev_find_slot(0, SA_DEVFN_IGD); + const u32 gfx_vtbar = MCHBAR32(GFXVTBAR) & ~0xfff; + const bool gfxvten = MCHBAR32(GFXVTBAR) & 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)) { + 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 */ + tmp = current; + + current += acpi_create_dmar_rmrr(current, 0, + sa_get_gsm_base(), sa_get_tolud_base() - 1); + current += acpi_create_dmar_ds_pci(current, 0, 2, 0); + acpi_dmar_rmrr_fixup(tmp, current); + } + + struct device *const p2sb_dev = dev_find_slot(0, PCH_DEVFN_P2SB); + const u32 vtvc0bar = MCHBAR32(VTVC0BAR) & ~0xfff; + const bool vtvc0en = MCHBAR32(VTVC0BAR) & 1; + + /* General VTBAR has to be set and in 32-bit space. */ + if (p2sb_dev && vtvc0bar && vtvc0en && !MCHBAR32(VTVC0BAR + 4)) { + const unsigned long tmp = current; + + /* P2SB may already be hidden. There's no clear rule, when. */ + const u8 p2sb_hidden = + pci_read_config8(p2sb_dev, PCH_P2SB_E0 + 1); + pci_write_config8(p2sb_dev, PCH_P2SB_E0 + 1, 0); + + const u16 ibdf = pci_read_config16(p2sb_dev, PCH_P2SB_IBDF); + const u16 hbdf = pci_read_config16(p2sb_dev, PCH_P2SB_HBDF); + + pci_write_config8(p2sb_dev, PCH_P2SB_E0 + 1, p2sb_hidden); + current += acpi_create_dmar_drhd(current, + DRHD_INCLUDE_PCI_ALL, 0, vtvc0bar); + current += acpi_create_dmar_ds_ioapic(current, + 2, ibdf >> 8, PCI_SLOT(ibdf), PCI_FUNC(ibdf)); + current += acpi_create_dmar_ds_msi_hpet(current, + 0, hbdf >> 8, PCI_SLOT(hbdf), PCI_FUNC(hbdf)); + + acpi_dmar_drhd_fixup(tmp, current); + } + + return current; +} + +unsigned long sa_write_acpi_tables(struct device *dev, + unsigned long current, + struct acpi_rsdp *rsdp) +{ + const struct soc_intel_cannonlake_config *const config = dev->chip_info; + acpi_dmar_t *const dmar = (acpi_dmar_t *)current; + + /* Create DMAR table only if we have Vt-d capability */ + if ((config && config->ignore_vtd) || !soc_is_vtd_capable()) + return current; + + printk(BIOS_DEBUG, "ACPI: * DMAR\n"); + acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar); + current += dmar->header.length; + current = acpi_align_current(current); + acpi_add_table(rsdp, dmar); + + return current; +} diff --git a/src/soc/intel/cannonlake/chip.c b/src/soc/intel/cannonlake/chip.c index 993e7f3..050e026 100644 --- a/src/soc/intel/cannonlake/chip.c +++ b/src/soc/intel/cannonlake/chip.c @@ -196,6 +196,7 @@ .set_resources = &pci_domain_set_resources, .scan_bus = &pci_domain_scan_bus, #if CONFIG(HAVE_ACPI_TABLES) + .write_acpi_tables = &sa_write_acpi_tables, .acpi_name = &soc_acpi_name, #endif }; diff --git a/src/soc/intel/cannonlake/chip.h b/src/soc/intel/cannonlake/chip.h index 3e4bafc..1574b8e 100644 --- a/src/soc/intel/cannonlake/chip.h +++ b/src/soc/intel/cannonlake/chip.h @@ -221,6 +221,9 @@ /* Estimated maximum platform power in Watts */ uint16_t psys_pmax;
+ /* Whether to ignore VT-d support of the SKU */ + int ignore_vtd; + /* Intel Speed Shift Technology */ uint8_t speed_shift_enable; /* Enable VR specific mailbox command diff --git a/src/soc/intel/cannonlake/include/soc/iomap.h b/src/soc/intel/cannonlake/include/soc/iomap.h index ed9b29f..100bd11 100644 --- a/src/soc/intel/cannonlake/include/soc/iomap.h +++ b/src/soc/intel/cannonlake/include/soc/iomap.h @@ -52,6 +52,15 @@ #define EDRAM_BASE_ADDRESS 0xfed80000 #define EDRAM_BASE_SIZE 0x4000
+#define GFXVT_BASE_ADDRESS 0xfed90000 +#define GFXVT_BASE_SIZE 0x1000 + +#define IPUVT_BASE_ADDRESS 0xfed92000 +#define IPUVT_BASE_SIZE 0x1000 + +#define VTVC0_BASE_ADDRESS 0xfed91000 +#define VTVC0_BASE_SIZE 0x1000 + #define REG_BASE_ADDRESS 0xfc000000 #define REG_BASE_SIZE 0x1000
diff --git a/src/soc/intel/cannonlake/include/soc/systemagent.h b/src/soc/intel/cannonlake/include/soc/systemagent.h index da83c38..390bd56 100644 --- a/src/soc/intel/cannonlake/include/soc/systemagent.h +++ b/src/soc/intel/cannonlake/include/soc/systemagent.h @@ -30,10 +30,15 @@ #define D_LCK (1 << 4) #define G_SMRAME (1 << 3) #define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) +#define CAPID0_A 0xe4 +#define VTD_DISABLE (1 << 23)
-#define BIOS_RESET_CPL 0x5da8 -#define EDRAMBAR 0x5408 -#define REGBAR 0x5420 +#define BIOS_RESET_CPL 0x5da8 +#define GFXVTBAR 0x5400 +#define EDRAMBAR 0x5408 +#define IPUVTBAR 0x7884 +#define VTVC0BAR 0x5410 +#define REGBAR 0x5420
#define MCH_PKG_POWER_LIMIT_LO 0x59a0 #define MCH_PKG_POWER_LIMIT_HI 0x59a4 @@ -43,4 +48,11 @@ #define IMRBASE 0x6A40 #define IMRLIMIT 0x6A48
+bool soc_is_vtd_capable(void); + +static const struct sa_mmio_descriptor soc_vtd_resources[] = { + { GFXVTBAR, GFXVT_BASE_ADDRESS, GFXVT_BASE_SIZE, "GFXVTBAR" }, + { IPUVTBAR, IPUVT_BASE_ADDRESS, IPUVT_BASE_SIZE, "IPUVTBAR" }, + { VTVC0BAR, VTVC0_BASE_ADDRESS, VTVC0_BASE_SIZE, "VTVC0BAR" }, +}; #endif diff --git a/src/soc/intel/cannonlake/romstage/fsp_params.c b/src/soc/intel/cannonlake/romstage/fsp_params.c index 5597c4f..04a24a1 100644 --- a/src/soc/intel/cannonlake/romstage/fsp_params.c +++ b/src/soc/intel/cannonlake/romstage/fsp_params.c @@ -98,6 +98,7 @@ assert(dev != NULL); const config_t *config = dev->chip_info; FSP_M_CONFIG *m_cfg = &mupd->FspmConfig; + FSP_M_TEST_CONFIG *t_cfg = &mupd->FspmTestConfig;
soc_memory_init_params(m_cfg, config);
@@ -109,6 +110,15 @@ /* Set debug probe type */ m_cfg->PlatformDebugConsent = config->DebugConsent;
+ /* Enable VT-d and X2APIC */ + if (!config->ignore_vtd) { + m_cfg->VtdBaseAddress[0] = GFXVT_BASE_ADDRESS; + m_cfg->VtdBaseAddress[1] = IPUVT_BASE_ADDRESS; + m_cfg->VtdBaseAddress[2] = VTVC0_BASE_ADDRESS; + m_cfg->X2ApicOptOut = 0; + t_cfg->VtdDisable = 0; + } + mainboard_memory_init_params(mupd); }
diff --git a/src/soc/intel/cannonlake/romstage/systemagent.c b/src/soc/intel/cannonlake/romstage/systemagent.c index 61db22e..6fb3917 100644 --- a/src/soc/intel/cannonlake/romstage/systemagent.c +++ b/src/soc/intel/cannonlake/romstage/systemagent.c @@ -16,10 +16,31 @@ */
#include <device/device.h> +#include <device/pci_ops.h> #include <intelblocks/systemagent.h> #include <soc/iomap.h> +#include <soc/pci_devs.h> #include <soc/romstage.h> #include <soc/systemagent.h> +#include "chip.h" + +static void systemagent_vtd_init(void) +{ + const struct device *const dev = dev_find_slot(0, SA_DEVFN_ROOT); + const struct soc_intel_cannonlake_config *config = NULL; + + if (dev) + config = dev->chip_info; + if (config && config->ignore_vtd) + return; + + const bool vtd_capable = + !(pci_read_config32(SA_DEV_ROOT, CAPID0_A) & VTD_DISABLE); + if (!vtd_capable) + return; + + sa_set_mch_bar(soc_vtd_resources, ARRAY_SIZE(soc_vtd_resources)); +}
void systemagent_early_init(void) { @@ -40,6 +61,9 @@ /* Set Fixed MMIO address into MCH base address */ sa_set_mch_bar(soc_fixed_mch_resources, ARRAY_SIZE(soc_fixed_mch_resources)); + + systemagent_vtd_init(); + /* Enable PAM registers */ enable_pam_region(); } diff --git a/src/soc/intel/cannonlake/systemagent.c b/src/soc/intel/cannonlake/systemagent.c index 9c8d761..4ff4c1c 100644 --- a/src/soc/intel/cannonlake/systemagent.c +++ b/src/soc/intel/cannonlake/systemagent.c @@ -18,10 +18,19 @@ #include <device/device.h> #include <delay.h> #include <device/pci.h> +#include <device/pci_ops.h> #include <intelblocks/systemagent.h> #include <soc/cpu.h> #include <soc/iomap.h> #include <soc/systemagent.h> +#include "chip.h" + +bool soc_is_vtd_capable(void) +{ + struct device *const root_dev = SA_DEV_ROOT; + return root_dev && + !(pci_read_config32(root_dev, CAPID0_A) & VTD_DISABLE); +}
/* * SoC implementation @@ -31,6 +40,8 @@ */ void soc_add_fixed_mmio_resources(struct device *dev, int *index) { + const struct soc_intel_cannonlake_config *const config = dev->chip_info; + static const struct sa_mmio_descriptor soc_fixed_resources[] = { { PCIEXBAR, CONFIG_MMCONF_BASE_ADDRESS, CONFIG_SA_PCIEX_LENGTH, "PCIEXBAR" }, @@ -54,6 +65,11 @@
sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources, ARRAY_SIZE(soc_fixed_resources)); + + if (!(config && config->ignore_vtd) && soc_is_vtd_capable()) { + sa_add_fixed_mmio_resources(dev, index, soc_vtd_resources, + ARRAY_SIZE(soc_vtd_resources)); + } }
/*