platform_drv: add PCI device support

* Parse PCI specific information from devices ROM
* Enable DMA, I/O memory and I/O port access dependent on BARs in config space
* Introduce device PD for Nova + IOMMU support
* Enable MSIs if available
* Add PCI specific policy rules

Fixes genodelabs/genode#4502
This commit is contained in:
Stefan Kalkowski 2022-05-03 13:36:27 +02:00 committed by Christian Helmuth
parent 6b92006565
commit 9370e5e4d0
14 changed files with 613 additions and 32 deletions

View File

@ -47,6 +47,21 @@ ROM will contain detailed information about physical resources of the devices
of its virtual bus. This is only useful when using ported legacy drivers, which
operate with global names of physical resources.
Policy for PCI devices
----------------------
Policies for PCI devices do not necessarily need to state the name of
the device, but can either state a class of devices, or a vendor/device
pair of identifiers inside a pci sub-node:
! <config>
! <policy label="usb_drv -> ">
! <pci class="USB"/>
! </policy>
! <policy label="nvme_drv -> ">
! <pci vendor_id="0x1987" device_id="0x5007"/>
! </policy>
Report facilities
-----------------

View File

@ -12,6 +12,7 @@
*/
#include <device.h>
#include <pci.h>
#include <device_component.h>
#include <session_component.h>
@ -78,6 +79,7 @@ void Driver::Device::acquire(Session_component & sc)
}
});
pci_enable(sc.env(), sc.device_pd(), *this);
sc.update_devices_rom();
sc.devices().update_report();
}
@ -88,6 +90,8 @@ void Driver::Device::release(Session_component & sc)
if (!(_owner == sc))
return;
pci_disable(sc.env(), *this);
_reset_domain_list.for_each([&] (Reset_domain & r)
{
sc.devices().resets().apply(r.name, [&] (Driver::Reset &reset) {
@ -156,6 +160,13 @@ void Driver::Device::report(Xml_generator & xml, Device_model & devices,
});
});
});
_pci_config_list.for_each([&] (Pci_config &pci) {
xml.node("pci-config", [&] () {
xml.attribute("vendor_id", String<16>(Hex(pci.vendor_id)));
xml.attribute("device_id", String<16>(Hex(pci.device_id)));
xml.attribute("class", String<16>(Hex(pci.class_code)));
});
});
_report_platform_specifics(xml, devices);
});

View File

