platform_drv: remove deprecated env() usage

Issue #1987
This commit is contained in:
Alexander Boettcher 2017-01-02 14:23:03 +01:00 committed by Norman Feske
parent 658547d058
commit dd8e13d6fa
12 changed files with 269 additions and 394 deletions

View File

@ -30,7 +30,7 @@
/**
* Custom handling of PD-session depletion during attach operations
*
* The default implementation of 'env().rm()' automatically issues a resource
* 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.
@ -59,7 +59,7 @@ struct Expanding_region_map_client : Genode::Region_map_client
[&] () {
enum { UPGRADE_QUOTA = 4096 };
if (Genode::env()->ram_session()->avail() < UPGRADE_QUOTA)
if (_env.ram().avail() < UPGRADE_QUOTA)
throw;
Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_QUOTA);
@ -172,7 +172,7 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili
};
/* try to assign pci device to this protection domain */
if (!env()->pd_session()->assign_pci(page, rid))
if (!_env.pd().assign_pci(page, rid))
Genode::error("assignment of PCI device ", Rid(rid), " failed ",
"phys=", Genode::Hex(ds_client.phys_addr()), " "
"virt=", Genode::Hex(page));
@ -190,7 +190,7 @@ struct Main
Expanding_region_map_client rm { env };
Platform::Device_pd_component pd_component { rm };
Platform::Device_pd_component pd_component { rm, env };
Genode::Static_root<Platform::Device_pd> root { env.ep().manage(pd_component) };

View File

