pci_decode: interpret reserved memory from ACPI

We need the information about reserved memory region reports
from the ACPI tables within the platform driver to pre-fill
IOMMU tables with the corresponding mappings. Therefore,
the pci_decode component now parses the information from the
ACPI ROM, and adds "reserved_memory" nodes to all related
devices in the devices report.

Ref genodelabs/genode#4578
This commit is contained in:
Stefan Kalkowski 2022-09-15 11:26:32 +02:00 committed by Christian Helmuth
parent 281785f6bd
commit 85dc2e5b9b
2 changed files with 91 additions and 0 deletions

View File

@ -19,6 +19,7 @@
#include <os/reporter.h>
#include <irq.h>
#include <rmrr.h>
#include <pci/config.h>
using namespace Genode;
@ -43,6 +44,7 @@ struct Main
List_model<Irq_routing> irq_routing_list {};
List_model<Irq_override> irq_override_list {};
List_model<Rmrr> reserved_memory_list {};
Constructible<Attached_io_mem_dataspace> pci_config_ds {};
@ -168,6 +170,15 @@ void Main::parse_pci_function(Bdf bdf,
gen.attribute("number", irq);
});
reserved_memory_list.for_each([&] (Rmrr & rmrr) {
if (rmrr.bdf == bdf)
gen.node("reserved_memory", [&]
{
gen.attribute("address", rmrr.addr);
gen.attribute("size", rmrr.size);
});
});
});
}
@ -259,6 +270,11 @@ void Main::sys_rom_update()
irq_routing_list.update_from_xml(policy, xml);
}
{
Rmrr_policy policy(heap);
reserved_memory_list.update_from_xml(policy, xml);
}
parse_pci_config_spaces(xml);
}

View File

@ -0,0 +1,75 @@
/*
* \brief Reserved memory region reporting from ACPI information in list models
* \author Stefan Kalkowski
* \date 2022-09-12
*/
/*
* Copyright (C) 2022 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 <base/heap.h>
#include <pci/types.h>
#include <util/list_model.h>
using namespace Genode;
using namespace Pci;
struct Rmrr : List_model<Rmrr>::Element
{
Bdf bdf;
addr_t addr;
size_t size;
Rmrr(Bdf bdf, addr_t addr, size_t size)
: bdf(bdf), addr(addr), size(size) {}
};
struct Rmrr_policy : List_model<Rmrr>::Update_policy
{
Heap & heap;
void destroy_element(Rmrr & rmrr) {
destroy(heap, &rmrr); }
Rmrr & create_element(Xml_node node)
{
bus_t bus = 0;
dev_t dev = 0;
func_t fn = 0;
addr_t start = node.attribute_value("start", 0UL);
addr_t end = node.attribute_value("end", 0UL);
node.with_optional_sub_node("scope", [&] (Xml_node node) {
bus = node.attribute_value<uint8_t>("bus_start", 0U);
node.with_optional_sub_node("path", [&] (Xml_node node) {
dev = node.attribute_value<uint8_t>("dev", 0);
fn = node.attribute_value<uint8_t>("func", 0);
});
});
return *(new (heap) Rmrr({bus, dev, fn}, start, (end-start+1)));
}
void update_element(Rmrr &, Xml_node) {}
static bool element_matches_xml_node(Rmrr const & rmrr,
Genode::Xml_node node)
{
addr_t start = node.attribute_value("start", 0UL);
addr_t end = node.attribute_value("end", 0UL);
return rmrr.addr == start &&
rmrr.size == (end-start+1);
}
static bool node_is_element(Genode::Xml_node node) {
return node.has_type("rmrr"); }
Rmrr_policy(Heap & heap) : heap(heap) {}
};