Werner Zeh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/30990
Change subject: soc/apollolake: Add generation of DMAR table ......................................................................
soc/apollolake: Add generation of DMAR table
Generate DMAR table if VTd feature is enabled.
Change-Id: Ie3683a2f3578c141c691b2268e32f27ba2e772fa Signed-off-by: Werner Zeh werner.zeh@siemens.com --- M src/soc/intel/apollolake/acpi.c M src/soc/intel/apollolake/include/soc/systemagent.h M src/soc/intel/common/block/include/intelblocks/p2sb.h 3 files changed, 93 insertions(+), 3 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/90/30990/1
diff --git a/src/soc/intel/apollolake/acpi.c b/src/soc/intel/apollolake/acpi.c index 0c4ff81..06ebf6c 100644 --- a/src/soc/intel/apollolake/acpi.c +++ b/src/soc/intel/apollolake/acpi.c @@ -2,7 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2016 Intel Corp. - * Copyright (C) 2017 Siemens AG + * Copyright (C) 2017-2018 Siemens AG * (Written by Lance Zhao lijian.zhao@intel.com for Intel Corp.) * * This program is free software; you can redistribute it and/or modify @@ -20,16 +20,19 @@ #include <arch/acpigen.h> #include <arch/io.h> #include <arch/smp/mpspec.h> +#include <device/pci_ops.h> #include <cbmem.h> #include <cpu/x86/smm.h> #include <gpio.h> #include <intelblocks/acpi.h> #include <intelblocks/pmclib.h> #include <intelblocks/sgx.h> +#include <intelblocks/p2sb.h> #include <soc/iomap.h> #include <soc/pm.h> #include <soc/nvs.h> #include <soc/pci_devs.h> +#include <soc/systemagent.h> #include <string.h> #include "chip.h"
@@ -178,6 +181,82 @@ fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0; }
+static unsigned long soc_fill_dmar(unsigned long current) +{ + struct device *const igfx_dev = dev_find_slot(0, SA_DEVFN_IGD); + uint32_t gfxvtbar = MCHBAR32(GFXVTBAR) & VTBAR_MASK; + uint32_t defvtbar = MCHBAR32(DEFVTBAR) & VTBAR_MASK; + bool gfxvten = MCHBAR32(GFXVTBAR) & VTBAR_ENABLED; + bool defvten = MCHBAR32(DEFVTBAR) & VTBAR_ENABLED; + unsigned long tmp; + + /* IGD has to be enabled, GFXVTBAR set and enabled as well as allocated + in 32-bit space. */ + if (igfx_dev && igfx_dev->enabled && gfxvtbar && gfxvten + && !MCHBAR32(GFXVTBAR + 4)) { + tmp = current; + + current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar); + 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); + } + + /* DEFVTBAR has to be set, enabled, and allocated in 32-bit space. */ + if (defvtbar && defvten && !MCHBAR32(DEFVTBAR + 4)) { + tmp = current; + /* + * P2SB may already be hidden. There's no clear rule, when. + * It is needed to get bus, device and function for IOAPIC and + * HPET device which is stored in P2SB device. So unhide it to + * get the info and hide it again when done. + */ + p2sb_unhide(); + struct device *p2sb_dev = dev_find_slot(0, PCH_DEVFN_P2SB); + uint16_t ibdf = pci_read_config16(p2sb_dev, PCH_P2SB_IBDF); + uint16_t hbdf = pci_read_config16(p2sb_dev, PCH_P2SB_HBDF); + /* Now that it is not needed any more hide P2SB device again. */ + p2sb_hide(); + + current += acpi_create_dmar_drhd(current, + DRHD_INCLUDE_PCI_ALL, 0, defvtbar); + 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 *const dev, + unsigned long current, + struct acpi_rsdp *const rsdp) +{ + acpi_dmar_t *const dmar = (acpi_dmar_t *)current; + + /* Create DMAR table only if virtualization is enabled */ + if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE) || + !(MCHBAR32(DEFVTBAR) & VTBAR_ENABLED)) + return current; + + printk(BIOS_DEBUG, "ACPI: * DMAR\n"); + acpi_create_dmar(dmar, DMAR_INTR_REMAP, soc_fill_dmar); + current += dmar->header.length; + current = acpi_align_current(current); + acpi_add_table(rsdp, dmar); + current = acpi_align_current(current); + + return current; +} + void soc_power_states_generation(int core_id, int cores_per_package) { /* Generate P-state tables */ diff --git a/src/soc/intel/apollolake/include/soc/systemagent.h b/src/soc/intel/apollolake/include/soc/systemagent.h index fe9c15f..55fdccd 100644 --- a/src/soc/intel/apollolake/include/soc/systemagent.h +++ b/src/soc/intel/apollolake/include/soc/systemagent.h @@ -3,6 +3,7 @@ * * Copyright (C) 2015 Intel Corp. * (Written by Andrey Petrov andrey.petrov@intel.com for Intel Corp.) + * Copyright (C) 2018 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,5 +29,12 @@ #define PCODE_INIT_DONE (1 << 8) #define MCHBAR_RAPL_PPL 0x70A8 #define CORE_DISABLE_MASK 0x7168 +#define CAPID0_A 0xE4 +#define VTD_DISABLE (1 << 23) +#define DEFVTBAR 0x6c80 +#define GFXVTBAR 0x6c88 +#define VTBAR_ENABLED 0x01 +#define VTBAR_MASK 0xfffff000 +#define VTBAR_SIZE 0x1000
#endif /* SOC_APOLLOLAKE_SYSTEMAGENT_H */ diff --git a/src/soc/intel/common/block/include/intelblocks/p2sb.h b/src/soc/intel/common/block/include/intelblocks/p2sb.h index e5c1f3e..22ab140 100644 --- a/src/soc/intel/common/block/include/intelblocks/p2sb.h +++ b/src/soc/intel/common/block/include/intelblocks/p2sb.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2017-2018 Intel Corporation. + * Copyright (C) 2018 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,8 +20,10 @@ #include <stddef.h> #include <stdint.h>
-#define PCH_P2SB_E0 0xe0 -#define P2SB_E0_MASKLOCK (1 << 1) +#define PCH_P2SB_E0 0xe0 +#define P2SB_E0_MASKLOCK (1 << 1) +#define PCH_P2SB_IBDF 0x6c +#define PCH_P2SB_HBDF 0x70
enum { P2SB_EP_MASK_0_REG,