[coreboot-gerrit] Patch set updated for coreboot: nb/amd/pi/00730F01: Add initial native IVRS support

Philipp Deppenwiese (zaolin.daisuki@googlemail.com) gerrit at coreboot.org
Tue Jul 5 17:00:48 CEST 2016


Philipp Deppenwiese (zaolin.daisuki at googlemail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15164

-gerrit

commit d1f414137b19558edc2ea640808c7d1d98938732
Author: Timothy Pearson <tpearson at raptorengineering.com>
Date:   Mon Jun 13 13:48:58 2016 -0500

    nb/amd/pi/00730F01: Add initial native IVRS support
    
    Change-Id: I1ae789f75363435accd14a1b556e1570f43f94c4
    Signed-off-by: Timothy Pearson <tpearson at raptorengineering.com>
---
 src/mainboard/amd/olivehillplus/acpi_tables.c |   9 ++
 src/mainboard/pcengines/apu2/acpi_tables.c    |   9 ++
 src/northbridge/amd/pi/00730F01/northbridge.c | 208 ++++++++++++++++++++++++--
 3 files changed, 214 insertions(+), 12 deletions(-)

diff --git a/src/mainboard/amd/olivehillplus/acpi_tables.c b/src/mainboard/amd/olivehillplus/acpi_tables.c
index d5ebad4..a1a5a6b 100644
--- a/src/mainboard/amd/olivehillplus/acpi_tables.c
+++ b/src/mainboard/amd/olivehillplus/acpi_tables.c
@@ -54,3 +54,12 @@ unsigned long acpi_fill_madt(unsigned long current)
 
 	return current;
 }
+
+unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t* ivrs, unsigned long current)
+{
+	/* TODO
+	 * Add IVRS entries
+	 */
+
+	 return current;
+}
diff --git a/src/mainboard/pcengines/apu2/acpi_tables.c b/src/mainboard/pcengines/apu2/acpi_tables.c
index d5ebad4..17995ce 100644
--- a/src/mainboard/pcengines/apu2/acpi_tables.c
+++ b/src/mainboard/pcengines/apu2/acpi_tables.c
@@ -54,3 +54,12 @@ unsigned long acpi_fill_madt(unsigned long current)
 
 	return current;
 }
+
+unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t* ivrs, unsigned long current)
+{
+	/* TODO
+	 * Add IVRS entries
+	 */
+
+	return current;
+}
diff --git a/src/northbridge/amd/pi/00730F01/northbridge.c b/src/northbridge/amd/pi/00730F01/northbridge.c
index 9b1c1b1..44b1501 100644
--- a/src/northbridge/amd/pi/00730F01/northbridge.c
+++ b/src/northbridge/amd/pi/00730F01/northbridge.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * Copyright (C) 2016 Raptor Engineering, LLC
  *
  * 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
@@ -478,6 +479,193 @@ static unsigned long acpi_fill_hest(acpi_hest_t *hest)
 	return (unsigned long)current;
 }
 
