mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
x86: detect root bridge properly
Beforehand the root bridge was expected to be at 0:0.0. Fixes #2801
This commit is contained in:
parent
58fb5ed722
commit
0de62717f9
@ -88,6 +88,17 @@ struct Generic
|
||||
uint8_t creator[4];
|
||||
uint32_t creator_rev;
|
||||
|
||||
void print(Genode::Output &out) const
|
||||
{
|
||||
Genode::String<7> s_oem((const char *)oemid);
|
||||
Genode::String<9> s_oemtabid((const char *)oemtabid);
|
||||
Genode::String<5> s_creator((const char *)creator);
|
||||
|
||||
Genode::print(out, "OEM '", s_oem, "', table id '", s_oemtabid, "', "
|
||||
"revision ", oemrev, ", creator '", s_creator, "' (",
|
||||
creator_rev, ")");
|
||||
}
|
||||
|
||||
uint8_t const *data() { return reinterpret_cast<uint8_t *>(this); }
|
||||
|
||||
/* MADT ACPI structure */
|
||||
@ -495,6 +506,9 @@ class Pci_routing : public List<Pci_routing>::Element
|
||||
}
|
||||
};
|
||||
|
||||
/* set during ACPI Table walk to valid value */
|
||||
enum { INVALID_ROOT_BRIDGE = 0x10000U };
|
||||
static unsigned root_bridge_bdf = INVALID_ROOT_BRIDGE;
|
||||
|
||||
/**
|
||||
* A table element (method, device, scope or name)
|
||||
@ -1081,6 +1095,13 @@ class Element : private List<Element>::Element
|
||||
if (prt) prt->dump();
|
||||
|
||||
if (prt) {
|
||||
uint32_t const hid= e->_value("_HID");
|
||||
uint32_t const cid= e->_value("_CID");
|
||||
if (hid == 0x80ad041 || cid == 0x80ad041 || // "PNP0A08" PCI Express root bridge
|
||||
hid == 0x30ad041 || cid == 0x30ad041) { // "PNP0A03" PCI root bridge
|
||||
root_bridge_bdf = e->_bdf;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
Genode::log("Scanning device ", Genode::Hex(e->_bdf));
|
||||
|
||||
@ -1091,31 +1112,6 @@ class Element : private List<Element>::Element
|
||||
e->_routed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for GSI of given device, bridge, and pin
|
||||
*/
|
||||
static uint32_t search_gsi(uint32_t device_bdf, uint32_t bridge_bdf, uint32_t pin)
|
||||
{
|
||||
Element *e = list()->first();
|
||||
|
||||
for (; e; e = e->next()) {
|
||||
if (!e->is_device() || e->_bdf != bridge_bdf)
|
||||
continue;
|
||||
|
||||
Pci_routing *r = e->pci_list().first();
|
||||
for (; r; r = r->next()) {
|
||||
if (r->match_bdf(device_bdf) && r->pin() == pin) {
|
||||
if (verbose)
|
||||
Genode::log("Found GSI: ", r->gsi(), " "
|
||||
"device : ", Genode::Hex(device_bdf), " ",
|
||||
"pin ", pin);
|
||||
return r->gsi();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1287,16 +1283,6 @@ class Acpi_table
|
||||
return;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
uint8_t oem[7];
|
||||
memcpy(oem, rsdp->oemid, 6);
|
||||
oem[6] = 0;
|
||||
Genode::log("ACPI revision ", rsdp->revision, " of "
|
||||
"OEM '", oem, "', "
|
||||
"rsdt:", Genode::Hex(rsdp->rsdt), " "
|
||||
"xsdt:", Genode::Hex(rsdp->xsdt));
|
||||
}
|
||||
|
||||
rsdt = rsdp->rsdt;
|
||||
xsdt = rsdp->xsdt;
|
||||
acpi_revision = rsdp->revision;
|
||||
@ -1311,6 +1297,8 @@ class Acpi_table
|
||||
|
||||
uint64_t * entries = reinterpret_cast<uint64_t *>(table.table() + 1);
|
||||
_parse_tables(alloc, entries, table.entry_count(entries));
|
||||
|
||||
Genode::log("XSDT ", *table.table());
|
||||
} else {
|
||||
/* running (32bit) or (64bit and xsdt isn't valid) */
|
||||
Table_wrapper table(_memory, rsdt);
|
||||
@ -1318,6 +1306,8 @@ class Acpi_table
|
||||
|
||||
uint32_t * entries = reinterpret_cast<uint32_t *>(table.table() + 1);
|
||||
_parse_tables(alloc, entries, table.entry_count(entries));
|
||||
|
||||
Genode::log("RSDT ", *table.table());
|
||||
}
|
||||
|
||||
/* free up memory of elements not of any use */
|
||||
@ -1348,14 +1338,11 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc)
|
||||
acpi.enabled(true);
|
||||
|
||||
Genode::Reporter::Xml_generator xml(acpi, [&] () {
|
||||
if (!(!Fadt::features && !Fadt::reset_type &&
|
||||
!Fadt::reset_addr && !Fadt::reset_value))
|
||||
xml.node("fadt", [&] () {
|
||||
attribute_hex(xml, "features" , Fadt::features);
|
||||
attribute_hex(xml, "reset_type" , Fadt::reset_type);
|
||||
attribute_hex(xml, "reset_addr" , Fadt::reset_addr);
|
||||
attribute_hex(xml, "reset_value", Fadt::reset_value);
|
||||
if (root_bridge_bdf != INVALID_ROOT_BRIDGE) {
|
||||
xml.node("root_bridge", [&] () {
|
||||
attribute_hex(xml, "bdf", root_bridge_bdf);
|
||||
});
|
||||
}
|
||||
|
||||
for (Pci_config_space *e = Pci_config_space::list()->first(); e;
|
||||
e = e->next())
|
||||
|
@ -287,12 +287,15 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig
|
||||
|
||||
|
||||
unsigned short Platform::Irq_routing::rewrite(unsigned char bus, unsigned char dev,
|
||||
unsigned char /* func */, unsigned char pin)
|
||||
unsigned char, unsigned char pin)
|
||||
{
|
||||
for (Irq_routing *i = list()->first(); i; i = i->next())
|
||||
unsigned const bridge_bdf_bus = Platform::bridge_bdf(bus);
|
||||
|
||||
for (Irq_routing *i = list()->first(); i; i = i->next()) {
|
||||
if ((dev == i->_device) && (pin - 1 == i->_device_pin) &&
|
||||
(i->_bridge_bdf == Platform::bridge_bdf(bus)))
|
||||
(i->_bridge_bdf == bridge_bdf_bus))
|
||||
return i->_gsi;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -53,4 +53,7 @@ class Platform::Bridge : public Genode::List<Bridge>::Element
|
||||
bdf = (bdf << 8) | ((_dev & 0x1f) << 3) | (_fun & 0x7);
|
||||
return bdf;
|
||||
}
|
||||
|
||||
enum { INVALID_ROOT_BRIDGE = 0x10000U };
|
||||
static unsigned root_bridge_bdf;
|
||||
};
|
||||
|
@ -34,9 +34,10 @@
|
||||
#include <base/allocator_guard.h>
|
||||
|
||||
/* local */
|
||||
#include "pci_device_component.h"
|
||||
#include "pci_config_access.h"
|
||||
#include "device_pd.h"
|
||||
#include "pci_bridge.h"
|
||||
#include "pci_config_access.h"
|
||||
#include "pci_device_component.h"
|
||||
|
||||
typedef Genode::Ram_dataspace_capability Ram_capability;
|
||||
|
||||
@ -828,27 +829,6 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Fadt {
|
||||
Genode::uint32_t features = 0, reset_type = 0, reset_value = 0;
|
||||
Genode::uint64_t reset_addr = 0;
|
||||
|
||||
/* Table 5-35 Fixed ACPI Description Table Fixed Feature Flags */
|
||||
struct Features : Genode::Register<32> {
|
||||
struct Reset : Bitfield<10, 1> { };
|
||||
};
|
||||
|
||||
/* ACPI spec - 5.2.3.2 Generic Address Structure */
|
||||
struct Gas : Genode::Register<32>
|
||||
{
|
||||
struct Address_space : Bitfield <0, 8> {
|
||||
enum { SYSTEM_IO = 1 };
|
||||
};
|
||||
struct Access_size : Bitfield<24,8> {
|
||||
enum { UNDEFINED = 0, BYTE = 1, WORD = 2, DWORD = 3, QWORD = 4};
|
||||
};
|
||||
};
|
||||
} fadt { };
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Attached_rom_dataspace &_config;
|
||||
|
||||
@ -974,11 +954,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.has_type("fadt")) {
|
||||
node.attribute("features").value(&fadt.features);
|
||||
node.attribute("reset_type").value(&fadt.reset_type);
|
||||
node.attribute("reset_addr").value(&fadt.reset_addr);
|
||||
node.attribute("reset_value").value(&fadt.reset_value);
|
||||
if (node.has_type("root_bridge")) {
|
||||
node.attribute("bdf").value(&Platform::Bridge::root_bridge_bdf);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -997,40 +974,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
node.attribute("device").value(&device);
|
||||
node.attribute("device_pin").value(&device_pin);
|
||||
|
||||
/* check that bridge bdf is actually a valid device */
|
||||
Device_config config((bridge_bdf >> 8 & 0xff),
|
||||
(bridge_bdf >> 3) & 0x1f,
|
||||
bridge_bdf & 0x7, &config_access);
|
||||
|
||||
if (!config.valid())
|
||||
continue;
|
||||
|
||||
/* drop routing information on non ACPI platform */
|
||||
if (!acpi_platform) {
|
||||
if (config.pci_bridge())
|
||||
continue;
|
||||
|
||||
Device_config dev(device << 3);
|
||||
|
||||
enum { PCI_IRQ_LINE = 0x3c };
|
||||
uint8_t pin = dev.read(config_access, PCI_IRQ_LINE,
|
||||
Platform::Device::ACCESS_8BIT);
|
||||
warning(dev, " ignore ACPI IRQ routing: ", pin, "->", gsi);
|
||||
if (!acpi_platform)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config.pci_bridge() && bridge_bdf != 0)
|
||||
/**
|
||||
* If the bridge bdf has not a type header of a bridge in
|
||||
* the pci config space, then it should be the host bridge
|
||||
* device. The host bridge device need not to be
|
||||
* necessarily at 0:0.0, it may be on another location. The
|
||||
* irq routing information for the host bridge however
|
||||
* contain entries for the bridge bdf to be 0:0.0 -
|
||||
* therefore we override it here for the irq rerouting
|
||||
* information of host bridge devices.
|
||||
*/
|
||||
bridge_bdf = 0;
|
||||
|
||||
Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf,
|
||||
device, device_pin);
|
||||
@ -1123,6 +1069,12 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
||||
throw;
|
||||
}
|
||||
|
||||
if (Platform::Bridge::root_bridge_bdf < Platform::Bridge::INVALID_ROOT_BRIDGE) {
|
||||
Device_config config(Platform::Bridge::root_bridge_bdf);
|
||||
Genode::log("Root bridge: ", config);
|
||||
} else
|
||||
Genode::warning("Root bridge: unknown");
|
||||
|
||||
_construct_buses();
|
||||
|
||||
_pci_reporter.enabled(config.xml().has_sub_node("report") &&
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include "pci_bridge.h"
|
||||
|
||||
|
||||
/* set during ACPI ROM parsing to valid value */
|
||||
unsigned Platform::Bridge::root_bridge_bdf = INVALID_ROOT_BRIDGE;
|
||||
|
||||
|
||||
static Genode::List<Platform::Bridge> *bridges()
|
||||
{
|
||||
static Genode::List<Platform::Bridge> list;
|
||||
@ -30,7 +34,8 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
|
||||
if (bridge->part_of(bus))
|
||||
return bridge->bdf();
|
||||
}
|
||||
return 0;
|
||||
/* XXX Ideally, this case should never happen */
|
||||
return Platform::Bridge::root_bridge_bdf;
|
||||
}
|
||||
|
||||
void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||
|
Loading…
x
Reference in New Issue
Block a user