[coreboot-gerrit] Change in coreboot[master]: soc/intel/skylake: Generate ACPI DMAR table

Youness Alaoui (Code Review) gerrit at coreboot.org
Sat Feb 10 01:49:32 CET 2018


Youness Alaoui has uploaded this change for review. ( https://review.coreboot.org/23681


Change subject: soc/intel/skylake: Generate ACPI DMAR table
......................................................................

soc/intel/skylake: Generate ACPI DMAR table

The DMAR ACPI table gets added if VT-d is supported and if
IOMMU is enabled and properly configured.

This code was influenced by Nico Huber's implementation [1].

[1] https://review.coreboot.org/#/c/coreboot/+/21588/

Change-Id: Iea48a349d60bdd2e7d3bc74b4e1036b050d2ae71
Signed-off-by: Youness Alaoui <youness.alaoui at puri.sm>
---
M src/soc/intel/skylake/acpi.c
M src/soc/intel/skylake/chip.c
M src/soc/intel/skylake/chip_fsp20.c
M src/soc/intel/skylake/include/soc/acpi.h
M src/soc/intel/skylake/include/soc/p2sb.h
M src/soc/intel/skylake/include/soc/systemagent.h
6 files changed, 79 insertions(+), 0 deletions(-)



  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/81/23681/1

diff --git a/src/soc/intel/skylake/acpi.c b/src/soc/intel/skylake/acpi.c
index a0be5f5..42c7350 100644
--- a/src/soc/intel/skylake/acpi.c
+++ b/src/soc/intel/skylake/acpi.c
@@ -39,9 +39,11 @@
 #include <soc/cpu.h>
 #include <soc/iomap.h>
 #include <soc/msr.h>
+#include <soc/p2sb.h>
 #include <soc/pci_devs.h>
 #include <soc/pm.h>
 #include <soc/ramstage.h>
+#include <soc/systemagent.h>
 #include <string.h>
 #include <types.h>
 #include <vendorcode/google/chromeos/gnvs.h>
@@ -341,6 +343,51 @@
 	fadt->x_gpe1_blk.addrh = 0x0;
 }
 
+static unsigned long acpi_fill_dmar(unsigned long current)
+{
+	struct device *const igfx_dev = dev_find_slot(0, SA_DEVFN_IGD);
+	struct device *const p2sb_dev = dev_find_slot(0, PCH_DEVFN_P2SB);
+	const u32 gfx_vtbar = MCHBAR32(IOMMU1BAR) & ~0xfff;
+	const u32 vtdpvc0_bar = MCHBAR32(IOMMU2BAR) & ~0xfff;
+
+	/* iGFX has to be enabled, GFXVTBAR set and in 32-bit space. */
+	if (igfx_dev && igfx_dev->enabled &&
+		gfx_vtbar && !MCHBAR32(IOMMU1BAR + 4)) {
+		const unsigned long tmp = current;
+
+		current += acpi_create_dmar_drhd(current, 0, 0, gfx_vtbar);
+		current += acpi_create_dmar_drhd_ds_pci(current, 0, 2, 0);
+		acpi_dmar_drhd_fixup(tmp, current);
+	}
+
+
+	/* General VTBAR has to be set and in 32-bit space. */
+	if (p2sb_dev && vtdpvc0_bar && !MCHBAR32(IOMMU2BAR + 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, vtdpvc0_bar);
+		current += acpi_create_dmar_drhd_ds_ioapic(current,
+			2, ibdf >> 8, PCI_SLOT(ibdf), PCI_FUNC(ibdf));
+		current += acpi_create_dmar_drhd_ds_msi_hpet(current,
+			0, hbdf >> 8, PCI_SLOT(hbdf), PCI_FUNC(hbdf));
+
+		acpi_dmar_drhd_fixup(tmp, current);
+	}
+
+	return current;
+}
+
 static void generate_c_state_entries(int s0ix_enable, int max_cstate)
 {
 
@@ -566,6 +613,27 @@
 	return acpi_align_current(current);
 }
 