@ -11,12 +11,13 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_
#ifndef _SRC__DRIVERS__PLATFORM__DEVICE_H_
#define _SRC__DRIVERS__PLATFORM__DEVICE_H_
#include <base/allocator.h>
#include <base/heap.h>
#include <os/reporter.h>
#include <pci/types.h>
#include <platform_session/device.h>
#include <util/list.h>
#include <util/list_model.h>
@ -41,6 +42,7 @@ namespace Driver {
struct Clock_update_policy;
struct Reset_domain_update_policy;
struct Power_domain_update_policy;
struct Pci_config_update_policy;
}
@ -141,6 +143,36 @@ class Driver::Device : private List_model<Device>::Element
Reset_domain(Name name) : name(name) {}
};
struct Pci_config : List_model<Pci_config>::Element
{
addr_t addr;
Pci::bus_t bus_num;
Pci::dev_t dev_num;
Pci::func_t func_num;
Pci::vendor_t vendor_id;
Pci::device_t device_id;
Pci::class_t class_code;
bool bridge;
Pci_config(addr_t addr,
Pci::bus_t bus_num,
Pci::dev_t dev_num,
Pci::func_t func_num,
Pci::vendor_t vendor_id,
Pci::device_t device_id,
Pci::class_t class_code,
bool bridge)
:
addr(addr),
bus_num(bus_num),
dev_num(dev_num),
func_num(func_num),
vendor_id(vendor_id),
device_id(device_id),
class_code(class_code),
bridge(bridge) {}
};
Device(Name name, Type type);
virtual ~Device();
@ -155,7 +187,7 @@ class Driver::Device : private List_model<Device>::Element
{
unsigned idx = 0;
_irq_list.for_each([&] (Irq const & irq) {
fn(idx++, irq.number, irq.type, irq.polarity, irq.mode, 0); });
fn(idx++, irq.number, irq.type, irq.polarity, irq.mode); });
}
template <typename FN> void for_each_io_mem(FN const & fn)
@ -172,6 +204,23 @@ class Driver::Device : private List_model<Device>::Element
fn(idx++, ipr.addr, ipr.size); });
}
template <typename FN> void for_pci_config(FN const & fn)
{
/*
* we allow only one PCI config per device,
* even if more were declared
*/
bool found = false;
_pci_config_list.for_each([&] (Pci_config const & cfg) {
if (found) {
warning("Only one pci-config is supported per device!");
return;
}
found = true;
fn(cfg);
});
}
void report(Xml_generator &, Device_model &, bool);
protected:
@ -193,6 +242,7 @@ class Driver::Device : private List_model<Device>::Element
List_model<Clock> _clock_list {};
List_model<Power_domain> _power_domain_list {};
List_model<Reset_domain> _reset_domain_list {};
List_model<Pci_config> _pci_config_list {};
/*
* Noncopyable
@ -487,4 +537,48 @@ struct Driver::Reset_domain_update_policy
}
};
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ */
struct Driver::Pci_config_update_policy
: Genode::List_model<Device::Pci_config>::Update_policy
{
Genode::Allocator & alloc;
Pci_config_update_policy(Genode::Allocator & alloc) : alloc(alloc) {}
void destroy_element(Element & pd) {
Genode::destroy(alloc, &pd); }
Element & create_element(Genode::Xml_node node)
{
using namespace Pci;
addr_t addr = node.attribute_value("address", ~0UL);
bus_t bus_num = node.attribute_value<bus_t>("bus", 0);
dev_t dev_num = node.attribute_value<dev_t>("device", 0);
func_t func_num = node.attribute_value<func_t>("function", 0);
vendor_t vendor_id = node.attribute_value<vendor_t>("vendor_id",
0xffff);
device_t device_id = node.attribute_value<device_t>("device_id",
0xffff);
class_t class_code = node.attribute_value<class_t>("class", 0xff);
bool bridge = node.attribute_value("bridge", false);
return *(new (alloc) Element(addr, bus_num, dev_num, func_num,
vendor_id, device_id, class_code, bridge));
}
void update_element(Element &, Genode::Xml_node) {}
static bool element_matches_xml_node(Element const & e, Genode::Xml_node node)
{
addr_t addr = node.attribute_value("address", ~0UL);
return addr == e.addr;
}
static bool node_is_element(Genode::Xml_node node)
{
return node.has_type("pci-config");
}
};
#endif /* _SRC__DRIVERS__PLATFORM__DEVICE_H_ */

View File

