[coreboot] New patch to review for coreboot: 8341513 acpi: Add support for DMAR tables (Intel IOMMU support)

Patrick Georgi (patrick@georgi-clan.de) gerrit at coreboot.org
Tue Oct 30 10:34:10 CET 2012


Patrick Georgi (patrick at georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1654

-gerrit

commit 834151336c710800a419e967b53e2dbda9b13f68
Author: Patrick Georgi <patrick.georgi at secunet.com>
Date:   Tue Sep 11 15:21:01 2012 +0200

    acpi: Add support for DMAR tables (Intel IOMMU support)
    
    Adds lowlevel handling of DMAR tables for use by mainboards'
    ACPI code. Not much automagic (yet).
    
    Change-Id: Ia86e950dfcc5b9994202ec0e2f6d9a2912c74ad8
    Signed-off-by: Patrick Georgi <patrick.georgi at secunet.com>
---
 src/arch/x86/boot/acpi.c         | 65 ++++++++++++++++++++++++++++++++++++++++
 src/arch/x86/include/arch/acpi.h | 57 +++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)

diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c
index 9881ffe..447e7da 100644
--- a/src/arch/x86/boot/acpi.c
+++ b/src/arch/x86/boot/acpi.c
@@ -334,6 +334,71 @@ void acpi_create_srat(acpi_srat_t *srat)
 	header->checksum = acpi_checksum((void *)srat, header->length);
 }
 
+unsigned long __attribute__((weak)) acpi_fill_dmar(unsigned long current)
+{
+	return current;
+}
+
+void acpi_create_dmar(acpi_dmar_t *dmar)
+{
+	acpi_header_t *header = &(dmar->header);
+	unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
+
+	memset((void *)dmar, 0, sizeof(acpi_dmar_t));
+
+	/* Fill out header fields. */
+	memcpy(header->signature, "DMAR", 4);
+	memcpy(header->oem_id, OEM_ID, 6);
+	memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+	memcpy(header->asl_compiler_id, ASLC, 4);
+
+	header->length = sizeof(acpi_dmar_t);
+	header->revision = 1;
+
+	dmar->host_address_width = 40 - 1; /* FIXME: == MTRR size? */
+	dmar->flags = 0;
+
+	current = acpi_fill_dmar(current);
+
+	/* (Re)calculate length and checksum. */
+	header->length = current - (unsigned long)dmar;
+	header->checksum = acpi_checksum((void *)dmar, header->length);
+}
+
+unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
+	u16 segment, u32 bar)
+{
+	dmar_entry_t *drhd = (dmar_entry_t *)current;
+	memset(drhd, 0, sizeof(*drhd));
+	drhd->type = DMAR_DRHD;
+	drhd->length = sizeof(*drhd); /* will be fixed up later */
+	drhd->flags = flags;
+	drhd->segment = segment;
+	drhd->bar = bar;
+
+	return drhd->length;
+}
+
+void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
+{
+	dmar_entry_t *drhd = (dmar_entry_t *)base;
+	drhd->length = current - base;
+}
+
+unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
+	u8 dev, u8 fn)
+{
+	dev_scope_t *ds = (dev_scope_t *)current;
+	memset(ds, 0, sizeof(*ds));
+	ds->type = SCOPE_PCI_ENDPOINT;
+	ds->length = sizeof(*ds) + 2; /* we don't support longer paths yet */
+	ds->start_bus = segment;
+	ds->path[0].dev = dev;
+	ds->path[0].fn = fn;
+
+	return ds->length; 
+}
+
 /* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
 void acpi_create_slit(acpi_slit_t *slit)
 {
diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h
index 0b2cbf4..b39e8c0 100644
--- a/src/arch/x86/include/arch/acpi.h
+++ b/src/arch/x86/include/arch/acpi.h
@@ -187,6 +187,54 @@ typedef struct acpi_madt {
 	u32 flags;			/* Multiple APIC flags */
 } __attribute__ ((packed)) acpi_madt_t;
 
+enum dev_scope_type {
+	SCOPE_PCI_ENDPOINT = 1,
+	SCOPE_PCI_SUB = 2,
+	SCOPE_IOAPIC = 3,
+	SCOPE_MSI_HPET = 4
+};
+
+typedef struct dev_scope {
+	u8 type;
+	u8 length;
+	u8 reserved[2];
+	u8 enumeration;
+	u8 start_bus;
+	struct {
+		u8 dev;
+		u8 fn;
+	} __attribute__((packed)) path[0];
+} __attribute__ ((packed)) dev_scope_t;
+
+enum dmar_type {
+	DMAR_DRHD = 0,
+	DMAR_RMRR = 1,
+	DMAR_ATSR = 2,
+	DMAR_RHSA = 3
+};
+
+enum {
+	DRHD_INCLUDE_PCI_ALL = 1
+};
+
+typedef struct dmar_entry {
+	u16 type;
+	u16 length;
+	u8 flags;
+	u8 reserved;
+	u16 segment;
+	u64 bar;
+} __attribute__ ((packed)) dmar_entry_t;
+
+/* DMAR (DMA Remapping Reporting Structure) */
+typedef struct acpi_dmar {
+	struct acpi_table_header header;
+	u8 host_address_width;
+	u8 flags;
+	u8 reserved[10];
+	dmar_entry_t structure[0];
+} __attribute__ ((packed)) acpi_dmar_t;
+
 /* MADT: APIC Structure Types */
 /* TODO: Convert to ALLCAPS. */
 enum acpi_apic_types {
@@ -483,6 +531,15 @@ void acpi_create_mcfg(acpi_mcfg_t *mcfg);
 
 void acpi_create_facs(acpi_facs_t *facs);
 
+void acpi_create_dmar(acpi_dmar_t *dmar);
+unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
+				    u16 segment, u32 bar);
+void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current);
+unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
+					   u8 dev, u8 fn);
+
+unsigned long acpi_fill_dmar(unsigned long);
+
 #if CONFIG_HAVE_ACPI_SLIC
 unsigned long acpi_create_slic(unsigned long current);
 #endif




More information about the coreboot mailing list