+static void add_ivrs_device_entries(struct device *parent, struct device *dev, int depth, int linknum, int8_t *root_level, unsigned long *current, uint16_t *length)
+{
+	uint8_t *p;
+	struct device *sibling;
+	struct bus *link;
+
+	if (!root_level) {
+		root_level = malloc(sizeof(int8_t));
+		*root_level = -1;
+	}
+
+	if (dev->path.type == DEVICE_PATH_PCI) {
+		if ((dev->bus->secondary == 0x0) && (dev->path.pci.devfn == 0x0))
+			*root_level = depth;
+
+		if (*root_level != -1) {
+			if (depth >= *root_level) {
+				if (dev->enabled) {
+					if (depth == *root_level) {
+						if (dev->path.pci.devfn  == 0x2) {
+							/* IOMMU */
+							p = (uint8_t *) *current;
+							p[0] = 0x2;			/* Entry type */
+							p[1] = dev->path.pci.devfn;	/* Device */
+							p[2] = dev->bus->secondary;	/* Bus */
+							p[3] = 0x0;			/* Data */
+							p[4] = 0x0;			/* Padding */
+							p[5] = 0x0;			/* Padding */
+							p[6] = 0x0;			/* Padding */
+							p[7] = 0x0;			/* Padding */
+							*length += 8;
+							*current += 8;
+						} else if (dev->path.pci.devfn < (0x2 << 3)) {
+							/* FCH control device */
+						} else if ((dev->path.pci.devfn >= (0x2 << 3)) && (dev->path.pci.devfn < (0x3 << 3))) {
+							/* FCH PCIe bridge device */
+							p = (uint8_t *) *current;
+							p[0] = 0x2;			/* Entry type */
+							p[1] = dev->path.pci.devfn;	/* Device */
+							p[2] = dev->bus->secondary;	/* Bus */
+							p[3] = 0x0;			/* Data */
+							p[4] = 0x0;			/* Padding */
+							p[5] = 0x0;			/* Padding */
+							p[6] = 0x0;			/* Padding */
+							p[7] = 0x0;			/* Padding */
+							*length += 8;
+							*current += 8;
+						} else {
+							if (dev->path.pci.devfn == (0x14 << 3)) {
+								/* SMBUS controller */
+								p = (uint8_t *) *current;
+								p[0] = 0x2;			/* Entry type */
+								p[1] = dev->path.pci.devfn;	/* Device */
+								p[2] = dev->bus->secondary;	/* Bus */
+								p[3] = 0x97;			/* Data */
+								p[4] = 0x0;			/* Padding */
+								p[5] = 0x0;			/* Padding */
+								p[6] = 0x0;			/* Padding */
+								p[7] = 0x0;			/* Padding */
+								*length += 8;
+								*current += 8;
+							} else {
+								/* Other southbridge device */
+								p = (uint8_t *) *current;
+								p[0] = 0x2;			/* Entry type */
+								p[1] = dev->path.pci.devfn;	/* Device */
+								p[2] = dev->bus->secondary;	/* Bus */
+								p[3] = 0x0;			/* Data */
+								p[4] = 0x0;			/* Padding */
+								p[5] = 0x0;			/* Padding */
+								p[6] = 0x0;			/* Padding */
+								p[7] = 0x0;			/* Padding */
+								*length += 8;
+								*current += 8;
+							}
+						}
+					} else {
+						if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_NORMAL) {
+							/* Device behind bridge */
+							if (pci_find_capability(dev, PCI_CAP_ID_PCIE)) {
+								/* Device is PCIe */
+								p = (uint8_t *) *current;
+								p[0] = 0x2;			/* Entry type */
+								p[1] = dev->path.pci.devfn;	/* Device */
+								p[2] = dev->bus->secondary;	/* Bus */
+								p[3] = 0x0;			/* Data */
+								p[4] = 0x0;			/* Padding */
+								p[5] = 0x0;			/* Padding */
+								p[6] = 0x0;			/* Padding */
+								p[7] = 0x0;			/* Padding */
+								*length += 8;
+								*current += 8;
+							} else {
+								/* Device is legacy PCI or PCI-X */
+								p = (uint8_t *) *current;
+								p[0] = 0x42;			/* Entry type */
+								p[1] = dev->path.pci.devfn;	/* Device */
+								p[2] = dev->bus->secondary;	/* Bus */
+								p[3] = 0x0;			/* Data */
+								p[4] = 0x0;			/* Reserved */
+								p[5] = parent->path.pci.devfn;	/* Device */
+								p[6] = parent->bus->secondary;	/* Bus */
+								p[7] = 0x0;			/* Reserved */
+								*length += 8;
+								*current += 8;
+							}
+						} else if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
+							if (pci_find_capability(dev, PCI_CAP_ID_PCIE)) {
+								/* Bridge is PCIe */
+								p = (uint8_t *) *current;
+								p[0] = 0x2;			/* Entry type */
+								p[1] = dev->path.pci.devfn;	/* Device */
+								p[2] = dev->bus->secondary;	/* Bus */
+								p[3] = 0x0;			/* Data */
+								p[4] = 0x0;			/* Padding */
+								p[5] = 0x0;			/* Padding */
+								p[6] = 0x0;			/* Padding */
+								p[7] = 0x0;			/* Padding */
+								*length += 8;
+								*current += 8;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	for (link = dev->link_list; link; link = link->next)
+		for (sibling = link->children; sibling; sibling = sibling->sibling)
+			add_ivrs_device_entries(dev, sibling, depth + 1, depth, root_level, current, length);
+
+	free(root_level);
+}
+
+static unsigned long acpi_fill_ivrs(acpi_ivrs_t* ivrs, unsigned long current)
+{
+	uint8_t *p;
+
+	device_t nb_dev = dev_find_slot(0, PCI_DEVFN(0, 0));
+	if (!nb_dev) {
+		printk(BIOS_WARNING, "acpi_fill_ivrs: Unable to locate G-series northbridge device!  IVRS table not generated...\n");
+		return (unsigned long)ivrs;
+	}
+
+	ivrs->iv_info = 0x0;
+	ivrs->iv_info |= (0x40 << 15);	/* Maximum supported virtual address size */
+	ivrs->iv_info |= (0x30 << 8);	/* Maximum supported physical address size */
+	ivrs->iv_info |= (0x2 << 5);	/* Guest virtual address width */
+
+	ivrs->ivhd.type = 0x10;
+	ivrs->ivhd.flags = 0x0e;
+	ivrs->ivhd.flags |= 0x10;					/* Enable ATS support */
+	ivrs->ivhd.length = sizeof(struct acpi_ivrs_ivhd);
+	ivrs->ivhd.device_id = 0x2 | (nb_dev->bus->secondary << 8);	/* BDF <bus>:00.2 */
+	ivrs->ivhd.capability_offset = 0x40;				/* Capability block 0x40 (type 0xf, "Secure device") */
+	ivrs->ivhd.iommu_base_low = 0xfeb00000;
+	ivrs->ivhd.iommu_base_high = 0x0;
+	ivrs->ivhd.pci_segment_group = 0x0;
+	ivrs->ivhd.iommu_info = 0x0;
+	ivrs->ivhd.iommu_info |= (0x13 << 8);
+	ivrs->ivhd.efr = 0x0;
+
+	/* Describe HPET */
+	p = (uint8_t *)current;
+	p[0] = 0x48;			/* Entry type */
+	p[1] = 0;			/* Device */
+	p[2] = 0;			/* Bus */
+	p[3] = 0xd7;			/* Data */
+	p[4] = 0x0;			/* HPET number */
+	p[5] = 0x14 << 3;		/* HPET device */
+	p[6] = nb_dev->bus->secondary;	/* HPET bus */
+	p[7] = 0x2;			/* Variety */
+	ivrs->ivhd.length += 8;
+	current += 8;
+
+	/* Describe PCI devices */
+	add_ivrs_device_entries(NULL, all_devices, 0, -1, NULL, &current, &ivrs->ivhd.length);
+
+	/* Describe IOAPICs */
+	unsigned long prev_current = current;
+	current = acpi_fill_ivrs_ioapic(ivrs, current);
+	ivrs->ivhd.length += (current - prev_current);
+
+	return current;
+}
+
 static void northbridge_fill_ssdt_generator(device_t device)
 {
 	msr_t msr;
@@ -507,7 +695,7 @@ static unsigned long agesa_write_acpi_tables(device_t device,
 	acpi_slit_t *slit;
 	acpi_header_t *ssdt;
 	acpi_header_t *alib;
-	acpi_header_t *ivrs;
+	acpi_ivrs_t *ivrs;
 	acpi_hest_t *hest;
 
 	/* HEST */
@@ -517,17 +705,13 @@ static unsigned long agesa_write_acpi_tables(device_t device,
 	acpi_add_table(rsdp, (void *)current);
 	current += ((acpi_header_t *)current)->length;
 
-	current   = ALIGN(current, 8);
-	printk(BIOS_DEBUG, "ACPI:    * IVRS at %lx\n", current);
-	ivrs = agesawrapper_getlateinitptr(PICK_IVRS);
-	if (ivrs != NULL) {
-		memcpy((void *)current, ivrs, ivrs->length);
-		ivrs = (acpi_header_t *) current;
-		current += ivrs->length;
-		acpi_add_table(rsdp, ivrs);
-	} else {
-		printk(BIOS_DEBUG, "  AGESA IVRS table NULL. Skipping.\n");
-	}
+	/* IVRS */
+	current = ALIGN(current, 8);
+	printk(BIOS_DEBUG, "ACPI:   * IVRS at %lx\n", current);
+	ivrs = (acpi_ivrs_t *) current;
+	acpi_create_ivrs(ivrs, acpi_fill_ivrs);
+	current += ivrs->header.length;
+	acpi_add_table(rsdp, ivrs);
 
 	/* SRAT */
 	current = ALIGN(current, 8);



More information about the coreboot-gerrit mailing list