soc/intel/*: Disable InternalGfx w/o iGPU to prevent FSP-M/S crash

Add verification to ensure that the integrated GPU is available,
avoiding crashes in FSP-M and FSP-S. The problem was first identified
on Skylake systems where the iGPU is missing or disabled, particularly
when VT-D is enabled, which can cause FSP-S to hang during boot.
Enabling SGX hides the issue, but it also leads to unstable
virtualization.

Apply the fix to Alderlake, Cannonlake, and Tigerlake SoCs in addition
to Skylake.

TEST=Build and boot to OS (Windows, Proxmox). Check to verify
functions work. (Skylake H110 + Xeon E3-1245 V5, E3-1260L V5,
i7-6700K, i3-7100)

Change-Id: I394f46ed5a277218a8dd587705eaecabe59fd110
Signed-off-by: Ulysse Ballesteros <ulysseballesteros@gmail.com>
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89821
Reviewed-by: Walter Sonius <walterav1984@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Alicja Michalska <ahplka19@gmail.com>
This commit is contained in:
Ulysse Ballesteros 2025-10-30 11:14:04 +01:00 committed by Matt DeVillier
commit a974b7668e
5 changed files with 62 additions and 15 deletions

View file

@ -2,6 +2,7 @@
#include <assert.h>
#include <console/console.h>
#include <device/pci.h>
#include <cpu/x86/msr.h>
#include <cpu/intel/common/common.h>
#include <cpu/intel/cpu_ids.h>
@ -152,9 +153,19 @@ static void fill_fspm_igd_params(FSP_M_CONFIG *m_cfg,
[DDI_PORT_3] = {&m_cfg->DdiPort3Ddc, &m_cfg->DdiPort3Hpd},
[DDI_PORT_4] = {&m_cfg->DdiPort4Ddc, &m_cfg->DdiPort4Hpd},
};
m_cfg->InternalGfx = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD)) && is_devfn_enabled(SA_DEVFN_IGD);
if (m_cfg->InternalGfx) {
bool igd_enabled = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD))
&& is_devfn_enabled(SA_DEVFN_IGD);
/* Probe for no IGD and disable InternalGfx to prevent a crash in FSP-M. */
if (igd_enabled && pci_read_config16(SA_DEV_IGD, PCI_VENDOR_ID) == 0xffff) {
printk(BIOS_ERR, "igd_enabled is set, but IGD is not present. Disabling IGD.\n");
igd_enabled = false;
}
if (igd_enabled) {
/* IGD is enabled, set IGD stolen size to 60MB. */
m_cfg->InternalGfx = 1;
m_cfg->IgdDvmt50PreAlloc = get_uint_option("igd_dvmt_prealloc", IGD_SM_60MB);
m_cfg->ApertureSize = get_uint_option("igd_aperture_size", IGD_AP_SZ_256MB);
/* DP port config */
@ -168,6 +179,7 @@ static void fill_fspm_igd_params(FSP_M_CONFIG *m_cfg,
}
} else {
/* IGD is disabled, skip IGD init in FSP. */
m_cfg->InternalGfx = 0;
m_cfg->IgdDvmt50PreAlloc = 0;
/* DP port config */
m_cfg->DdiPortAConfig = 0;

View file

@ -30,12 +30,16 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
m_cfg->HyperThreading = get_uint_option("hyper_threading", CONFIG(FSP_HYPERTHREADING));
/*
* Probe for no IGD and disable InternalGfx and panel power to prevent a
* crash in FSP-M.
*/
const bool igd_on = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD)) && is_devfn_enabled(SA_DEVFN_IGD);
if (igd_on && pci_read_config16(SA_DEV_IGD, PCI_VENDOR_ID) != 0xffff) {
bool igd_enabled = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD))
&& is_devfn_enabled(SA_DEVFN_IGD);
/* Probe for no IGD and disable InternalGfx and panel power to prevent a crash in FSP-M. */
if (igd_enabled && pci_read_config16(SA_DEV_IGD, PCI_VENDOR_ID) == 0xffff) {
printk(BIOS_ERR, "igd_enabled is set, but IGD is not present. Disabling IGD.\n");
igd_enabled = false;
}
if (igd_enabled) {
/* Set IGD stolen size to 64MB. */
m_cfg->InternalGfx = 1;
m_cfg->IgdDvmt50PreAlloc = get_uint_option("igd_dvmt_prealloc", IGD_SM_64MB);

View file

@ -5,6 +5,7 @@
#include <acpi/acpi.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <fsp/util.h>
#include <gpio.h>
@ -491,7 +492,18 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
/* Enable VT-d and X2APIC */
if (soc_vtd_enabled()) {
params->VtdBaseAddress[0] = GFXVT_BASE_ADDRESS;
/*
* Probe for no IGD and set VtdBaseAddress accordingly to prevent a
* crash in FSP-S.
*/
const struct device *igd_dev = pcidev_path_on_root(SA_DEVFN_IGD);
if (igd_dev && pci_read_config16(igd_dev, PCI_VENDOR_ID) != 0xffff) {
printk(BIOS_DEBUG, "iGPU present - GFXVT_BASE_ADDRESS set\n");
params->VtdBaseAddress[0] = GFXVT_BASE_ADDRESS;
} else {
printk(BIOS_DEBUG, "No iGPU - GFXVT_BASE_ADDRESS disabled\n");
params->VtdBaseAddress[0] = 0;
}
params->VtdBaseAddress[1] = VTVC0_BASE_ADDRESS;
params->X2ApicOptOut = 0;
tconfig->VtdDisable = 0;

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <device/pci.h>
#include <cpu/x86/msr.h>
#include <fsp/util.h>
#include <intelblocks/cpulib.h>
@ -104,7 +105,14 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
static void soc_primary_gfx_config_params(FSP_M_CONFIG *m_cfg,
const struct soc_intel_skylake_config *config)
{
m_cfg->InternalGfx = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD)) && is_devfn_enabled(SA_DEVFN_IGD);
bool igd_enabled = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD))
&& is_devfn_enabled(SA_DEVFN_IGD);
/* Probe for no IGD and disable InternalGfx to prevent a crash in FSP-M. */
if (igd_enabled && pci_read_config16(SA_DEV_IGD, PCI_VENDOR_ID) == 0xffff) {
printk(BIOS_ERR, "igd_enabled is set, but IGD is not present. Disabling IGD.\n");
igd_enabled = false;
}
/*
* If iGPU is enabled, set IGD stolen size to 64MB. The FBC
@ -116,12 +124,13 @@ static void soc_primary_gfx_config_params(FSP_M_CONFIG *m_cfg,
*
* If disabled, don't reserve memory for it.
*/
if (m_cfg->InternalGfx) {
/* IGD is enabled, set IGD stolen size to 64MB. */
if (igd_enabled) {
/* Set IGD stolen size to 64MB. */
m_cfg->InternalGfx = 1;
m_cfg->IgdDvmt50PreAlloc = get_uint_option("igd_dvmt_prealloc", IGD_SM_64MB);
m_cfg->ApertureSize = get_uint_option("igd_aperture_size", IGD_AP_SZ_256MB);
} else {
/* IGD is disabled, skip IGD init in FSP. */
m_cfg->InternalGfx = 0;
m_cfg->IgdDvmt50PreAlloc = 0;
}

View file

@ -6,6 +6,7 @@
#include <cpu/intel/cpu_ids.h>
#include <cpu/x86/msr.h>
#include <device/device.h>
#include <device/pci.h>
#include <fsp/util.h>
#include <gpio.h>
#include <intelblocks/cpulib.h>
@ -27,14 +28,23 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
m_cfg->HyperThreading = get_uint_option("hyper_threading", CONFIG(FSP_HYPERTHREADING));
m_cfg->InternalGfx = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD)) && is_devfn_enabled(SA_DEVFN_IGD);
bool igd_enabled = get_uint_option("igd_enabled", !CONFIG(SOC_INTEL_DISABLE_IGD))
&& is_devfn_enabled(SA_DEVFN_IGD);
if (m_cfg->InternalGfx) {
/* Probe for no IGD and disable InternalGfx to prevent a crash in FSP-M. */
if (igd_enabled && pci_read_config16(SA_DEV_IGD, PCI_VENDOR_ID) == 0xffff) {
printk(BIOS_ERR, "igd_enabled is set, but IGD is not present. Disabling IGD.\n");
igd_enabled = false;
}
if (igd_enabled) {
/* IGD is enabled, set IGD stolen size to 60MB. */
m_cfg->InternalGfx = 1;
m_cfg->IgdDvmt50PreAlloc = get_uint_option("igd_dvmt_prealloc", IGD_SM_60MB);
m_cfg->ApertureSize = get_uint_option("igd_aperture_size", IGD_AP_SZ_256MB);
} else {
/* IGD is disabled, skip IGD init in FSP. */
m_cfg->InternalGfx = 0;
m_cfg->IgdDvmt50PreAlloc = 0;
}