acpi: support amd iommu detection

Issue #3928
This commit is contained in:
Alexander Boettcher 2020-09-29 21:21:23 +02:00 committed by Christian Helmuth
parent 6b20a6bc7c
commit d9cde328cb
3 changed files with 96 additions and 1 deletions

View File

@ -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<ACPI_TABLE_DMAR *>(header), xml);
}
status = AcpiGetTable((char *)ACPI_SIG_IVRS, 0, &header);
if (status == AE_OK)
add_ivdb(reinterpret_cast<ACPI_TABLE_IVRS *>(header), xml);
if (pci_root_bridge)
pci_root_bridge->generate(xml);
});

View File

@ -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<Ivdb_entry>::Element
{
unsigned const type;
Ivdb_entry(unsigned t) : type (t) { }
template <typename FUNC>
static void for_each(FUNC const &func)
{
for (Ivdb_entry *entry = list()->first(); entry; entry = entry->next()) {
func(*entry);
}
}
static List<Ivdb_entry> *list()
{
static List<Ivdb_entry> _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<Ivrs::Length>()) {
bool dmar = Ivinfo::Dmar::get(read<Ivinfo::Dmar>());
if (dmar)
Genode::warning("Predefined regions should be added to IOMMU");
Ivdb ivdb(addr);
uint32_t const type = ivdb.read<Ivdb::Type>();
uint32_t const size = ivdb.read<Ivdb::Length>();
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<Genode::addr_t>(table->signature));
ivrs.parse(alloc);
}
if (table.is_facp() && Fadt::size() <= table->size) {
Fadt fadt(reinterpret_cast<Genode::addr_t>(table->signature));
dsdt = fadt.read<Fadt::Dsdt>();
@ -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();

View File

@ -903,7 +903,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
continue;
}
if (node.has_type("drhd")) {
if (node.has_type("drhd") || node.has_type("ivdb")) {
_iommu = true;
continue;
}