mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-01 23:20:55 +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];
|
uint8_t creator[4];
|
||||||
uint32_t creator_rev;
|
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); }
|
uint8_t const *data() { return reinterpret_cast<uint8_t *>(this); }
|
||||||
|
|
||||||
/* MADT ACPI structure */
|
/* 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)
|
* A table element (method, device, scope or name)
|
||||||
@ -1081,6 +1095,13 @@ class Element : private List<Element>::Element
|
|||||||
if (prt) prt->dump();
|
if (prt) prt->dump();
|
||||||
|
|
||||||
if (prt) {
|
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)
|
if (verbose)
|
||||||
Genode::log("Scanning device ", Genode::Hex(e->_bdf));
|
Genode::log("Scanning device ", Genode::Hex(e->_bdf));
|
||||||
|
|
||||||
@ -1091,31 +1112,6 @@ class Element : private List<Element>::Element
|
|||||||
e->_routed = true;
|
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;
|
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;
|
rsdt = rsdp->rsdt;
|
||||||
xsdt = rsdp->xsdt;
|
xsdt = rsdp->xsdt;
|
||||||
acpi_revision = rsdp->revision;
|
acpi_revision = rsdp->revision;
|
||||||
@ -1311,6 +1297,8 @@ class Acpi_table
|
|||||||
|
|
||||||
uint64_t * entries = reinterpret_cast<uint64_t *>(table.table() + 1);
|
uint64_t * entries = reinterpret_cast<uint64_t *>(table.table() + 1);
|
||||||
_parse_tables(alloc, entries, table.entry_count(entries));
|
_parse_tables(alloc, entries, table.entry_count(entries));
|
||||||
|
|
||||||
|
Genode::log("XSDT ", *table.table());
|
||||||
} else {
|
} else {
|
||||||
/* running (32bit) or (64bit and xsdt isn't valid) */
|
/* running (32bit) or (64bit and xsdt isn't valid) */
|
||||||
Table_wrapper table(_memory, rsdt);
|
Table_wrapper table(_memory, rsdt);
|
||||||
@ -1318,6 +1306,8 @@ class Acpi_table
|
|||||||
|
|
||||||
uint32_t * entries = reinterpret_cast<uint32_t *>(table.table() + 1);
|
uint32_t * entries = reinterpret_cast<uint32_t *>(table.table() + 1);
|
||||||
_parse_tables(alloc, entries, table.entry_count(entries));
|
_parse_tables(alloc, entries, table.entry_count(entries));
|
||||||
|
|
||||||
|
Genode::log("RSDT ", *table.table());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free up memory of elements not of any use */
|
/* 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);
|
acpi.enabled(true);
|
||||||
|
|
||||||
Genode::Reporter::Xml_generator xml(acpi, [&] () {
|
Genode::Reporter::Xml_generator xml(acpi, [&] () {
|
||||||
if (!(!Fadt::features && !Fadt::reset_type &&
|
if (root_bridge_bdf != INVALID_ROOT_BRIDGE) {
|
||||||
!Fadt::reset_addr && !Fadt::reset_value))
|
xml.node("root_bridge", [&] () {
|
||||||
xml.node("fadt", [&] () {
|
attribute_hex(xml, "bdf", root_bridge_bdf);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (Pci_config_space *e = Pci_config_space::list()->first(); e;
|
for (Pci_config_space *e = Pci_config_space::list()->first(); e;
|
||||||
e = e->next())
|
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 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) &&
|
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 i->_gsi;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,7 @@ class Platform::Bridge : public Genode::List<Bridge>::Element
|
|||||||
bdf = (bdf << 8) | ((_dev & 0x1f) << 3) | (_fun & 0x7);
|
bdf = (bdf << 8) | ((_dev & 0x1f) << 3) | (_fun & 0x7);
|
||||||
return bdf;
|
return bdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum { INVALID_ROOT_BRIDGE = 0x10000U };
|
||||||
|
static unsigned root_bridge_bdf;
|
||||||
};
|
};
|
||||||
|
@ -34,9 +34,10 @@
|
|||||||
#include <base/allocator_guard.h>
|
#include <base/allocator_guard.h>
|
||||||
|
|
||||||
/* local */
|
/* local */
|
||||||
#include "pci_device_component.h"
|
|
||||||
#include "pci_config_access.h"
|
|
||||||
#include "device_pd.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;
|
typedef Genode::Ram_dataspace_capability Ram_capability;
|
||||||
|
|
||||||
@ -828,27 +829,6 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
{
|
{
|
||||||
private:
|
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::Env &_env;
|
||||||
Genode::Attached_rom_dataspace &_config;
|
Genode::Attached_rom_dataspace &_config;
|
||||||
|
|
||||||
@ -974,11 +954,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.has_type("fadt")) {
|
if (node.has_type("root_bridge")) {
|
||||||
node.attribute("features").value(&fadt.features);
|
node.attribute("bdf").value(&Platform::Bridge::root_bridge_bdf);
|
||||||
node.attribute("reset_type").value(&fadt.reset_type);
|
|
||||||
node.attribute("reset_addr").value(&fadt.reset_addr);
|
|
||||||
node.attribute("reset_value").value(&fadt.reset_value);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,40 +974,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
node.attribute("device").value(&device);
|
node.attribute("device").value(&device);
|
||||||
node.attribute("device_pin").value(&device_pin);
|
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 */
|
/* drop routing information on non ACPI platform */
|
||||||
if (!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);
|
|
||||||
continue;
|
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,
|
Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf,
|
||||||
device, device_pin);
|
device, device_pin);
|
||||||
@ -1123,6 +1069,12 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
throw;
|
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();
|
_construct_buses();
|
||||||
|
|
||||||
_pci_reporter.enabled(config.xml().has_sub_node("report") &&
|
_pci_reporter.enabled(config.xml().has_sub_node("report") &&
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#include "pci_bridge.h"
|
#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> *bridges()
|
||||||
{
|
{
|
||||||
static Genode::List<Platform::Bridge> list;
|
static Genode::List<Platform::Bridge> list;
|
||||||
@ -30,7 +34,8 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
|
|||||||
if (bridge->part_of(bus))
|
if (bridge->part_of(bus))
|
||||||
return bridge->bdf();
|
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,
|
void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user