platform_drv: avoid using Register in Bdf type

Issue #3963
This commit is contained in:
Alexander Boettcher 2021-01-08 12:08:44 +01:00 committed by Norman Feske
parent f358fcbda6
commit 14d8627186
6 changed files with 78 additions and 96 deletions

View File

@ -288,10 +288,10 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig
unsigned short Platform::Irq_routing::rewrite(Pci::Bdf const bdf, unsigned char pin) unsigned short Platform::Irq_routing::rewrite(Pci::Bdf const bdf, unsigned char pin)
{ {
unsigned const bridge_bdf_bus = Platform::bridge_bdf(bdf.bus()); unsigned const bridge_bdf_bus = Platform::bridge_bdf(bdf.bus);
for (Irq_routing *i = list()->first(); i; i = i->next()) { for (Irq_routing *i = list()->first(); i; i = i->next()) {
if ((bdf.device() == i->_device) && (pin - 1 == i->_device_pin) && if ((bdf.device == i->_device) && (pin - 1 == i->_device_pin) &&
(i->_bridge_bdf == bridge_bdf_bus)) (i->_bridge_bdf == bridge_bdf_bus))
return i->_gsi; return i->_gsi;
} }

View File

@ -28,31 +28,32 @@ namespace Platform { namespace Pci { struct Bdf; struct Config; } }
struct Platform::Pci::Bdf struct Platform::Pci::Bdf
{ {
struct Bdf_register : Register<16> unsigned bus, device, function;
static Bdf from_value(uint16_t const bdf)
{ {
struct Function : Bitfield< 0, 3> { }; return Bdf { .bus = (bdf >> 8) & 0xffu,
struct Device : Bitfield< 3, 5> { }; .device = (bdf >> 3) & 0x1fu,
struct Bus : Bitfield< 8, 8> { }; .function = bdf & 0x07u };
};
uint16_t bdf;
Bdf(uint16_t bdf) : bdf(bdf) { }
Bdf(unsigned bus, unsigned device, unsigned function) : bdf(0)
{
Bdf_register::Bus::set(bdf, bus);
Bdf_register::Device::set(bdf, device);
Bdf_register::Function::set(bdf, function);
} }
uint8_t bus() const { return Bdf_register::Bus::get(bdf); } uint16_t value() const {
uint8_t device() const { return Bdf_register::Device::get(bdf); } return ((bus & 0xff) << 8) | ((device & 0x1f) << 3) | (function & 7); }
uint8_t function() const { return Bdf_register::Function::get(bdf); }
bool operator == (Bdf const &other) const { return bdf == other.bdf; } bool operator == (Bdf const &other) const {
return value() == other.value(); }
void print(Genode::Output &out) const
{
using Genode::print;
using Genode::Hex;
print(out, Hex(bus, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD),
":", Hex(device, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD),
".", Hex(function, Hex::Prefix::OMIT_PREFIX));
}
}; };
namespace Platform { namespace Platform {
class Config_access class Config_access
@ -69,7 +70,7 @@ namespace Platform {
*/ */
unsigned _dev_base(Pci::Bdf const bdf) unsigned _dev_base(Pci::Bdf const bdf)
{ {
return unsigned(bdf.bdf) << 12; return unsigned(bdf.value()) << 12;
} }
Genode::Bit_array<256> _used { }; Genode::Bit_array<256> _used { };

View File

@ -282,7 +282,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
* as we have no driver which will switch it on again * as we have no driver which will switch it on again
*/ */
if (_device_config.pci_bridge() || if (_device_config.pci_bridge() ||
_device_config.bdf() == Pci::Bdf(Platform::Bridge::root_bridge_bdf)) _device_config.bdf() == Pci::Bdf::from_value(Platform::Bridge::root_bridge_bdf))
return; return;
_device_config.disable_bus_master_dma(_config_access); _device_config.disable_bus_master_dma(_config_access);
@ -554,9 +554,9 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
void bus_address(unsigned char *bus, unsigned char *dev, void bus_address(unsigned char *bus, unsigned char *dev,
unsigned char *fn) override unsigned char *fn) override
{ {
*bus = _device_config.bdf().bus(); *bus = _device_config.bdf().bus;
*dev = _device_config.bdf().device(); *dev = _device_config.bdf().device;
*fn = _device_config.bdf().function(); *fn = _device_config.bdf().function;
} }
unsigned short vendor_id() override { return _device_config.vendor_id(); } unsigned short vendor_id() override { return _device_config.vendor_id(); }

View File

@ -174,7 +174,8 @@ namespace Platform {
/** /**
* Constructor * Constructor
*/ */
Device_config() : _bdf(0, 0, 0), _vendor_id(INVALID_VENDOR) { } Device_config() : _bdf({ .bus = 0, .device = 0, .function = 0 }) {
_vendor_id = INVALID_VENDOR; }
Device_config(Pci::Bdf bdf) : _bdf(bdf) { } Device_config(Pci::Bdf bdf) : _bdf(bdf) { }
@ -198,8 +199,8 @@ namespace Platform {
* device. Note, the mf bit of function 1-7 is not significant * device. Note, the mf bit of function 1-7 is not significant
* and may be set or unset. * and may be set or unset.
*/ */
if (bdf.function() != 0) { if (bdf.function != 0) {
Pci::Bdf const dev(bdf.bus(), bdf.device(), 0); Pci::Bdf const dev { .bus = bdf.bus, .device = bdf.device, .function = 0 };
if (!(pci_config->read(dev, 0xe, Device::ACCESS_8BIT) & 0x80)) { if (!(pci_config->read(dev, 0xe, Device::ACCESS_8BIT) & 0x80)) {
_vendor_id = INVALID_VENDOR; _vendor_id = INVALID_VENDOR;
return; return;
@ -270,14 +271,7 @@ namespace Platform {
*/ */
Pci::Bdf bdf() const { return _bdf; } Pci::Bdf bdf() const { return _bdf; }
void print(Genode::Output &out) const void print(Genode::Output &out) const { Genode::print(out, bdf()); }
{
using Genode::print;
using Genode::Hex;
print(out, Hex(_bdf.bus(), Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD),
":", Hex(_bdf.device(), Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD),
".", Hex(_bdf.function(), Hex::Prefix::OMIT_PREFIX));
}
/** /**
* Accessor functions for device information * Accessor functions for device information
@ -393,8 +387,8 @@ namespace Platform {
Genode::addr_t lookup_config_space(Pci::Bdf const bdf) Genode::addr_t lookup_config_space(Pci::Bdf const bdf)
{ {
if ((_bdf_start <= bdf.bdf) && (bdf.bdf <= _bdf_start + _func_count - 1)) if ((_bdf_start <= bdf.value()) && (bdf.value() <= _bdf_start + _func_count - 1))
return _base + (unsigned(bdf.bdf) << 12); return _base + (unsigned(bdf.value()) << 12);
return 0; return 0;
} }
}; };

View File

@ -82,8 +82,8 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
bool match(Pci::Bdf const bdf) bool match(Pci::Bdf const bdf)
{ {
return bdf.bus() == _bus && bdf.device() == _dev && return bdf.bus == _bus && bdf.device == _dev &&
bdf.function() == _func; bdf.function == _func;
} }
}; };
@ -172,7 +172,7 @@ class Platform::Pci_buses
* \retval true device was found * \retval true device was found
* \retval false no device was found * \retval false no device was found
*/ */
bool find_next(int bus, int device, int function, bool find_next(unsigned bus, unsigned device, unsigned function,
Device_config *out_device_config, Device_config *out_device_config,
Config_access *config_access) Config_access *config_access)
{ {
@ -184,7 +184,7 @@ class Platform::Pci_buses
for (; function < Device_config::MAX_FUNCTIONS; function++) { for (; function < Device_config::MAX_FUNCTIONS; function++) {
/* read config space */ /* read config space */
Pci::Bdf const bdf(bus, device, function); Pci::Bdf const bdf { .bus = bus, .device = device, .function = function };
Device_config config(bdf, config_access); Device_config config(bdf, config_access);
if (config.valid()) { if (config.valid()) {
@ -345,29 +345,14 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
&& node.has_attribute("function"); && node.has_attribute("function");
} }
struct Bdf static Pci::Bdf _bdf_from_xml(Xml_node node)
{ {
unsigned b, d, f; return Pci::Bdf { .bus = node.attribute_value("bus", 0U),
.device = node.attribute_value("device", 0U),
bool equals(Bdf const &other) const .function = node.attribute_value("function", 0U) };
{
return other.b == b && other.d == d && other.f == f;
}
void print(Genode::Output &out) const
{
Genode::print(out, Genode::Hex(b), ":", Genode::Hex(d), ".", f);
}
};
static Bdf _bdf_from_xml(Xml_node node)
{
return Bdf { .b = node.attribute_value("bus", 0U),
.d = node.attribute_value("device", 0U),
.f = node.attribute_value("function", 0U) };
} }
static bool _bdf_attributes_in_valid_range(Xml_node node) static bool _bdf_attributes_in_valid_range(Xml_node const &node)
{ {
return _bdf_exactly_specified(node) return _bdf_exactly_specified(node)
&& (node.attribute_value("bus", 0U) < Device_config::MAX_BUSES) && (node.attribute_value("bus", 0U) < Device_config::MAX_BUSES)
@ -375,15 +360,15 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
&& (node.attribute_value("function", 0U) < Device_config::MAX_FUNCTIONS); && (node.attribute_value("function", 0U) < Device_config::MAX_FUNCTIONS);
} }
static bool _bdf_matches(Xml_node node, Bdf bdf) static bool _bdf_matches(Xml_node const &node, Pci::Bdf const &bdf)
{ {
return _bdf_from_xml(node).equals(bdf); return _bdf_from_xml(node) == bdf;
} }
/** /**
* Check according session policy device usage * Check according session policy device usage
*/ */
bool permit_device(Bdf const bdf, unsigned class_code) bool permit_device(Pci::Bdf const bdf, unsigned const class_code)
{ {
using namespace Genode; using namespace Genode;
@ -447,7 +432,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
/** /**
* Lookup a given device name. * Lookup a given device name.
*/ */
bool find_dev_in_policy(Bdf const bdf, bool once = true) bool find_dev_in_policy(Pci::Bdf const bdf, bool once = true)
{ {
using namespace Genode; using namespace Genode;
@ -574,7 +559,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
throw Genode::Service_denied(); throw Genode::Service_denied();
} }
Bdf const bdf = _bdf_from_xml(node); Pci::Bdf const bdf = _bdf_from_xml(node);
enum { DOUBLET = false }; enum { DOUBLET = false };
if (find_dev_in_policy(bdf, DOUBLET)) { if (find_dev_in_policy(bdf, DOUBLET)) {
@ -662,9 +647,9 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
if (prev) { if (prev) {
Device_config config = prev->device_config(); Device_config config = prev->device_config();
bus = config.bdf().bus(); bus = config.bdf().bus;
device = config.bdf().device(); device = config.bdf().device;
function = config.bdf().function(); function = config.bdf().function;
} }
/* /*
@ -680,18 +665,18 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
return Device_capability(); return Device_capability();
/* get new bdf values */ /* get new bdf values */
bus = config.bdf().bus(); bus = config.bdf().bus;
device = config.bdf().device(); device = config.bdf().device;
function = config.bdf().function(); function = config.bdf().function;
/* if filter of driver don't match skip and continue */ /* if filter of driver don't match skip and continue */
if ((config.class_code() ^ device_class) & class_mask) if ((config.class_code() ^ device_class) & class_mask)
continue; continue;
/* check that policy permit access to the matched device */ /* check that policy permit access to the matched device */
if (permit_device(Bdf { (unsigned)bus, if (permit_device(Pci::Bdf { (unsigned)bus,
(unsigned)device, (unsigned)device,
(unsigned)function }, (unsigned)function },
config.class_code())) config.class_code()))
break; break;
} }
@ -713,12 +698,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
try { try {
/* if more than one driver uses the device - warn about */ /* if more than one driver uses the device - warn about */
if (bdf_in_use.get(config.bdf().bdf, 1)) if (bdf_in_use.get(config.bdf().value(), 1))
Genode::error("Device ", config, Genode::error("Device ", config,
" is used by more than one driver - " " is used by more than one driver - "
"session '", _label, "'."); "session '", _label, "'.");
else else
bdf_in_use.set(config.bdf().bdf, 1); bdf_in_use.set(config.bdf().value(), 1);
return _env.ep().rpc_ep().manage(dev); return _env.ep().rpc_ep().manage(dev);
} catch (...) { } catch (...) {
@ -740,8 +725,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
return; return;
if (device->device_config().valid()) { if (device->device_config().valid()) {
if (bdf_in_use.get(device->device_config().bdf().bdf, 1)) if (bdf_in_use.get(device->device_config().bdf().value(), 1))
bdf_in_use.clear(device->device_config().bdf().bdf, 1); bdf_in_use.clear(device->device_config().bdf().value(), 1);
} }
_device_list.remove(device); _device_list.remove(device);
@ -764,7 +749,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
try { try {
addr_t const base_ecam = Dataspace_client(_pciconf.cap()).phys_addr(); addr_t const base_ecam = Dataspace_client(_pciconf.cap()).phys_addr();
addr_t const base_offset = 0x1000UL * device->device_config().bdf().bdf; addr_t const base_offset = 0x1000UL * device->device_config().bdf().value();
if (base_ecam + base_offset != device->config_space()) if (base_ecam + base_offset != device->config_space())
throw 1; throw 1;
@ -776,7 +761,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
} }
_device_pd.assign_pci(_pciconf.cap(), base_offset, _device_pd.assign_pci(_pciconf.cap(), base_offset,
device->device_config().bdf().bdf); device->device_config().bdf().value());
} catch (...) { } catch (...) {
Genode::error("assignment to device pd or of RMRR region failed"); Genode::error("assignment to device pd or of RMRR region failed");
@ -863,11 +848,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
Session_component::add_config_space(bdf_start, func_count, Session_component::add_config_space(bdf_start, func_count,
base, _heap); base, _heap);
Pci::Bdf const bdf_s(bdf_start); Device_config const bdf_first(Pci::Bdf::from_value(bdf_start));
Pci::Bdf const bdf_l(bdf_start + func_count - 1); Device_config const bdf_last(Pci::Bdf::from_value(bdf_start +
func_count - 1));
Device_config const bdf_first(bdf_s);
Device_config const bdf_last(bdf_l);
addr_t const memory_size = 0x1000UL * func_count; addr_t const memory_size = 0x1000UL * func_count;
@ -947,7 +930,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
path.attribute("dev") .value(dev); path.attribute("dev") .value(dev);
path.attribute("func").value(func); path.attribute("func").value(func);
Pci::Bdf const bdf(bus, dev, func); Pci::Bdf const bdf = { .bus = bus, .device = dev,
.function = func };
Device_config bridge(bdf, &config_access); Device_config bridge(bdf, &config_access);
if (bridge.pci_bridge()) if (bridge.pci_bridge())
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */ /* PCI bridge spec 3.2.5.3, 3.2.5.4 */
@ -1073,7 +1058,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
} }
if (Platform::Bridge::root_bridge_bdf < Platform::Bridge::INVALID_ROOT_BRIDGE) { if (Platform::Bridge::root_bridge_bdf < Platform::Bridge::INVALID_ROOT_BRIDGE) {
Device_config config(Pci::Bdf(Platform::Bridge::root_bridge_bdf)); Device_config config(Pci::Bdf::from_value(Platform::Bridge::root_bridge_bdf));
Genode::log("Root bridge: ", config); Genode::log("Root bridge: ", config);
} else } else
Genode::warning("Root bridge: unknown"); Genode::warning("Root bridge: unknown");
@ -1098,9 +1083,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
&config_access)) &config_access))
return; return;
bus = config.bdf().bus(); bus = config.bdf().bus;
device = config.bdf().device(); device = config.bdf().device;
function = config.bdf().function(); function = config.bdf().function;
using Genode::String; using Genode::String;
using Genode::Hex; using Genode::Hex;

View File

@ -43,11 +43,13 @@ void Platform::Pci_buses::scan_bus(Config_access &config_access,
Device_bars_pool &devices_bars, Device_bars_pool &devices_bars,
unsigned char bus) unsigned char bus)
{ {
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) { for (unsigned dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) { for (unsigned fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
Pci::Bdf const bdf { .bus = bus, .device = dev, .function = fun };
/* read config space */ /* read config space */
Device_config config(Pci::Bdf(bus, dev, fun), &config_access); Device_config config(bdf, &config_access);
/* remember Device BARs required after power off and/or reset */ /* remember Device BARs required after power off and/or reset */
if (config.valid()) { if (config.valid()) {