@ -13,6 +13,7 @@
#include <device.h>
#include <device_component.h>
#include <pci.h>
#include <session_component.h>
using Driver::Device_component;
@ -72,19 +73,17 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx)
return;
if (!irq.irq.constructed()) {
/*
* Unfortunately, we have to deliver the PCI config space address
* to the IRQ session for working MSI(-x) on NOVA. It is used
* for IOMMU configuration as some kind of access control
*
* Once, the IOMMU support is solved kernel-independent, this
* attribute has to be removed from the IRQs
*/
addr_t pci_cfg_addr = (irq.type != Device::Irq::LEGACY)
? irq.pci_config_addr : 0;
addr_t pci_cfg_addr = 0;
if (irq.type != Device::Irq::LEGACY) {
if (_pci_config.constructed()) pci_cfg_addr = _pci_config->addr;
else
error("MSI(-x) detected for device without pci-config!");
}
irq.irq.construct(_session.env(), irq.number, irq.mode, irq.polarity,
pci_cfg_addr);
Irq_session::Info info = irq.irq->info();
if (info.type == Irq_session::Info::MSI)
pci_msi_enable(_session.env(), pci_cfg_addr, info);
}
cap = irq.irq->cap();
@ -137,15 +136,13 @@ Device_component::Device_component(Registry<Device_component> & registry,
unsigned nr,
Device::Irq::Type type,
Irq_session::Polarity polarity,
Irq_session::Trigger mode,
addr_t pci_cfg_addr)
Irq_session::Trigger mode)
{
session.ram_quota_guard().withdraw(Ram_quota{Irq_session::RAM_QUOTA});
_ram_quota += Irq_session::RAM_QUOTA;
session.cap_quota_guard().withdraw(Cap_quota{Irq_session::CAP_QUOTA});
_cap_quota += Irq_session::CAP_QUOTA;
new (session.heap()) Irq(_irq_registry, idx, nr, type,
polarity, mode, pci_cfg_addr);
new (session.heap()) Irq(_irq_registry, idx, nr, type, polarity, mode);
});
device.for_each_io_mem([&] (unsigned idx, Range range)
@ -167,6 +164,15 @@ Device_component::Device_component(Registry<Device_component> & registry,
new (session.heap()) Io_port_range(_io_port_range_registry,
idx, addr, size);
});
device.for_pci_config([&] (Device::Pci_config const & cfg)
{
session.ram_quota_guard().withdraw(Ram_quota{Io_mem_session::RAM_QUOTA});
_ram_quota += Io_mem_session::RAM_QUOTA;
session.cap_quota_guard().withdraw(Cap_quota{Io_mem_session::CAP_QUOTA});
_cap_quota += Io_mem_session::CAP_QUOTA;
_pci_config.construct(cfg.addr);
});
} catch(...) {
_release_resources();
throw;

View File

@ -43,7 +43,6 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
Device::Irq::Type type;
Irq_session::Polarity polarity;
Irq_session::Trigger mode;
addr_t pci_config_addr;
Constructible<Irq_connection> irq {};
Irq(Registry<Irq> & registry,
@ -51,13 +50,11 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
unsigned number,
Device::Irq::Type type,
Irq_session::Polarity polarity,
Irq_session::Trigger mode,
addr_t pci_config_addr)
Irq_session::Trigger mode)
:
Registry<Irq>::Element(registry, *this),
idx(idx), number(number), type(type),
polarity(polarity), mode(mode),
pci_config_addr(pci_config_addr) {}
polarity(polarity), mode(mode) {}
};
struct Io_mem : Registry<Io_mem>::Element
@ -90,6 +87,13 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
idx(idx), addr(addr), size(size) {}
};
struct Pci_config
{
addr_t addr;
Pci_config(addr_t addr) : addr(addr) {}
};
Device_component(Registry<Device_component> & registry,
Session_component & session,
Driver::Device & device);
@ -117,6 +121,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
Registry<Irq> _irq_registry {};
Registry<Io_mem> _io_mem_registry {};
Registry<Io_port_range> _io_port_range_registry {};
Constructible<Pci_config> _pci_config {};
void _release_resources();

View File

@ -53,6 +53,11 @@ void Device_model::destroy_element(Device & device)
device._reset_domain_list.destroy_all_elements(policy);
}
{
Pci_config_update_policy policy(_heap);
device._pci_config_list.destroy_all_elements(policy);
}
Genode::destroy(_heap, &device);
}
@ -102,4 +107,9 @@ void Device_model::update_element(Device & device,
Reset_domain_update_policy policy(_heap);
device._reset_domain_list.update_from_xml(policy, node);
}
{
Pci_config_update_policy policy(_heap);
device._pci_config_list.update_from_xml(policy, node);
}
}

View File

@ -0,0 +1,135 @@
/*
* \brief Pci device protection for platform driver
* \author Alexander Boettcher
* \author Stefan Kalkowski
* \date 2013-02-10
*/
/*
* Copyright (C) 2013-2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <dataspace/client.h>
#include <region_map/client.h>
#include <pd_session/client.h>
#include <util/retry.h>
#include <device_pd.h>
using namespace Driver;
Device_pd::Region_map_client::Local_addr
Device_pd::Region_map_client::attach(Dataspace_capability ds,
size_t size,
off_t offset,
bool use_local_addr,
Local_addr local_addr,
bool executable,
bool writeable)
{
return retry<Out_of_ram>(
[&] () {
return retry<Out_of_caps>(
[&] () {
return Genode::Region_map_client::attach(ds, size, offset,
use_local_addr,
local_addr,
executable,
writeable); },
[&] () {
upgrade_caps();
}
);
},
[&] () { upgrade_ram(); }
);
}
void Device_pd::Region_map_client::upgrade_ram()
{
Ram_quota const ram { 4096 };
_ram_guard.withdraw(ram);
_env.pd().transfer_quota(_pd.rpc_cap(), ram);
}
void Device_pd::Region_map_client::upgrade_caps()
{
Cap_quota const caps { 2 };
_cap_guard.withdraw(caps);
_env.pd().transfer_quota(_pd.rpc_cap(), caps);
}
void Device_pd::attach_dma_mem(Dataspace_capability ds_cap,
addr_t const dma_addr)
{
using namespace Genode;
bool retry = false;
Dataspace_client ds_client(ds_cap);
do {
_pd.attach_dma(ds_cap, dma_addr).with_result(
[&] (Pd_session::Attach_dma_ok) {
/* trigger eager mapping of memory */
_pd.map(dma_addr, ds_client.size());
retry = false;
},
[&] (Pd_session::Attach_dma_error e) {
switch (e) {
case Pd_session::Attach_dma_error::OUT_OF_RAM:
_address_space.upgrade_ram();
retry = true;
break;
case Pd_session::Attach_dma_error::OUT_OF_CAPS:
_address_space.upgrade_caps();
retry = true;
break;
case Pd_session::Attach_dma_error::DENIED:
_address_space.detach(dma_addr);
error("Device PD: attach_dma denied!");
break;
}
}
);
} while (retry);
}
void Device_pd::assign_pci(Io_mem_dataspace_capability const io_mem_cap,
Pci::Bdf const bdf)
{
addr_t addr = _address_space.attach(io_mem_cap, 0x1000);
/* sanity check */
if (!addr)
throw Region_map::Region_conflict();
/* trigger eager mapping of memory */
_pd.map(addr, 0x1000);
/* try to assign pci device to this protection domain */
if (!_pd.assign_pci(addr, Pci::Bdf::rid(bdf)))
error("Assignment of PCI device ", bdf, " to device PD failed!");
/* we don't need the mapping anymore */
_address_space.detach(addr);
}
Device_pd::Device_pd(Env & env,
Ram_quota_guard & ram_guard,
Cap_quota_guard & cap_guard)
:
_pd(env, Pd_connection::Device_pd()),
_address_space(env, _pd, ram_guard, cap_guard)
{
_pd.ref_account(env.pd_session_cap());
}

