From e816020346a304dc703da9ab927b1015068cb2e1 Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Fri, 18 Aug 2023 16:39:05 +0200 Subject: [PATCH] pci_decode: add intel_iommu devices to devices ROM genodelabs/genode#5002 --- repos/os/src/app/pci_decode/drhd.h | 61 ++++++++++++++++++++++++++ repos/os/src/app/pci_decode/main.cc | 66 +++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 repos/os/src/app/pci_decode/drhd.h diff --git a/repos/os/src/app/pci_decode/drhd.h b/repos/os/src/app/pci_decode/drhd.h new file mode 100644 index 0000000000..6592687f1e --- /dev/null +++ b/repos/os/src/app/pci_decode/drhd.h @@ -0,0 +1,61 @@ +/* + * \brief DMA remapping hardware reporting from ACPI information in list models + * \author Johannes Schlatow + * \date 2023-08-14 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#include +#include +#include + +using namespace Genode; +using namespace Pci; + + +struct Drhd : List_model::Element +{ + using Drhd_name = String<16>; + + enum Scope { INCLUDE_PCI_ALL, EXPLICIT }; + + addr_t addr; + size_t size; + unsigned segment; + Scope scope; + unsigned number; + + struct Device : Registry::Element + { + Bdf bdf; + + Device(Registry & registry, Bdf bdf) + : Registry::Element(registry, *this), bdf(bdf) + { } + }; + + Registry devices { }; + + Drhd(addr_t addr, size_t size, unsigned segment, Scope scope, unsigned number) + : addr(addr), size(size), segment(segment), scope(scope), number(number) + { } + + Drhd_name name() const { return Drhd_name("drhd", number); } + + bool matches(Xml_node const &node) const + { + return addr == node.attribute_value("phys", 0UL); + } + + static bool type_matches(Xml_node const &node) + { + return node.has_type("drhd"); + } +}; diff --git a/repos/os/src/app/pci_decode/main.cc b/repos/os/src/app/pci_decode/main.cc index e250963955..6f4759df73 100644 --- a/repos/os/src/app/pci_decode/main.cc +++ b/repos/os/src/app/pci_decode/main.cc @@ -21,6 +21,7 @@ #include #include +#include #include using namespace Genode; @@ -41,6 +42,7 @@ struct Main List_model irq_routing_list {}; List_model irq_override_list {}; List_model reserved_memory_list {}; + List_model drhd_list {}; Constructible pci_config_ds {}; @@ -412,6 +414,20 @@ void Main::parse_acpi_device_info(Xml_node const &xml, Xml_generator & gen) */ if (xml.has_sub_node("sci_int")) parse_acpica_info(xml, gen); + + /* Intel DMA-remapping hardware units */ + drhd_list.for_each([&] (Drhd const & drhd) { + gen.node("device", [&] + { + gen.attribute("name", drhd.name()); + gen.attribute("type", "intel_iommu"); + gen.node("io_mem", [&] + { + gen.attribute("address", String<20>(Hex(drhd.addr))); + gen.attribute("size", String<20>(Hex(drhd.size))); + }); + }); + }); } @@ -559,6 +575,56 @@ Main::Main(Env & env) : env(env) [&] (Rmrr &, Xml_node const &) { } ); + unsigned nbr { 0 }; + drhd_list.update_from_xml(xml, + + /* create */ + [&] (Xml_node const &node) -> Drhd & + { + addr_t addr = node.attribute_value("phys", 0UL); + size_t size = node.attribute_value("size", 0UL); + unsigned seg = node.attribute_value("segment", 0U); + unsigned flags = node.attribute_value("flags", 0U); + + Drhd * drhd; + if (flags & 0x1) + drhd = new (heap) Drhd(addr, size, seg, + Drhd::Scope::INCLUDE_PCI_ALL, nbr++); + else + drhd = new (heap) Drhd(addr, size, seg, + Drhd::Scope::EXPLICIT, nbr++); + + /* parse device scopes which define the explicitly assigned devices */ + bus_t bus = 0; + dev_t dev = 0; + func_t fn = 0; + + node.for_each_sub_node("scope", [&] (Xml_node node) { + bus = node.attribute_value("bus_start", 0U); + node.with_optional_sub_node("path", [&] (Xml_node node) { + dev = node.attribute_value("dev", 0); + fn = node.attribute_value("func", 0); + }); + + new (heap) Drhd::Device(drhd->devices, {bus, dev, fn}); + }); + + return *drhd; + }, + + /* destroy */ + [&] (Drhd &drhd) + { + drhd.devices.for_each([&] (Drhd::Device & device) { + destroy(heap, &device); }); + destroy(heap, &drhd); + }, + + /* update */ + [&] (Drhd &, Xml_node const &) { } + + ); + pci_reporter.generate([&] (Xml_generator & generator) { parse_acpi_device_info(xml, generator);