+unsigned long northbridge_write_acpi_tables(device_t device,
+					     unsigned long current,
+					     struct acpi_rsdp *rsdp)
+{
+	acpi_dmar_t *const dmar = (acpi_dmar_t *) current;
+	struct device *const root_dev = dev_find_slot(0, SA_DEVFN_ROOT);
+
+	/* Create DMAR table only if we have VT-d capability. */
+	if (!root_dev || pci_read_config32(root_dev, CAPID0_A) & VTDD)
+		return current;
+
+	printk(BIOS_DEBUG, "ACPI:    * DMAR\n");
+
+	acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
+	if (dmar->header.length > sizeof(acpi_dmar_t)) {
+		current += dmar->header.length;
+		acpi_add_table(rsdp, dmar);
+	}
+	return acpi_align_current(current);
+}
+
 void southbridge_inject_dsdt(device_t device)
 {
 	global_nvs_t *gnvs;
diff --git a/src/soc/intel/skylake/chip.c b/src/soc/intel/skylake/chip.c
index f60c08d..f2fd9fe 100644
--- a/src/soc/intel/skylake/chip.c
+++ b/src/soc/intel/skylake/chip.c
@@ -49,6 +49,7 @@
 	.scan_bus         = &pci_domain_scan_bus,
 	.ops_pci_bus      = &pci_bus_default_ops,
 #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+	.write_acpi_tables	= &northbridge_write_acpi_tables,
 	.acpi_name        = &soc_acpi_name,
 #endif
 };
diff --git a/src/soc/intel/skylake/chip_fsp20.c b/src/soc/intel/skylake/chip_fsp20.c
index 3bc66b2..abfb049 100644
--- a/src/soc/intel/skylake/chip_fsp20.c
+++ b/src/soc/intel/skylake/chip_fsp20.c
@@ -57,6 +57,7 @@
 	.scan_bus         = &pci_domain_scan_bus,
 	.ops_pci_bus      = &pci_bus_default_ops,
 #if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+	.write_acpi_tables	= &northbridge_write_acpi_tables,
 	.acpi_name        = &soc_acpi_name,
 #endif
 };
diff --git a/src/soc/intel/skylake/include/soc/acpi.h b/src/soc/intel/skylake/include/soc/acpi.h
index b0d2194..d9524e6 100644
--- a/src/soc/intel/skylake/include/soc/acpi.h
+++ b/src/soc/intel/skylake/include/soc/acpi.h
@@ -32,5 +32,7 @@
 void southbridge_inject_dsdt(device_t device);
 unsigned long southbridge_write_acpi_tables(device_t device,
 	unsigned long current, struct acpi_rsdp *rsdp);
+unsigned long northbridge_write_acpi_tables(device_t device,
+	unsigned long current, struct acpi_rsdp *rsdp);
 
 #endif /* _SOC_ACPI_H_ */
diff --git a/src/soc/intel/skylake/include/soc/p2sb.h b/src/soc/intel/skylake/include/soc/p2sb.h
index d846dfc..9fb2653 100644
--- a/src/soc/intel/skylake/include/soc/p2sb.h
+++ b/src/soc/intel/skylake/include/soc/p2sb.h
@@ -19,6 +19,9 @@
 #define HPTC_OFFSET		0x60
 #define HPTC_ADDR_ENABLE_BIT	(1 << 7)
 
+#define PCH_P2SB_IBDF		0x6C
+#define PCH_P2SB_HBDF		0x70
+
 #define PCH_P2SB_EPMASK0		0xB0
 #define PCH_P2SB_EPMASK(mask_number)	(PCH_P2SB_EPMASK0 + ((mask_number) * 4))
 
diff --git a/src/soc/intel/skylake/include/soc/systemagent.h b/src/soc/intel/skylake/include/soc/systemagent.h
index d8192a3..54ff121 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	0x94
+#define  VTDD		(1 << 23)
 
 #define BIOS_RESET_CPL		0x5da8
 #define EDRAMBAR		0x5408
+#define IOMMU1BAR		0x5400
+#define IOMMU2BAR		0x5410
 #define GDXCBAR			0x5420
 
 #define MCH_PKG_POWER_LIMIT_LO	0x59a0

-- 
To view, visit https://review.coreboot.org/23681
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iea48a349d60bdd2e7d3bc74b4e1036b050d2ae71
Gerrit-Change-Number: 23681
Gerrit-PatchSet: 1
Gerrit-Owner: Youness Alaoui <snifikino at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.coreboot.org/pipermail/coreboot-gerrit/attachments/20180210/a41d7176/attachment-0001.html>


More information about the coreboot-gerrit mailing list