View File

@ -0,0 +1,83 @@
/*
* \brief Device PD handling for the platform driver
* \author Alexander Boettcher
* \date 2015-11-05
*/
/*
* Copyright (C) 2015-2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__PLATFORM__DEVICE_PD_H_
#define _SRC__DRIVERS__PLATFORM__DEVICE_PD_H_
/* base */
#include <base/env.h>
#include <base/quota_guard.h>
#include <region_map/client.h>
#include <pci/types.h>
#include <pd_session/connection.h>
#include <io_mem_session/capability.h>
namespace Driver {
using namespace Genode;
class Device_pd;
}
class Driver::Device_pd
{
private:
Pd_connection _pd;
/**
* Custom handling of PD-session depletion during attach operations
*
* The default implementation of 'env.rm()' automatically issues a resource
* request if the PD session quota gets exhausted. For the device PD, we don't
* want to issue resource requests but let the platform driver reflect this
* condition to its client.
*/
struct Region_map_client : Genode::Region_map_client
{
Env & _env;
Pd_connection & _pd;
Ram_quota_guard & _ram_guard;
Cap_quota_guard & _cap_guard;
Region_map_client(Env & env,
Pd_connection & pd,
Ram_quota_guard & ram_guard,
Cap_quota_guard & cap_guard)
:
Genode::Region_map_client(pd.address_space()),
_env(env), _pd(pd),
_ram_guard(ram_guard), _cap_guard(cap_guard)
{ }
Local_addr attach(Dataspace_capability ds,
size_t size = 0,
off_t offset = 0,
bool use_local_addr = false,
Local_addr local_addr = (void *)0,
bool executable = false,
bool writeable = true) override;
void upgrade_ram();
void upgrade_caps();
} _address_space;
public:
Device_pd(Env &env,
Ram_quota_guard &ram_guard,
Cap_quota_guard &cap_guard);
void attach_dma_mem(Dataspace_capability, addr_t dma_addr);
void assign_pci(Io_mem_dataspace_capability const, Pci::Bdf const);
};
#endif /* _SRC__DRIVERS__PLATFORM__DEVICE_PD_H_ */

View File

