From d9cde328cb3a7b15eb8dc630308eda2f508dbc1d Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 29 Sep 2020 21:21:23 +0200 Subject: [PATCH] acpi: support amd iommu detection Issue #3928 --- repos/libports/src/app/acpica/report.cc | 16 ++++ repos/os/src/drivers/acpi/acpi.cc | 79 +++++++++++++++++++ .../platform/spec/x86/pci_session_component.h | 2 +- 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/repos/libports/src/app/acpica/report.cc b/repos/libports/src/app/acpica/report.cc index da12f58570..b737d155e6 100644 --- a/repos/libports/src/app/acpica/report.cc +++ b/repos/libports/src/app/acpica/report.cc @@ -134,6 +134,18 @@ static void add_dmar(ACPI_TABLE_DMAR const * const dmar_table, }, [](ACPI_DMAR_HEADER const * const e) { return e->Length; }); } +static void add_ivdb(ACPI_TABLE_IVRS const * const ivrs_table, + Reporter::Xml_generator &xml) +{ + typedef ACPI_IVRS_HEADER Ivdb; + + for_each_element(ivrs_table, (Ivdb *) nullptr, [&](Ivdb const * const e) { + xml.node("ivdb", [&] () { + xml.attribute("type", e->Type); + }); + }, [](Ivdb const * const e) { return e->Length; }); +} + void Acpica::generate_report(Genode::Env &env, Bridge *pci_root_bridge) { enum { REPORT_SIZE = 5 * 4096 }; @@ -161,6 +173,10 @@ void Acpica::generate_report(Genode::Env &env, Bridge *pci_root_bridge) add_dmar(reinterpret_cast(header), xml); } + status = AcpiGetTable((char *)ACPI_SIG_IVRS, 0, &header); + if (status == AE_OK) + add_ivdb(reinterpret_cast(header), xml); + if (pci_root_bridge) pci_root_bridge->generate(xml); }); diff --git a/repos/os/src/drivers/acpi/acpi.cc b/repos/os/src/drivers/acpi/acpi.cc index cec5f9c2b2..e87344a454 100644 --- a/repos/os/src/drivers/acpi/acpi.cc +++ b/repos/os/src/drivers/acpi/acpi.cc @@ -238,6 +238,69 @@ struct Dmar_rmrr : Genode::Mmio } }; +/* I/O Virtualization Definition Blocks for AMD IO-MMU */ +struct Ivdb : Genode::Mmio +{ + struct Type : Register<0x00, 8> { }; + struct Length : Register<0x02, 16> { }; + + Ivdb(addr_t const addr) : Genode::Mmio(addr) { } +}; + + +struct Ivdb_entry : public List::Element +{ + unsigned const type; + + Ivdb_entry(unsigned t) : type (t) { } + + template + static void for_each(FUNC const &func) + { + for (Ivdb_entry *entry = list()->first(); entry; entry = entry->next()) { + func(*entry); + } + } + + static List *list() + { + static List _list; + return &_list; + } +}; + + +/* I/O Virtualization Reporting Structure (IVRS) for AMD IO-MMU */ +struct Ivrs : Genode::Mmio +{ + struct Length : Register<0x04, 32> { }; + struct Ivinfo : Register<0x24, 32> { + struct Dmar : Bitfield<1, 1> { }; + }; + + static constexpr unsigned min_size() { return 0x30; } + + Ivrs(addr_t const table) : Genode::Mmio(table) { } + + void parse(Allocator &alloc) + { + addr_t addr = base() + 0x30; + while (addr < base() + read()) { + bool dmar = Ivinfo::Dmar::get(read()); + if (dmar) + Genode::warning("Predefined regions should be added to IOMMU"); + + Ivdb ivdb(addr); + + uint32_t const type = ivdb.read(); + uint32_t const size = ivdb.read(); + + Ivdb_entry::list()->insert(new (&alloc) Ivdb_entry(type)); + + addr += size; + } + } +}; /* Fixed ACPI description table (FADT) */ struct Fadt : Genode::Mmio @@ -371,6 +434,8 @@ class Table_wrapper bool valid() { return !checksum((uint8_t *)_table, _table->size); } + bool is_ivrs() const { return _cmp("IVRS");} + /** * Is this the FACP table */ @@ -1201,6 +1266,13 @@ class Acpi_table continue; } + if (table.is_ivrs() && Ivrs::min_size() <= table->size) { + log("Found IVRS"); + + Ivrs ivrs(reinterpret_cast(table->signature)); + ivrs.parse(alloc); + } + if (table.is_facp() && Fadt::size() <= table->size) { Fadt fadt(reinterpret_cast(table->signature)); dsdt = fadt.read(); @@ -1421,6 +1493,13 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc) }); }); } + + Ivdb_entry::for_each([&](auto entry) { + xml.node("ivdb", [&] () { + xml.attribute("type", entry.type); + }); + }); + { Element *e = Element::list()->first(); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index a7439a224d..0d41850fd8 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -903,7 +903,7 @@ class Platform::Root : public Genode::Root_component continue; } - if (node.has_type("drhd")) { + if (node.has_type("drhd") || node.has_type("ivdb")) { _iommu = true; continue; }