[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, ¤t, &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