@ -0,0 +1,165 @@
/*
* \brief Platform driver - PCI helper utilities
* \author Stefan Kalkowski
* \date 2022-05-02
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/attached_io_mem_dataspace.h>
#include <pci/config.h>
#include <util/reconstructible.h>
#include <device.h>
#include <device_pd.h>
#include <pci.h>
using namespace Genode;
using namespace Pci;
struct Config_helper
{
Driver::Device & _dev;
Driver::Device::Pci_config const & _cfg;
Attached_io_mem_dataspace _io_mem;
Config _config { (addr_t)_io_mem.local_addr<void>() };
Config_helper(Env & env,
Driver::Device & dev,
Driver::Device::Pci_config const & cfg)
: _dev(dev), _cfg(cfg), _io_mem(env, cfg.addr, 0x1000) { }
void enable(Driver::Device_pd & pd)
{
pd.assign_pci(_io_mem.cap(),
{ _cfg.bus_num, _cfg.dev_num, _cfg.func_num });
Config::Command::access_t cmd =
_config.read<Config::Command>();
/* always allow DMA operations */
Config::Command::Bus_master_enable::set(cmd, 1);
/* enable memory space when I/O mem is defined */
_dev.for_each_io_mem([&] (unsigned, Driver::Device::Range) {
Config::Command::Memory_space_enable::set(cmd, 1); });
/* enable i/o space when I/O ports are defined */
_dev.for_each_io_port_range([&] (unsigned, uint16_t, uint16_t) {
Config::Command::Io_space_enable::set(cmd, 1); });
_config.write<Config::Command>(cmd);
}
void disable()
{
Config::Command::access_t cmd =
_config.read<Config::Command>();
Config::Command::Io_space_enable::set(cmd, 0);
Config::Command::Memory_space_enable::set(cmd, 0);
Config::Command::Bus_master_enable::set(cmd, 0);
Config::Command::Interrupt_enable::set(cmd, 0);
_config.write<Config::Command>(cmd);
}
};
void Driver::pci_enable(Env & env, Device_pd & pd, Device & dev)
{
dev.for_pci_config([&] (Device::Pci_config const & pc) {
Config_helper(env, dev, pc).enable(pd); });
}
void Driver::pci_disable(Env & env, Device & dev)
{
dev.for_pci_config([&] (Device::Pci_config const & pc) {
Config_helper(env, dev, pc).disable(); });
}
void Driver::pci_msi_enable(Env & env, addr_t cfg_space, Irq_session::Info info)
{
Attached_io_mem_dataspace io_mem { env, cfg_space, 0x1000 };
Config config { (addr_t)io_mem.local_addr<void>() };
config.scan();
if (config.msi_cap.constructed())
config.msi_cap->enable(info.address, (uint16_t)info.value);
else error("Device does not support MSI(-x)!");
}
static inline String<16>
pci_class_code_alias(uint32_t class_code)
{
enum { WILDCARD = 0xff };
uint8_t const b = (class_code >> 16) & 0xff;
uint8_t const s = (class_code >> 8) & 0xff;
uint8_t const i = class_code & 0xff;
static struct Alias
{
String<16> name;
uint8_t base;
uint8_t sub;
uint8_t iface;
bool matches(uint8_t b, uint8_t s, uint8_t i) const
{
return (base == WILDCARD || base == b) &&
(sub == WILDCARD || sub == s) &&
(iface == WILDCARD || iface == i);
}
} const aliases [] = {
{ "NVME" , 0x01, 0x08, 0x02 },
{ "USB" , 0x0c, 0x03, 0x00 }, /* UHCI */
{ "USB" , 0x0c, 0x03, 0x10 }, /* OHCI */
{ "USB" , 0x0c, 0x03, 0x20 }, /* EHCI */
{ "USB" , 0x0c, 0x03, 0x30 }, /* XHCI */
{ "VGA" , 0x03, 0x00, 0x00 },
{ "AHCI" , 0x01, 0x06, WILDCARD },
{ "AUDIO" , 0x04, 0x01, WILDCARD },
{ "ETHERNET" , 0x02, 0x00, WILDCARD },
{ "HDAUDIO" , 0x04, 0x03, WILDCARD },
{ "ISABRIDGE", 0x06, 0x01, WILDCARD },
{ "WIFI" , 0x02, 0x80, WILDCARD },
};
for (Alias const & alias : aliases)
if (alias.matches(b, s, i))
return alias.name;
return "ALL";
}
bool Driver::pci_device_matches(Session_policy const & policy, Device & dev)
{
bool ret = false;
policy.for_each_sub_node("pci", [&] (Xml_node node)
{
if (dev.type() != "pci")
return;
String<16> class_code = node.attribute_value("class", String<16>());
vendor_t vendor_id = node.attribute_value<vendor_t>("vendor_id", 0);
device_t device_id = node.attribute_value<device_t>("device_id", 0);
dev.for_pci_config([&] (Device::Pci_config cfg)
{
if ((pci_class_code_alias(cfg.class_code) == class_code) ||
(vendor_id == cfg.vendor_id && device_id == cfg.device_id))
ret = true;
});
});
return ret;
}

View File