@ -24,7 +24,6 @@
namespace Platform {
class Irq_component;
class Irq_allocator;
class Irq_thread;
}
@ -32,9 +31,9 @@ using Genode::size_t;
using Genode::addr_t;
/**
* A simple range allocator implementation used by the Irq_proxy
* A simple allocator implementation used by the Irq_proxy
*/
class Platform::Irq_allocator : public Genode::Range_allocator
class Platform::Irq_allocator
{
private:
@ -64,76 +63,13 @@ class Platform::Irq_allocator : public Genode::Range_allocator
void free_msi(unsigned msi) { _msi.free(msi); }
Alloc_return alloc_addr(size_t size, addr_t addr) override
bool alloc_irq(addr_t addr)
{
try {
_legacy.set(addr, size);
return Alloc_return::OK;
_legacy.set(addr, 1);
return true;
} catch (...) {
return Alloc_return::RANGE_CONFLICT;
}
}
/* unused methods */
int remove_range(addr_t, size_t) override { return 0; }
int add_range(addr_t, size_t) override { return 0; }
bool valid_addr(addr_t) const override { return false; }
size_t avail() const override { return 0; }
bool alloc(size_t, void **) override { return false; }
void free(void *) override { }
void free(void *, size_t) override { }
size_t overhead(size_t) const override { return 0; }
bool need_size_for_free() const override { return 0; }
Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) override {
return Alloc_return::RANGE_CONFLICT; }
};
/**
* Required by Irq_proxy if we would like to have a thread per IRQ,
* which we don't want to in the platform driver - one thread is sufficient.
*/
class NoThread
{
public:
NoThread(const char *) { }
void start(void) { }
};
/**
* Thread waiting for signals caused by IRQs
*/
class Platform::Irq_thread : public Genode::Thread_deprecated<4096>
{
private:
Genode::Signal_receiver _sig_rec;
public:
Irq_thread() : Thread_deprecated<4096>("irq_sig_recv") { start(); }
Genode::Signal_receiver & sig_rec() { return _sig_rec; }
void entry() {
typedef Genode::Signal_dispatcher_base Sdb;
while (1) {
Genode::Signal sig = _sig_rec.wait_for_signal();
Sdb *dispatcher = dynamic_cast<Sdb *>(sig.context());
if (!dispatcher) {
Genode::error("dispatcher missing for signal ",
sig.context(), " ", sig.num());
continue;
}
dispatcher->dispatch(sig.num());
return false;
}
}
};
@ -144,20 +80,17 @@ class Platform::Irq_thread : public Genode::Thread_deprecated<4096>
* for Genode signals of all hardware IRQs.
*/
static Platform::Irq_allocator irq_alloc;
static Platform::Irq_thread irq_thread;
/**
* Irq_proxy interface implementation
*/
typedef Genode::Irq_proxy<NoThread> Proxy;
class Platform::Irq_component : public Proxy
class Platform::Irq_component : public Platform::Irq_proxy
{
private:
Genode::Irq_connection _irq;
Genode::Signal_dispatcher<Platform::Irq_component> _irq_dispatcher;
Genode::Signal_handler<Platform::Irq_component> _irq_dispatcher;
bool _associated;
@ -178,11 +111,8 @@ class Platform::Irq_component : public Proxy
_irq.ack_irq();
}
bool _associate() { return _associated; }
void _wait_for_irq() { }
virtual bool remove_sharer(Genode::Irq_sigh *s) override {
if (!Proxy::remove_sharer(s))
virtual bool remove_sharer(Platform::Irq_sigh *s) override {
if (!Irq_proxy::remove_sharer(s))
return false;
/* De-associate handler. */
@ -193,15 +123,42 @@ class Platform::Irq_component : public Proxy
public:
Irq_component(unsigned gsi, Genode::Irq_session::Trigger trigger,
Irq_component(Genode::Env &env, unsigned gsi,
Genode::Irq_session::Trigger trigger,
Genode::Irq_session::Polarity polarity)
:
Proxy(gsi),
_irq(gsi, trigger, polarity),
_irq_dispatcher(irq_thread.sig_rec(), *this,
&::Proxy::notify_about_irq),
Irq_proxy(gsi),
_irq(env, gsi, trigger, polarity),
_irq_dispatcher(env.ep(), *this, &Platform::Irq_proxy::notify_about_irq),
_associated(false)
{ }
static Irq_component *get_irq_proxy(unsigned irq_number,
Irq_allocator *irq_alloc = nullptr,
Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED,
Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED,
Genode::Env *env = nullptr,
Genode::Allocator *heap = nullptr)
{
static Genode::List<Irq_proxy> proxies;
static Genode::Lock proxies_lock;
Genode::Lock::Guard lock_guard(proxies_lock);
/* lookup proxy in database */
for (Irq_proxy *p = proxies.first(); p; p = p->next())
if (p->irq_number() == irq_number)
return static_cast<Irq_component *>(p);
/* try to create proxy */
if (!irq_alloc || !env || !heap || !irq_alloc->alloc_irq(irq_number))
return 0;
Irq_component *new_proxy = new (heap) Irq_component(*env, irq_number, trigger,
polarity);
proxies.insert(new_proxy);
return new_proxy;
}
};
@ -218,7 +175,7 @@ void Platform::Irq_session_component::ack_irq()
}
/* shared irq handling */
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
if (!irq_obj) {
Genode::error("expected to find IRQ proxy for IRQ ", Genode::Hex(_gsi));
return;
@ -230,7 +187,9 @@ void Platform::Irq_session_component::ack_irq()
Platform::Irq_session_component::Irq_session_component(unsigned irq,
addr_t pci_config_space)
addr_t pci_config_space,
Genode::Env &env,
Genode::Allocator &heap)
:
_gsi(irq)
{
@ -245,7 +204,7 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
try {
using namespace Genode;
_irq_conn.construct(msi, Irq_session::TRIGGER_UNCHANGED,
_irq_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED,
Irq_session::POLARITY_UNCHANGED,
pci_config_space);
@ -273,8 +232,8 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
try {
/* check if shared IRQ object was used before */
if (Proxy::get_irq_proxy<Irq_component>(_gsi, &irq_alloc, trigger,
polarity))
if (Irq_component::get_irq_proxy(_gsi, &irq_alloc, trigger,
polarity, &env, &heap))
return;
} catch (Genode::Parent::Service_denied) { }
@ -292,7 +251,7 @@ Platform::Irq_session_component::~Irq_session_component()
}
/* shared irq handling */
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
if (!irq_obj) return;
if (_irq_sigh.valid())
@ -309,7 +268,7 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig
}
/* shared irq handling */
Irq_component *irq_obj = Proxy::get_irq_proxy<Irq_component>(_gsi);
Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi);
if (!irq_obj) {
Genode::error("signal handler got not registered - irq object unavailable");
return;

View File

@ -34,7 +34,7 @@ class Platform::Irq_session_component : public Genode::Rpc_object<Genode::Irq_se
private:
unsigned _gsi;
Genode::Irq_sigh _irq_sigh;
Platform::Irq_sigh _irq_sigh;
Genode::Irq_session::Info _msi_info;
Genode::Constructible<Genode::Irq_connection> _irq_conn;
@ -43,7 +43,8 @@ class Platform::Irq_session_component : public Genode::Rpc_object<Genode::Irq_se
enum { INVALID_IRQ = 0xffU };
Irq_session_component(unsigned, Genode::addr_t);
Irq_session_component(unsigned, Genode::addr_t, Genode::Env &,
Genode::Allocator &heap);
~Irq_session_component();
bool msi()

View File

@ -15,23 +15,20 @@
#ifndef _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
#define _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
#include <base/env.h>
namespace Genode {
namespace Platform {
class Irq_sigh;
template <typename THREAD> class Irq_proxy;
class Irq_proxy;
}
class Genode::Irq_sigh : public Genode::Signal_context_capability,
public Genode::List<Genode::Irq_sigh>::Element
class Platform::Irq_sigh : public Genode::Signal_context_capability,
public Genode::List<Platform::Irq_sigh>::Element
{
public:
inline Irq_sigh * operator= (const Signal_context_capability &cap)
inline Irq_sigh * operator= (const Genode::Signal_context_capability &cap)
{
Signal_context_capability::operator=(cap);
Genode::Signal_context_capability::operator=(cap);
return this;
}
@ -47,121 +44,37 @@ class Genode::Irq_sigh : public Genode::Signal_context_capability,
*
* XXX resources are not accounted as the interrupt is shared
*/
template <typename THREAD>
class Genode::Irq_proxy : public THREAD,
public Genode::List<Genode::Irq_proxy<THREAD> >::Element
class Platform::Irq_proxy : public Genode::List<Platform::Irq_proxy>::Element
{
protected:
char _name[32];
Lock _startup_lock;
unsigned _irq_number;
Lock _mutex; /* protects this object */
Genode::Lock _mutex; /* protects this object */
int _num_sharers; /* number of clients sharing this IRQ */
Semaphore _sleep; /* wake me up if aspired blockers return */
List<Irq_sigh> _sigh_list;
Genode::List<Irq_sigh> _sigh_list;
int _num_acknowledgers; /* number of currently blocked clients */
bool _woken_up; /* client decided to wake me up -
this prevents multiple wakeups
to happen during initialization */
/***************
** Interface **
***************/
/**
* Request interrupt
*
* \return true on success
*/
virtual bool _associate() = 0;
/**
* Wait for associated interrupt
*/
virtual void _wait_for_irq() = 0;
/**
* Acknowledge interrupt
*/
virtual void _ack_irq() = 0;
/********************
** Implementation **
********************/
const char *_construct_name(unsigned irq_number)
{
snprintf(_name, sizeof(_name), "irqproxy%02x", irq_number);
return _name;
}
void _loop()
{
/* wait for first blocker */
_sleep.down();
while (1) {
_wait_for_irq();
/* notify all */
notify_about_irq(1);
/*
* We must wait for all clients to ack their interrupt,
* otherwise level-triggered interrupts will occur immediately
* after acknowledgement. That's an inherent security problem
* with shared IRQs and induces problems with dynamic driver
* load and unload.
*/
_sleep.down();
/* acknowledge previous interrupt */
_ack_irq();
}
}
/**
* Start this thread, should be called externally from derived class
*/
virtual void _start()
{
THREAD::start();
_startup_lock.lock();
}
public:
Irq_proxy(unsigned irq_number)
:
THREAD(_construct_name(irq_number)),
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
_mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false)
_irq_number(irq_number),
_mutex(Genode::Lock::UNLOCKED), _num_sharers(0),
_num_acknowledgers(0), _woken_up(false)
{ }
/**
* Thread interface
*/
void entry()
{
bool const associate_suceeded = _associate();
_startup_lock.unlock();
if (associate_suceeded)
_loop();
}
/**
* Acknowledgements of clients
*/
virtual bool ack_irq()
{
Lock::Guard lock_guard(_mutex);
Genode::Lock::Guard lock_guard(_mutex);
_num_acknowledgers++;
@ -170,7 +83,6 @@ class Genode::Irq_proxy : public THREAD,
* before and this client is the last aspired acknowledger.
*/
if (!_woken_up && _num_acknowledgers == _num_sharers) {
_sleep.up();
_woken_up = true;
}
@ -180,9 +92,9 @@ class Genode::Irq_proxy : public THREAD,
/**
* Notify all clients about irq
*/
void notify_about_irq(unsigned)
void notify_about_irq()
{
Lock::Guard lock_guard(_mutex);
Genode::Lock::Guard lock_guard(_mutex);
/* reset acknowledger state */
_num_acknowledgers = 0;
@ -197,7 +109,7 @@ class Genode::Irq_proxy : public THREAD,
virtual bool add_sharer(Irq_sigh *s)
{
Lock::Guard lock_guard(_mutex);
Genode::Lock::Guard lock_guard(_mutex);
++_num_sharers;
_sigh_list.insert(s);
@ -207,7 +119,7 @@ class Genode::Irq_proxy : public THREAD,
virtual bool remove_sharer(Irq_sigh *s)
{
Lock::Guard lock_guard(_mutex);
Genode::Lock::Guard lock_guard(_mutex);
_sigh_list.remove(s);
--_num_sharers;
@ -216,38 +128,11 @@ class Genode::Irq_proxy : public THREAD,
return _num_sharers == 0;
if (_num_acknowledgers == _num_sharers) {
_sleep.up();
_woken_up = true;
}
return _num_sharers == 0;
}
template <typename PROXY>
static PROXY *get_irq_proxy(unsigned irq_number,
Range_allocator *irq_alloc = 0,
Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED,
Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED)
{
static List<Irq_proxy> proxies;
static Lock proxies_lock;
Lock::Guard lock_guard(proxies_lock);
/* lookup proxy in database */
for (Irq_proxy *p = proxies.first(); p; p = p->next())
if (p->irq_number() == irq_number)
return static_cast<PROXY *>(p);
/* try to create proxy */
if (!irq_alloc || irq_alloc->alloc_addr(1, irq_number).error())
return 0;
PROXY *new_proxy = new (env()->heap()) PROXY(irq_number, trigger,
polarity);
proxies.insert(new_proxy);
return new_proxy;
}
};
#endif /* _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ */

View File

@ -11,13 +11,12 @@
* under the terms of the GNU General Public License version 2.
*/
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/env.h>
#include <util/reconstructible.h>
#include <os/attached_rom_dataspace.h>
#include "pci_session_component.h"
#include "pci_device_config.h"
#include "device_pd.h"
@ -119,15 +118,15 @@ struct Platform::Main
if (_system_rom) {
/* wait for system state changes, e.g. reset and acpi_ready */
system_state.construct("system");
system_state.construct(env, "system");
system_state->sigh(_system_report);
acpi_ready.construct("acpi_ready");
acpi_ready.construct(env, "acpi_ready");
acpi_ready->sigh(_system_report);
}
if (wait_for_acpi == "yes") {
/* for ACPI support, wait for the first valid acpi report */
acpi_rom.construct("acpi");
acpi_rom.construct(env, "acpi");
acpi_rom->sigh(_acpi_report);
/* check if already valid */
acpi_update();

View File

@ -36,12 +36,14 @@ class Nonpci::Ps2 : public Platform::Device_component
public:
Ps2(Genode::Rpc_entrypoint &ep, Platform::Session_component &session)
Ps2(Genode::Env &env, Platform::Session_component &session,
Genode::Allocator &heap_for_irq)
:
Platform::Device_component(ep, session, IRQ_KEYBOARD),
_ep(ep),
_irq_mouse(IRQ_MOUSE, ~0UL),
_data(REG_DATA, ACCESS_WIDTH), _status(REG_STATUS, ACCESS_WIDTH)
Platform::Device_component(env, session, IRQ_KEYBOARD, heap_for_irq),
_ep(env.ep().rpc_ep()),
_irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq),
_data(env, REG_DATA, ACCESS_WIDTH),
_status(env, REG_STATUS, ACCESS_WIDTH)
{
_ep.manage(&_irq_mouse);
}
@ -97,10 +99,11 @@ class Nonpci::Pit : public Platform::Device_component
public:
Pit(Genode::Rpc_entrypoint &ep, Platform::Session_component &session)
Pit(Genode::Env &env, Platform::Session_component &session,
Genode::Allocator &heap_for_irq)
:
Platform::Device_component(ep, session, IRQ_PIT),
_ports(PIT_PORT, PORTS_WIDTH)
Platform::Device_component(env, session, IRQ_PIT, heap_for_irq),
_ports(env, PIT_PORT, PORTS_WIDTH)
{ }
Genode::Io_port_session_capability io_port(Genode::uint8_t io_port) override
@ -147,17 +150,17 @@ Platform::Device_capability Platform::Session_component::device(String const &na
switch(devices_i) {
case 0:
dev = new (_md_alloc) Nonpci::Ps2(_ep, *this);
dev = new (_md_alloc) Nonpci::Ps2(_env, *this, _global_heap);
break;
case 1:
dev = new (_md_alloc) Nonpci::Pit(_ep, *this);
dev = new (_md_alloc) Nonpci::Pit(_env, *this, _global_heap);
break;
default:
return Device_capability();
}
_device_list.insert(dev);
return _ep.manage(dev);
return _env.ep().rpc_ep().manage(dev);
} catch (Genode::Allocator::Out_of_memory) {
throw Out_of_metadata();
} catch (Genode::Parent::Service_denied) {

View File

@ -24,6 +24,8 @@ namespace Platform {
{
private:
Genode::Env &_env;
enum { REG_ADDR = 0xcf8, REG_DATA = 0xcfc, REG_SIZE = 4 };
/**
@ -47,7 +49,7 @@ namespace Platform {
* Once created, each I/O-port session persists until
* the PCI driver gets killed by its parent.
*/
static Genode::Io_port_connection io_port(port, REG_SIZE);
static Genode::Io_port_connection io_port(_env, port, REG_SIZE);
return &io_port;
}
@ -79,6 +81,8 @@ namespace Platform {
public:
Config_access(Genode::Env &env) : _env(env) { }
/**
* Read value from config space of specified device/function
*

View File

@ -32,7 +32,7 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u
return _io_port_conn[v_id]->cap();
try {
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size());
_io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(_env, res.base(), res.size());
return _io_port_conn[v_id]->cap();
} catch (...) {
return Genode::Io_port_session_capability();
@ -68,7 +68,8 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin
try {
bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED;
Io_mem * io_mem = new (_slab_iomem) Io_mem(res.base() + offset,
Io_mem * io_mem = new (_slab_iomem) Io_mem(_env,
res.base() + offset,
res_size, wc);
_io_mem[i].insert(io_mem);
return io_mem->cap();
@ -144,16 +145,19 @@ Genode::Irq_session_capability Platform::Device_component::irq(Genode::uint8_t i
if (!_device_config.valid()) {
/* Non PCI devices */
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
_irq_line, ~0UL);
_irq_line, ~0UL,
_env,
_global_heap);
_ep.manage(_irq_session);
_env.ep().rpc_ep().manage(_irq_session);
return _irq_session->cap();
}
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
_configure_irq(_irq_line),
(!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space);
_ep.manage(_irq_session);
(!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space,
_env, _global_heap);
_env.ep().rpc_ep().manage(_irq_session);
Genode::uint16_t msi_cap = _msi_cap();

View File

@ -34,22 +34,25 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
{
private:
Genode::Env &_env;
Device_config _device_config;
Genode::addr_t _config_space;
Config_access _config_access;
Genode::Rpc_entrypoint &_ep;
Config_access _config_access = { _env };
Platform::Session_component &_session;
unsigned short _irq_line;
Irq_session_component *_irq_session = nullptr;
Genode::Constructible<Genode::Io_mem_connection> _io_mem_config_extended;
Genode::Allocator &_global_heap;
class Io_mem : public Genode::Io_mem_connection,
public Genode::List<Io_mem>::Element
{
public:
Io_mem (Genode::addr_t base, Genode::size_t size, bool wc)
: Genode::Io_mem_connection(base, size, wc) { }
Io_mem (Genode::Env &env, Genode::addr_t base,
Genode::size_t size, bool wc)
: Genode::Io_mem_connection(env, base, size, wc) { }
};
enum {
@ -182,15 +185,18 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
/**
* Constructor
*/
Device_component(Device_config device_config, Genode::addr_t addr,
Genode::Rpc_entrypoint &ep,
Device_component(Genode::Env &env,
Device_config device_config, Genode::addr_t addr,
Platform::Session_component &session,
Genode::Allocator &md_alloc)
Genode::Allocator &md_alloc,
Genode::Allocator &global_heap)
:
_env(env),
_device_config(device_config), _config_space(addr),
_ep(ep), _session(session),
_session(session),
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
Platform::Device::ACCESS_8BIT)),
_global_heap(global_heap),
_slab_ioport(&md_alloc, &_slab_ioport_block_data),
_slab_iomem(&md_alloc, &_slab_iomem_block_data)
{
@ -204,12 +210,15 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
/**
* Constructor for non PCI devices
*/
Device_component(Genode::Rpc_entrypoint &ep,
Platform::Session_component &session, unsigned irq)
Device_component(Genode::Env &env,
Platform::Session_component &session, unsigned irq,
Genode::Allocator &global_heap)
:
_env(env),
_config_space(~0UL),
_ep(ep), _session(session),
_session(session),
_irq_line(irq),
_global_heap(global_heap),
_slab_ioport(nullptr, &_slab_ioport_block_data),
_slab_iomem(nullptr, &_slab_iomem_block_data)
{
@ -223,7 +232,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
~Device_component()
{
if (_irq_session) {
_ep.dissolve(_irq_session);
_env.ep().rpc_ep().dissolve(_irq_session);
_irq_session->~Irq_session();
}
@ -254,7 +263,7 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
if (!_io_mem_config_extended.constructed()) {
try {
_io_mem_config_extended.construct(_config_space, 0x1000);
_io_mem_config_extended.construct(_env, _config_space, 0x1000);
} catch (...) {
_config_space = ~0UL;
}

View File

@ -72,10 +72,11 @@ struct Platform::Device_pd_connection : Genode::Connection<Device_pd>, Device_pd
struct Platform::Device_pd_component : Genode::Rpc_object<Device_pd,
Device_pd_component>
{
Genode::Env &_env;
Genode::Region_map &_address_space;
Device_pd_component(Genode::Region_map &address_space)
: _address_space(address_space) { }
Device_pd_component(Genode::Region_map &address_space, Genode::Env &env)
: _env(env), _address_space(address_space) { }
void attach_dma_mem(Genode::Dataspace_capability);
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);

View File

@ -37,12 +37,13 @@
#include "device_pd.h"
namespace Platform {
bool bus_valid(int bus = 0);
unsigned short bridge_bdf(unsigned char bus);
class Pci_buses;
class Ram_dataspace;
class Rmrr;
class Root;
class Ram_dataspace;
class Session_component;
}
class Platform::Ram_dataspace : public Genode::List<Ram_dataspace>::Element {
@ -92,7 +93,8 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
: _start(start), _end(end)
{ }
Genode::Io_mem_dataspace_capability match(Device_config config)
Genode::Io_mem_dataspace_capability match(Genode::Env &env,
Device_config config)
{
Genode::uint8_t bus = config.bus_number();
Genode::uint8_t device = config.device_number();
@ -105,7 +107,7 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
if (_cap.valid())
return _cap;
_io_mem.construct(_start, _end - _start + 1);
_io_mem.construct(env, _start, _end - _start + 1);
_cap = _io_mem->dataspace();
return _cap;
}
@ -122,13 +124,79 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
};
namespace Platform { class Session_component; }
class Platform::Pci_buses
{
private:
Genode::Bit_array<Device_config::MAX_BUSES> _valid;
void scan_bus(Config_access &config_access, Genode::Allocator &heap,
unsigned char bus = 0);
bool _bus_valid(int bus)
{
if (bus >= Device_config::MAX_BUSES)
return false;
return _valid.get(bus, 1);
}
public:
Pci_buses(Genode::Env &env, Genode::Allocator &heap)
{
Config_access c(env);
scan_bus(c, heap);
}
/**
* Scan PCI buses for a device
*
* \param bus start scanning at bus number
* \param device start scanning at device number
* \param function start scanning at function number
* \param out_device_config device config information of the
* found device
* \param config_access interface for accessing the PCI
* configuration
* space
*
* \retval true device was found
* \retval false no device was found
*/
bool find_next(int bus, int device, int function,
Device_config *out_device_config,
Config_access *config_access)
{
for (; bus < Device_config::MAX_BUSES; bus++) {
if (!_bus_valid(bus))
continue;
for (; device < Device_config::MAX_DEVICES; device++) {
for (; function < Device_config::MAX_FUNCTIONS; function++) {
/* read config space */
Device_config config(bus, device, function, config_access);
if (config.valid()) {
*out_device_config = config;
return true;
}
}
function = 0; /* init value for next device */
}
device = 0; /* init value for next bus */
}
return false;
}
};
class Platform::Session_component : public Genode::Rpc_object<Session>
{
private:
Genode::Rpc_entrypoint &_ep;
Genode::Env &_env;
Genode::Rpc_entrypoint &_device_pd_ep;
Genode::Ram_session_guard _env_ram;
Genode::Ram_session_capability _env_ram_cap;
@ -137,6 +205,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
Genode::Session_label const _label;
Genode::Session_policy const _policy { _label };
Genode::List<Device_component> _device_list;
Platform::Pci_buses &_pci_bus;
Genode::Heap &_global_heap;
bool _no_device_pd = false;
/**
@ -167,8 +237,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
*
* Restrict physical address to 3G on 32bit, 4G on 64bit
*/
Genode::Ram_connection _ram {
_label.string(), 0, (sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
Genode::Ram_connection _ram { _env, _label.string(), 0,
(sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
/*
* Associate session RAM session with platform_drv _ram session and
@ -319,46 +389,6 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
static Genode::Bit_array<MAX_PCI_DEVICES> bdf_in_use;
/**
* Scan PCI buses for a device
*
* \param bus start scanning at bus number
* \param device start scanning at device number
* \param function start scanning at function number
* \param out_device_config device config information of the
* found device
* \param config_access interface for accessing the PCI
* configuration
* space
*
* \retval true device was found
* \retval false no device was found
*/
bool _find_next(int bus, int device, int function,
Device_config *out_device_config,
Config_access *config_access)
{
for (; bus < Device_config::MAX_BUSES; bus++) {
if (!bus_valid(bus))
continue;
for (; device < Device_config::MAX_DEVICES; device++) {
for (; function < Device_config::MAX_FUNCTIONS; function++) {
/* read config space */
Device_config config(bus, device, function, config_access);
if (config.valid()) {
*out_device_config = config;
return true;
}
}
function = 0; /* init value for next device */
}
device = 0; /* init value for next bus */
}
return false;
}
/**
* List containing extended PCI config space information
@ -564,18 +594,20 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
/**
* Constructor
*/
Session_component(Genode::Env &env,
Genode::Rpc_entrypoint &ep,
Session_component(Genode::Env &env,
Genode::Rpc_entrypoint &device_pd_ep,
Platform::Pci_buses &buses,
Genode::Heap &global_heap,
char const *args)
:
_ep(ep), _device_pd_ep(device_pd_ep),
_env(env), _device_pd_ep(device_pd_ep),
_env_ram(env.ram(), env.ram_session_cap(),
Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
_env_ram_cap(env.ram_session_cap()),
_local_rm(env.rm()),
_md_alloc(_env_ram, env.rm()),
_label(Genode::label_from_args(args))
_label(Genode::label_from_args(args)),
_pci_bus(buses), _global_heap(global_heap)
{
/* non-pci devices */
_policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) {
@ -689,12 +721,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
static void add_config_space(Genode::uint32_t bdf_start,
Genode::uint32_t func_count,
Genode::addr_t base)
Genode::addr_t base,
Genode::Allocator &heap)
{
using namespace Genode;
Config_space * space =
new (env()->heap()) Config_space(bdf_start, func_count,
base);
new (heap) Config_space(bdf_start, func_count, base);
config_space_list().insert(space);
}
@ -731,7 +763,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
* Create the interface to the PCI config space.
* This involves the creation of I/O port sessions.
*/
Config_access config_access;
Config_access config_access(_env);
/* lookup device component for previous device */
auto lambda = [&] (Device_component *prev)
@ -759,8 +791,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
while (true) {
function += 1;
if (!_find_next(bus, device, function, &config,
&config_access))
if (!_pci_bus.find_next(bus, device, function, &config,
&config_access))
return Device_capability();
/* get new bdf values */
@ -788,8 +820,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
*/
try {
Device_component * dev = new (_md_alloc)
Device_component(config, config_space, _ep, *this,
_md_alloc);
Device_component(_env, config, config_space, *this,
_md_alloc, _global_heap);
/* if more than one driver uses the device - warn about */
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
@ -806,12 +838,12 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
function, 1);
_device_list.insert(dev);
return _ep.manage(dev);
return _env.ep().rpc_ep().manage(dev);
} catch (Genode::Allocator::Out_of_memory) {
throw Out_of_metadata();
}
};
return _ep.apply(prev_device, lambda);
return _env.ep().rpc_ep().apply(prev_device, lambda);
}
void release_device(Device_capability device_cap) override
@ -834,11 +866,11 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
Device_config::MAX_DEVICES * dev + func, 1);
_device_list.remove(device);
_ep.dissolve(device);
_env.ep().rpc_ep().dissolve(device);
};
/* lookup device component for previous device */
_ep.apply(device_cap, lambda);
_env.ep().rpc_ep().apply(device_cap, lambda);
if (!device) return;
@ -865,7 +897,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
_device_pd->session().assign_pci(io_mem, device->config().bdf());
for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) {
Io_mem_dataspace_capability rmrr_cap = r->match(device->config());
Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->config());
if (rmrr_cap.valid())
_device_pd->session().attach_dma_mem(rmrr_cap);
}
@ -991,12 +1023,14 @@ class Platform::Root : public Genode::Root_component<Session_component>
Genode::Env &_env;
Genode::Rpc_entrypoint _device_pd_ep;
Genode::Heap _heap { _env.ram(), _env.rm() };
Platform::Pci_buses _buses { _env, _heap };
void _parse_report_rom(const char * acpi_rom)
void _parse_report_rom(Genode::Env &env, const char * acpi_rom)
{
using namespace Genode;
Config_access config_access;
Config_access config_access(env);
Xml_node xml_acpi(acpi_rom);
if (!xml_acpi.has_type("acpi"))
@ -1016,7 +1050,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
node.attribute("base").value(&base);
Session_component::add_config_space(bdf_start, func_count,
base);
base, _heap);
}
if (node.has_type("irq_override")) {
@ -1029,9 +1063,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
node.attribute("flags").value(&flags);
using Platform::Irq_override;
Irq_override * o = new (env()->heap()) Irq_override(irq,
gsi,
flags);
Irq_override * o = new (_heap) Irq_override(irq, gsi,
flags);
Irq_override::list()->insert(o);
}
@ -1043,7 +1076,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
if (node.num_sub_nodes() == 0)
throw 2;
Rmrr * rmrr = new (env()->heap()) Rmrr(mem_start, mem_end);
Rmrr * rmrr = new (_heap) Rmrr(mem_start, mem_end);
Rmrr::list()->insert(rmrr);
for (unsigned s = 0; s < node.num_sub_nodes(); s++) {
@ -1070,8 +1103,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
Device::ACCESS_8BIT);
}
rmrr->add(new (env()->heap()) Rmrr::Bdf(bus, dev,
func));
rmrr->add(new (_heap) Rmrr::Bdf(bus, dev, func));
}
}
@ -1116,10 +1148,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
*/
bridge_bdf = 0;
Irq_routing * r = new (env()->heap()) Irq_routing(gsi,
bridge_bdf,
device,
device_pin);
Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf,
device, device_pin);
Irq_routing::list()->insert(r);
}
}
@ -1130,7 +1160,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
{
try {
return new (md_alloc())
Session_component(_env, *ep(), _device_pd_ep, args);
Session_component(_env, _device_pd_ep, _buses, _heap, args);
}
catch (Genode::Session_policy::No_policy_defined) {
Genode::error("Invalid session request, no matching policy for ",
@ -1164,12 +1194,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
_env(env),
_device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave")
{
/* enforce initial bus scan */
bus_valid();
if (acpi_rom) {
try {
_parse_report_rom(acpi_rom);
_parse_report_rom(env, acpi_rom);
} catch (...) {
Genode::error("PCI config space data could not be parsed.");
}
@ -1183,7 +1210,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
if (!io_port_space)
return;
Config_access config_access;
Config_access config_access(_env);
const unsigned raw_access_size = Fadt::Gas::Access_size::get(fadt.reset_type);
const bool reset_support = config_access.reset_support(fadt.reset_addr, raw_access_size);
if (!reset_support)

View File

@ -33,57 +33,40 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
return 0;
}
/**
* Check if given PCI bus was found on initial scan
*
* This tremendously speeds up further scans by other drivers.
*/
bool Platform::bus_valid(int bus)
void Platform::Pci_buses::scan_bus(Config_access &config_access,
Genode::Allocator &heap, unsigned char bus)
{
struct Valid_buses
{
bool valid[Device_config::MAX_BUSES];
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
void scan_bus(Config_access &config_access, unsigned char bus = 0)
{
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
/* read config space */
Device_config config(bus, dev, fun, &config_access);
/* read config space */
Device_config config(bus, dev, fun, &config_access);
if (!config.valid())
continue;
if (!config.valid())
continue;
/*
* There is at least one device on the current bus, so
* we mark it as valid.
*/
if (!_valid.get(bus, 1))
_valid.set(bus, 1);
/*
* There is at least one device on the current bus, so
* we mark it as valid.
*/
valid[bus] = true;
/* scan behind bridge */
if (config.pci_bridge()) {
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
unsigned char sec_bus = config.read(&config_access, 0x19,
Device::ACCESS_8BIT);
unsigned char sub_bus = config.read(&config_access, 0x20,
Device::ACCESS_8BIT);
/* scan behind bridge */
if (config.pci_bridge()) {
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
unsigned char sec_bus = config.read(&config_access,
0x19, Device::ACCESS_8BIT);
unsigned char sub_bus = config.read(&config_access,
0x20, Device::ACCESS_8BIT);
bridges()->insert(new (heap) Bridge(bus, dev, fun, sec_bus,
sub_bus));
bridges()->insert(new (Genode::env()->heap()) Bridge(bus, dev, fun, sec_bus, sub_bus));
scan_bus(config_access, sec_bus);
}
}
scan_bus(config_access, heap, sec_bus);
}
}
Valid_buses() { Config_access c; scan_bus(c); }
};
static Valid_buses buses;
return buses.valid[bus];
}
}