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 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()) {
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))
return i->_gsi;
}

View File

@ -28,31 +28,32 @@ namespace Platform { namespace Pci { struct Bdf; struct Config; } }
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> { };
struct Device : Bitfield< 3, 5> { };
struct Bus : Bitfield< 8, 8> { };
};
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);
return Bdf { .bus = (bdf >> 8) & 0xffu,
.device = (bdf >> 3) & 0x1fu,
.function = bdf & 0x07u };
}
uint8_t bus() const { return Bdf_register::Bus::get(bdf); }
uint8_t device() const { return Bdf_register::Device::get(bdf); }
uint8_t function() const { return Bdf_register::Function::get(bdf); }
uint16_t value() const {
return ((bus & 0xff) << 8) | ((device & 0x1f) << 3) | (function & 7); }
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 {
class Config_access
@ -69,7 +70,7 @@ namespace Platform {
*/
unsigned _dev_base(Pci::Bdf const bdf)
{
return unsigned(bdf.bdf) << 12;
return unsigned(bdf.value()) << 12;
}
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
*/
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;
_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,
unsigned char *fn) override
{
*bus = _device_config.bdf().bus();
*dev = _device_config.bdf().device();
*fn = _device_config.bdf().function();
*bus = _device_config.bdf().bus;
*dev = _device_config.bdf().device;
*fn = _device_config.bdf().function;
}
unsigned short vendor_id() override { return _device_config.vendor_id(); }

View File

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

View File

@ -82,8 +82,8 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
bool match(Pci::Bdf const bdf)
{
return bdf.bus() == _bus && bdf.device() == _dev &&
bdf.function() == _func;
return bdf.bus == _bus && bdf.device == _dev &&
bdf.function == _func;
}
};
@ -172,7 +172,7 @@ class Platform::Pci_buses
* \retval true 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,
Config_access *config_access)
{
@ -184,7 +184,7 @@ class Platform::Pci_buses
for (; function < Device_config::MAX_FUNCTIONS; function++) {
/* 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);
if (config.valid()) {
@ -345,29 +345,14 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
&& node.has_attribute("function");
}
struct Bdf
static Pci::Bdf _bdf_from_xml(Xml_node node)
{
unsigned b, d, f;
bool equals(Bdf const &other) const
{
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) };
return Pci::Bdf { .bus = node.attribute_value("bus", 0U),
.device = node.attribute_value("device", 0U),
.function = 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)
&& (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);
}
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
*/
bool permit_device(Bdf const bdf, unsigned class_code)
bool permit_device(Pci::Bdf const bdf, unsigned const class_code)
{
using namespace Genode;
@ -447,7 +432,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
/**
* 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;
@ -574,7 +559,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
throw Genode::Service_denied();
}
Bdf const bdf = _bdf_from_xml(node);
Pci::Bdf const bdf = _bdf_from_xml(node);
enum { DOUBLET = false };
if (find_dev_in_policy(bdf, DOUBLET)) {
@ -662,9 +647,9 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
if (prev) {
Device_config config = prev->device_config();
bus = config.bdf().bus();
device = config.bdf().device();
function = config.bdf().function();
bus = config.bdf().bus;
device = config.bdf().device;
function = config.bdf().function;
}
/*
@ -680,18 +665,18 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
return Device_capability();
/* get new bdf values */
bus = config.bdf().bus();
device = config.bdf().device();
function = config.bdf().function();
bus = config.bdf().bus;
device = config.bdf().device;
function = config.bdf().function;
/* if filter of driver don't match skip and continue */
if ((config.class_code() ^ device_class) & class_mask)
continue;
/* check that policy permit access to the matched device */
if (permit_device(Bdf { (unsigned)bus,
(unsigned)device,
(unsigned)function },
if (permit_device(Pci::Bdf { (unsigned)bus,
(unsigned)device,
(unsigned)function },
config.class_code()))
break;
}
@ -713,12 +698,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
try {
/* 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,
" is used by more than one driver - "
"session '", _label, "'.");
else
bdf_in_use.set(config.bdf().bdf, 1);
bdf_in_use.set(config.bdf().value(), 1);
return _env.ep().rpc_ep().manage(dev);
} catch (...) {
@ -740,8 +725,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
return;
if (device->device_config().valid()) {
if (bdf_in_use.get(device->device_config().bdf().bdf, 1))
bdf_in_use.clear(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().value(), 1);
}
_device_list.remove(device);
@ -764,7 +749,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
try {
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())
throw 1;
@ -776,7 +761,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
}
_device_pd.assign_pci(_pciconf.cap(), base_offset,
device->device_config().bdf().bdf);
device->device_config().bdf().value());
} catch (...) {
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,
base, _heap);
Pci::Bdf const bdf_s(bdf_start);
Pci::Bdf const bdf_l(bdf_start + func_count - 1);
Device_config const bdf_first(bdf_s);
Device_config const bdf_last(bdf_l);
Device_config const bdf_first(Pci::Bdf::from_value(bdf_start));
Device_config const bdf_last(Pci::Bdf::from_value(bdf_start +
func_count - 1));
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("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);
if (bridge.pci_bridge())
/* 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) {
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);
} else
Genode::warning("Root bridge: unknown");
@ -1098,9 +1083,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
&config_access))
return;
bus = config.bdf().bus();
device = config.bdf().device();
function = config.bdf().function();
bus = config.bdf().bus;
device = config.bdf().device;
function = config.bdf().function;
using Genode::String;
using Genode::Hex;

View File

@ -43,11 +43,13 @@ void Platform::Pci_buses::scan_bus(Config_access &config_access,
Device_bars_pool &devices_bars,
unsigned char bus)
{
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
for (unsigned dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (unsigned fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
Pci::Bdf const bdf { .bus = bus, .device = dev, .function = fun };
/* 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 */
if (config.valid()) {