From b136ed0dfc826b8aaad027ed2edfcf7136fab796 Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Wed, 20 Mar 2024 14:46:47 +0100 Subject: [PATCH] pci_decode: report IOAPIC devices genodelabs/genode#5066 --- repos/os/src/app/pci_decode/drhd.h | 10 +++- repos/os/src/app/pci_decode/ioapic.h | 42 ++++++++++++++ repos/os/src/app/pci_decode/main.cc | 86 ++++++++++++++++++++++++++-- 3 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 repos/os/src/app/pci_decode/ioapic.h diff --git a/repos/os/src/app/pci_decode/drhd.h b/repos/os/src/app/pci_decode/drhd.h index 6592687f1e..75714d6a51 100644 --- a/repos/os/src/app/pci_decode/drhd.h +++ b/repos/os/src/app/pci_decode/drhd.h @@ -34,10 +34,14 @@ struct Drhd : List_model::Element struct Device : Registry::Element { - Bdf bdf; + enum { IOAPIC = 0x3 }; - Device(Registry & registry, Bdf bdf) - : Registry::Element(registry, *this), bdf(bdf) + Bdf bdf; + uint8_t type; + uint8_t id; + + Device(Registry & registry, Bdf bdf, uint8_t type, uint8_t id) + : Registry::Element(registry, *this), bdf(bdf), type(type), id(id) { } }; diff --git a/repos/os/src/app/pci_decode/ioapic.h b/repos/os/src/app/pci_decode/ioapic.h new file mode 100644 index 0000000000..3c3598b55c --- /dev/null +++ b/repos/os/src/app/pci_decode/ioapic.h @@ -0,0 +1,42 @@ +/* + * \brief IOAPIC reporting from ACPI information in list models + * \author Johannes Schlatow + * \date 2024-03-20 + */ + +/* + * Copyright (C) 2024 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 + +using namespace Genode; + +struct Ioapic : List_model::Element +{ + using Ioapic_name = String<16>; + + uint8_t id; + addr_t addr; + uint32_t base_irq; + + Ioapic(uint8_t id, addr_t addr, uint32_t base_irq) + : id(id), addr(addr), base_irq(base_irq) + { } + + Ioapic_name name() const { return Ioapic_name("ioapic", id); } + + bool matches(Xml_node const &node) const + { + return id == node.attribute_value("id", 0UL); + } + + static bool type_matches(Xml_node const &node) + { + return node.has_type("ioapic"); + } +}; diff --git a/repos/os/src/app/pci_decode/main.cc b/repos/os/src/app/pci_decode/main.cc index 59d1ecbb7d..c85f28235e 100644 --- a/repos/os/src/app/pci_decode/main.cc +++ b/repos/os/src/app/pci_decode/main.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include using namespace Genode; @@ -50,6 +51,7 @@ struct Main List_model irq_override_list {}; List_model reserved_memory_list {}; List_model drhd_list {}; + List_model ioapic_list {}; Constructible pci_config_ds {}; @@ -149,6 +151,8 @@ bus_t Main::parse_pci_function(Bdf bdf, if (msi) cfg.msi_cap->write(0); if (msi_x) cfg.msi_x_cap->write(0); + /* XXX we might need to skip PCI-discoverable IOAPIC and IOMMU devices */ + gen.node("device", [&] { auto string = [&] (uint64_t v) { return String<16>(Hex(v)); }; @@ -491,6 +495,55 @@ 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); + /* + * IOAPIC devices + */ + bool intr_remap = false; + xml.with_optional_sub_node("dmar", [&] (Xml_node const & node) { + intr_remap = node.attribute_value("intr_remap", intr_remap); }); + + ioapic_list.for_each([&] (Ioapic const & ioapic) { + gen.node("device", [&] + { + gen.attribute("name", ioapic.name()); + gen.attribute("type", "ioapic"); + gen.node("io_mem", [&] + { + gen.attribute("address", String<20>(Hex(ioapic.addr))); + gen.attribute("size", "0x1000"); + }); + + /* find corresponding drhd and add node and Routing_id property */ + drhd_list.for_each([&] (Drhd const & drhd) { + drhd.devices.for_each([&] (Drhd::Device const & device) { + if (device.type == Drhd::Device::IOAPIC && device.id == ioapic.id) { + gen.node("io_mmu", [&] { gen.attribute("name", drhd.name()); }); + gen.node("property", [&] + { + gen.attribute("name", "routing_id"); + gen.attribute("value", String<10>(Hex(Pci::Bdf::rid(device.bdf)))); + }); + } + }); + }); + + gen.node("property", [&] + { + gen.attribute("name", "irq_start"); + gen.attribute("value", ioapic.base_irq); + }); + + if (!intr_remap) + return; + + gen.node("property", [&] + { + gen.attribute("name", "remapping"); + gen.attribute("value", "yes"); + }); + }); + }); + /* Intel DMA-remapping hardware units */ drhd_list.for_each([&] (Drhd const & drhd) { gen.node("device", [&] @@ -686,6 +739,25 @@ Main::Main(Env & env) : env(env) [&] (Rmrr &, Xml_node const &) { } ); + ioapic_list.update_from_xml(xml, + + /* create */ + [&] (Xml_node const &node) -> Ioapic & + { + uint8_t id = node.attribute_value("id", (uint8_t)0U); + addr_t addr = node.attribute_value("addr", 0U); + uint32_t base = node.attribute_value("base_irq", 0U); + + return *new (heap) Ioapic(id, addr, base); + }, + + /* destroy */ + [&] (Ioapic &ioapic) { destroy(heap, &ioapic); }, + + /* update */ + [&] (Ioapic &, Xml_node const &) { } + ); + unsigned nbr { 0 }; drhd_list.update_from_xml(xml, @@ -706,18 +778,22 @@ Main::Main(Env & env) : env(env) 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; + bus_t bus = 0; + dev_t dev = 0; + func_t fn = 0; + uint8_t type = 0; + uint8_t id = 0; node.for_each_sub_node("scope", [&] (Xml_node node) { - bus = node.attribute_value("bus_start", 0U); + bus = node.attribute_value("bus_start", 0U); + type = node.attribute_value("type", 0U); + id = node.attribute_value("id", 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}); + new (heap) Drhd::Device(drhd->devices, {bus, dev, fn}, type, id); }); return *drhd;