@ -0,0 +1,33 @@
/*
* \brief Platform driver - PCI helper utilities
* \author Stefan Kalkowski
* \date 2022-05-02
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__PLATFORM__PCI_H_
#define _SRC__DRIVERS__PLATFORM__PCI_H_
#include <base/env.h>
#include <irq_session/irq_session.h>
#include <os/session_policy.h>
namespace Driver {
class Device;
class Device_pd;
void pci_enable(Genode::Env & env, Device_pd & pd, Device & dev);
void pci_disable(Genode::Env & env, Device & dev);
void pci_msi_enable(Genode::Env & env, addr_t cfg_space,
Genode::Irq_session::Info info);
bool pci_device_matches(Genode::Session_policy const & policy,
Device & dev);
}
#endif /* _SRC__DRIVERS__PLATFORM__PCI_H_ */

View File

@ -11,8 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_
#ifndef _SRC__DRIVERS__PLATFORM__ROOT_H_
#define _SRC__DRIVERS__PLATFORM__ROOT_H_
#include <base/attached_rom_dataspace.h>
#include <base/registry.h>
@ -46,4 +46,4 @@ class Driver::Root : public Root_component<Session_component>
Registry<Session_component> _sessions {};
};
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__ROOT_H_ */
#endif /* _SRC__DRIVERS__PLATFORM__ROOT_H_ */

View File

@ -14,6 +14,7 @@
#include <dataspace/client.h>
#include <device.h>
#include <pci.h>
#include <session_component.h>
using Driver::Session_component;
@ -54,6 +55,12 @@ bool Session_component::matches(Device & dev) const
try {
Session_policy const policy { label(), _config.xml() };
/* check PCI devices */
if (pci_device_matches(policy, dev))
return true;
/* check for dedicated device name */
policy.for_each_sub_node("device", [&] (Xml_node node) {
if (dev.name() == node.attribute_value("name", Device::Name()))
ret = true;
@ -114,6 +121,9 @@ Driver::Device_model & Session_component::devices() { return _devices; }
Genode::Heap & Session_component::heap() { return _md_alloc; }
Driver::Device_pd & Session_component::device_pd() { return _device_pd; }
void Session_component::update_devices_rom()
{
_rom_session.trigger_update();
@ -175,7 +185,9 @@ Session_component::alloc_dma_buffer(size_t const size, Cache cache)
if (!ram_cap.valid()) return ram_cap;
try {
new (heap()) Dma_buffer(_buffer_registry, ram_cap);
Dma_buffer & buf =
*(new (heap()) Dma_buffer(_buffer_registry, ram_cap));
_device_pd.attach_dma_mem(ram_cap, _env.pd().dma_addr(buf.cap));
} catch (Out_of_ram) {
_env_ram.free(ram_cap);
throw;

View File

@ -11,8 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_
#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_
#ifndef _SRC__DRIVERS__PLATFORM__SESSION_COMPONENT_H_
#define _SRC__DRIVERS__PLATFORM__SESSION_COMPONENT_H_
#include <base/attached_rom_dataspace.h>
#include <base/env.h>
@ -25,6 +25,7 @@
#include <platform_session/platform_session.h>
#include <device_component.h>
#include <device_pd.h>
namespace Driver {
class Session_component;
@ -58,6 +59,7 @@ class Driver::Session_component
Env & env();
Heap & heap();
Device_model & devices();
Device_pd & device_pd();
bool matches(Device &) const;
void update_devices_rom();
@ -110,6 +112,9 @@ class Driver::Session_component
_env.rm(), *this };
bool _info;
Policy_version _version;
Device_pd _device_pd { _env,
_ram_quota_guard(),
_cap_quota_guard() };
Device_capability _acquire(Device & device);
void _release_device(Device_component & dc);
@ -129,4 +134,4 @@ class Driver::Session_component
void produce_xml(Xml_generator &xml) override;
};
#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ */
#endif /* _SRC__DRIVERS__PLATFORM__SESSION_COMPONENT_H_ */

View File

@ -1,4 +1,11 @@
TARGET = platform_drv
SRC_CC = device.cc device_component.cc device_model_policy.cc main.cc session_component.cc root.cc
SRC_CC += device.cc
SRC_CC += device_component.cc
SRC_CC += device_model_policy.cc
SRC_CC += device_pd.cc
SRC_CC += main.cc
SRC_CC += pci.cc
SRC_CC += root.cc
SRC_CC += session_component.cc
INC_DIR = $(PRG_DIR)
LIBS = base