diff options
author | Nico Huber <nico.h@gmx.de> | 2017-09-19 09:36:03 +0200 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2018-04-05 15:52:45 +0000 |
commit | 2afe4dc075fd2cab8d362aa026066a5f53663f2c (patch) | |
tree | b59930db3e2403c531697dbdccb87bdec1ee77e4 | |
parent | db06cf0576192dca4ae4cdb185d311baffc4669c (diff) | |
download | coreboot-2afe4dc075fd2cab8d362aa026066a5f53663f2c.tar.xz |
soc/intel/skylake: 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 (maybe, who knows, the blob is undocu-
mented), advertised to FSP and reserved from the OS.
The new devicetree option `ignore_vtd` allows to retain the old beha-
viour (do whatever pre-set UPD values suggest).
We also let FSP set up distinct BDFs for messages originating from the
I/O-APIC and the HPET.
Change-Id: I77f87c385736615c127143760bbd144f97986b37
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/21597
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Youness Alaoui <snifikino@gmail.com>
-rw-r--r-- | src/soc/intel/skylake/chip.h | 3 | ||||
-rw-r--r-- | src/soc/intel/skylake/chip_fsp20.c | 15 | ||||
-rw-r--r-- | src/soc/intel/skylake/include/soc/iomap.h | 6 | ||||
-rw-r--r-- | src/soc/intel/skylake/include/soc/systemagent.h | 11 | ||||
-rw-r--r-- | src/soc/intel/skylake/romstage/romstage_fsp20.c | 7 | ||||
-rw-r--r-- | src/soc/intel/skylake/romstage/systemagent.c | 23 | ||||
-rw-r--r-- | src/soc/intel/skylake/systemagent.c | 15 |
7 files changed, 80 insertions, 0 deletions
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h index dc7986948f..2523554613 100644 --- a/src/soc/intel/skylake/chip.h +++ b/src/soc/intel/skylake/chip.h @@ -113,6 +113,9 @@ struct soc_intel_skylake_config { /* Estimated maximum platform power in Watts */ u16 psys_pmax; + /* Wether to ignore VT-d support of the SKU */ + int ignore_vtd; + /* * The following fields come from FspUpdVpd.h. * These are configuration values that are passed to FSP during diff --git a/src/soc/intel/skylake/chip_fsp20.c b/src/soc/intel/skylake/chip_fsp20.c index b4fed26d1d..4ac73b57c6 100644 --- a/src/soc/intel/skylake/chip_fsp20.c +++ b/src/soc/intel/skylake/chip_fsp20.c @@ -31,9 +31,11 @@ #include <soc/acpi.h> #include <soc/intel/common/vbt.h> #include <soc/interrupt.h> +#include <soc/iomap.h> #include <soc/irq.h> #include <soc/pci_devs.h> #include <soc/ramstage.h> +#include <soc/systemagent.h> #include <string.h> void soc_init_pre_device(void *chip_info) @@ -326,6 +328,19 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd) /* Set TccActivationOffset */ tconfig->TccActivationOffset = config->tcc_offset; + /* Enable VT-d and X2APIC */ + if (!config->ignore_vtd && soc_is_vtd_capable()) { + params->VtdBaseAddress[0] = GFXVT_BASE_ADDRESS; + params->VtdBaseAddress[1] = VTVC0_BASE_ADDRESS; + params->X2ApicOptOut = 0; + tconfig->VtdDisable = 0; + + params->PchIoApicBdfValid = 1; + params->PchIoApicBusNumber = 250; + params->PchIoApicDeviceNumber = 31; + params->PchIoApicFunctionNumber = 0; + } + soc_irq_settings(params); } diff --git a/src/soc/intel/skylake/include/soc/iomap.h b/src/soc/intel/skylake/include/soc/iomap.h index ac0c78b3c0..37d1d6b270 100644 --- a/src/soc/intel/skylake/include/soc/iomap.h +++ b/src/soc/intel/skylake/include/soc/iomap.h @@ -49,6 +49,12 @@ #define GDXC_BASE_ADDRESS 0xfed84000 #define GDXC_BASE_SIZE 0x1000 +#define GFXVT_BASE_ADDRESS 0xfed90000 +#define GFXVT_BASE_SIZE 0x1000 + +#define VTVC0_BASE_ADDRESS 0xfed91000 +#define VTVC0_BASE_SIZE 0x1000 + #define HPET_BASE_ADDRESS 0xfed00000 #define PCH_PWRM_BASE_ADDRESS 0xfe000000 diff --git a/src/soc/intel/skylake/include/soc/systemagent.h b/src/soc/intel/skylake/include/soc/systemagent.h index d8192a3e75..8e53f54b75 100644 --- a/src/soc/intel/skylake/include/soc/systemagent.h +++ b/src/soc/intel/skylake/include/soc/systemagent.h @@ -32,9 +32,13 @@ #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 GFXVTBAR 0x5400 #define EDRAMBAR 0x5408 +#define VTVC0BAR 0x5410 #define GDXCBAR 0x5420 #define MCH_PKG_POWER_LIMIT_LO 0x59a0 @@ -42,4 +46,11 @@ #define MCH_DDR_POWER_LIMIT_LO 0x58e0 #define MCH_DDR_POWER_LIMIT_HI 0x58e4 +bool soc_is_vtd_capable(void); + +static const struct sa_mmio_descriptor soc_vtd_resources[] = { + { GFXVTBAR, GFXVT_BASE_ADDRESS, GFXVT_BASE_SIZE, "GFXVTBAR" }, + { VTVC0BAR, VTVC0_BASE_ADDRESS, VTVC0_BASE_SIZE, "VTVC0BAR" }, +}; + #endif diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c index 98c78a582e..0b2d276a73 100644 --- a/src/soc/intel/skylake/romstage/romstage_fsp20.c +++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c @@ -234,6 +234,13 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg, m_cfg->PcieRpEnableMask = mask; cpu_flex_override(m_cfg); + + if (!config->ignore_vtd) { + m_cfg->PchHpetBdfValid = 1; + m_cfg->PchHpetBusNumber = 250; + m_cfg->PchHpetDeviceNumber = 15; + m_cfg->PchHpetFunctionNumber = 0; + } } void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) diff --git a/src/soc/intel/skylake/romstage/systemagent.c b/src/soc/intel/skylake/romstage/systemagent.c index a262462a09..0c8e9e7b9e 100644 --- a/src/soc/intel/skylake/romstage/systemagent.c +++ b/src/soc/intel/skylake/romstage/systemagent.c @@ -18,8 +18,28 @@ #include <device/device.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_skylake_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 +60,9 @@ void systemagent_early_init(void) /* 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/skylake/systemagent.c b/src/soc/intel/skylake/systemagent.c index 3227519c3e..1d635834ab 100644 --- a/src/soc/intel/skylake/systemagent.c +++ b/src/soc/intel/skylake/systemagent.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ +#include <arch/io.h> #include <cpu/x86/msr.h> #include <console/console.h> #include <delay.h> @@ -23,7 +24,16 @@ #include <soc/cpu.h> #include <soc/iomap.h> #include <soc/msr.h> +#include <soc/pci_devs.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 @@ -42,9 +52,14 @@ void soc_add_fixed_mmio_resources(struct device *dev, int *index) { GDXCBAR, GDXC_BASE_ADDRESS, GDXC_BASE_SIZE, "GDXCBAR" }, { EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" }, }; + const struct soc_intel_skylake_config *const config = dev->chip_info; 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)); } /* |