mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-17 14:48:20 +00:00
committed by
Norman Feske
parent
658547d058
commit
dd8e13d6fa
@ -30,7 +30,7 @@
|
|||||||
/**
|
/**
|
||||||
* Custom handling of PD-session depletion during attach operations
|
* 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
|
* 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
|
* want to issue resource requests but let the platform driver reflect this
|
||||||
* condition to its client.
|
* condition to its client.
|
||||||
@ -59,7 +59,7 @@ struct Expanding_region_map_client : Genode::Region_map_client
|
|||||||
[&] () {
|
[&] () {
|
||||||
enum { UPGRADE_QUOTA = 4096 };
|
enum { UPGRADE_QUOTA = 4096 };
|
||||||
|
|
||||||
if (Genode::env()->ram_session()->avail() < UPGRADE_QUOTA)
|
if (_env.ram().avail() < UPGRADE_QUOTA)
|
||||||
throw;
|
throw;
|
||||||
|
|
||||||
Genode::String<32> arg("ram_quota=", (unsigned)UPGRADE_QUOTA);
|
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 */
|
/* 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 ",
|
Genode::error("assignment of PCI device ", Rid(rid), " failed ",
|
||||||
"phys=", Genode::Hex(ds_client.phys_addr()), " "
|
"phys=", Genode::Hex(ds_client.phys_addr()), " "
|
||||||
"virt=", Genode::Hex(page));
|
"virt=", Genode::Hex(page));
|
||||||
@ -190,7 +190,7 @@ struct Main
|
|||||||
|
|
||||||
Expanding_region_map_client rm { env };
|
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) };
|
Genode::Static_root<Platform::Device_pd> root { env.ep().manage(pd_component) };
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
namespace Platform {
|
namespace Platform {
|
||||||
class Irq_component;
|
class Irq_component;
|
||||||
class Irq_allocator;
|
class Irq_allocator;
|
||||||
class Irq_thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -32,9 +31,9 @@ using Genode::size_t;
|
|||||||
using Genode::addr_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:
|
private:
|
||||||
|
|
||||||
@ -64,76 +63,13 @@ class Platform::Irq_allocator : public Genode::Range_allocator
|
|||||||
|
|
||||||
void free_msi(unsigned msi) { _msi.free(msi); }
|
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 {
|
try {
|
||||||
_legacy.set(addr, size);
|
_legacy.set(addr, 1);
|
||||||
return Alloc_return::OK;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return Alloc_return::RANGE_CONFLICT;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -144,20 +80,17 @@ class Platform::Irq_thread : public Genode::Thread_deprecated<4096>
|
|||||||
* for Genode signals of all hardware IRQs.
|
* for Genode signals of all hardware IRQs.
|
||||||
*/
|
*/
|
||||||
static Platform::Irq_allocator irq_alloc;
|
static Platform::Irq_allocator irq_alloc;
|
||||||
static Platform::Irq_thread irq_thread;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Irq_proxy interface implementation
|
* Irq_proxy interface implementation
|
||||||
*/
|
*/
|
||||||
typedef Genode::Irq_proxy<NoThread> Proxy;
|
class Platform::Irq_component : public Platform::Irq_proxy
|
||||||
|
|
||||||
class Platform::Irq_component : public Proxy
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Irq_connection _irq;
|
Genode::Irq_connection _irq;
|
||||||
Genode::Signal_dispatcher<Platform::Irq_component> _irq_dispatcher;
|
Genode::Signal_handler<Platform::Irq_component> _irq_dispatcher;
|
||||||
|
|
||||||
bool _associated;
|
bool _associated;
|
||||||
|
|
||||||
@ -178,11 +111,8 @@ class Platform::Irq_component : public Proxy
|
|||||||
_irq.ack_irq();
|
_irq.ack_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _associate() { return _associated; }
|
virtual bool remove_sharer(Platform::Irq_sigh *s) override {
|
||||||
void _wait_for_irq() { }
|
if (!Irq_proxy::remove_sharer(s))
|
||||||
|
|
||||||
virtual bool remove_sharer(Genode::Irq_sigh *s) override {
|
|
||||||
if (!Proxy::remove_sharer(s))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* De-associate handler. */
|
/* De-associate handler. */
|
||||||
@ -193,15 +123,42 @@ class Platform::Irq_component : public Proxy
|
|||||||
|
|
||||||
public:
|
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)
|
Genode::Irq_session::Polarity polarity)
|
||||||
:
|
:
|
||||||
Proxy(gsi),
|
Irq_proxy(gsi),
|
||||||
_irq(gsi, trigger, polarity),
|
_irq(env, gsi, trigger, polarity),
|
||||||
_irq_dispatcher(irq_thread.sig_rec(), *this,
|
_irq_dispatcher(env.ep(), *this, &Platform::Irq_proxy::notify_about_irq),
|
||||||
&::Proxy::notify_about_irq),
|
|
||||||
_associated(false)
|
_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 */
|
/* 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) {
|
if (!irq_obj) {
|
||||||
Genode::error("expected to find IRQ proxy for IRQ ", Genode::Hex(_gsi));
|
Genode::error("expected to find IRQ proxy for IRQ ", Genode::Hex(_gsi));
|
||||||
return;
|
return;
|
||||||
@ -230,7 +187,9 @@ void Platform::Irq_session_component::ack_irq()
|
|||||||
|
|
||||||
|
|
||||||
Platform::Irq_session_component::Irq_session_component(unsigned 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)
|
_gsi(irq)
|
||||||
{
|
{
|
||||||
@ -245,7 +204,7 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
|
|||||||
try {
|
try {
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
_irq_conn.construct(msi, Irq_session::TRIGGER_UNCHANGED,
|
_irq_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED,
|
||||||
Irq_session::POLARITY_UNCHANGED,
|
Irq_session::POLARITY_UNCHANGED,
|
||||||
pci_config_space);
|
pci_config_space);
|
||||||
|
|
||||||
@ -273,8 +232,8 @@ Platform::Irq_session_component::Irq_session_component(unsigned irq,
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
/* check if shared IRQ object was used before */
|
/* check if shared IRQ object was used before */
|
||||||
if (Proxy::get_irq_proxy<Irq_component>(_gsi, &irq_alloc, trigger,
|
if (Irq_component::get_irq_proxy(_gsi, &irq_alloc, trigger,
|
||||||
polarity))
|
polarity, &env, &heap))
|
||||||
return;
|
return;
|
||||||
} catch (Genode::Parent::Service_denied) { }
|
} catch (Genode::Parent::Service_denied) { }
|
||||||
|
|
||||||
@ -292,7 +251,7 @@ Platform::Irq_session_component::~Irq_session_component()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* shared irq handling */
|
/* 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_obj) return;
|
||||||
|
|
||||||
if (_irq_sigh.valid())
|
if (_irq_sigh.valid())
|
||||||
@ -309,7 +268,7 @@ void Platform::Irq_session_component::sigh(Genode::Signal_context_capability sig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* shared irq handling */
|
/* 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) {
|
if (!irq_obj) {
|
||||||
Genode::error("signal handler got not registered - irq object unavailable");
|
Genode::error("signal handler got not registered - irq object unavailable");
|
||||||
return;
|
return;
|
||||||
|
@ -34,7 +34,7 @@ class Platform::Irq_session_component : public Genode::Rpc_object<Genode::Irq_se
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
unsigned _gsi;
|
unsigned _gsi;
|
||||||
Genode::Irq_sigh _irq_sigh;
|
Platform::Irq_sigh _irq_sigh;
|
||||||
Genode::Irq_session::Info _msi_info;
|
Genode::Irq_session::Info _msi_info;
|
||||||
|
|
||||||
Genode::Constructible<Genode::Irq_connection> _irq_conn;
|
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 };
|
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();
|
~Irq_session_component();
|
||||||
|
|
||||||
bool msi()
|
bool msi()
|
||||||
|
@ -15,23 +15,20 @@
|
|||||||
#ifndef _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
#ifndef _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
||||||
#define _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
#define _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_
|
||||||
|
|
||||||
#include <base/env.h>
|
namespace Platform {
|
||||||
|
|
||||||
|
|
||||||
namespace Genode {
|
|
||||||
class Irq_sigh;
|
class Irq_sigh;
|
||||||
template <typename THREAD> class Irq_proxy;
|
class Irq_proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Genode::Irq_sigh : public Genode::Signal_context_capability,
|
class Platform::Irq_sigh : public Genode::Signal_context_capability,
|
||||||
public Genode::List<Genode::Irq_sigh>::Element
|
public Genode::List<Platform::Irq_sigh>::Element
|
||||||
{
|
{
|
||||||
public:
|
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;
|
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
|
* XXX resources are not accounted as the interrupt is shared
|
||||||
*/
|
*/
|
||||||
template <typename THREAD>
|
class Platform::Irq_proxy : public Genode::List<Platform::Irq_proxy>::Element
|
||||||
class Genode::Irq_proxy : public THREAD,
|
|
||||||
public Genode::List<Genode::Irq_proxy<THREAD> >::Element
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
char _name[32];
|
|
||||||
Lock _startup_lock;
|
|
||||||
|
|
||||||
unsigned _irq_number;
|
unsigned _irq_number;
|
||||||
|
|
||||||
Lock _mutex; /* protects this object */
|
Genode::Lock _mutex; /* protects this object */
|
||||||
int _num_sharers; /* number of clients sharing this IRQ */
|
int _num_sharers; /* number of clients sharing this IRQ */
|
||||||
Semaphore _sleep; /* wake me up if aspired blockers return */
|
Genode::List<Irq_sigh> _sigh_list;
|
||||||
List<Irq_sigh> _sigh_list;
|
|
||||||
int _num_acknowledgers; /* number of currently blocked clients */
|
int _num_acknowledgers; /* number of currently blocked clients */
|
||||||
bool _woken_up; /* client decided to wake me up -
|
bool _woken_up; /* client decided to wake me up -
|
||||||
this prevents multiple wakeups
|
this prevents multiple wakeups
|
||||||
to happen during initialization */
|
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:
|
public:
|
||||||
|
|
||||||
Irq_proxy(unsigned irq_number)
|
Irq_proxy(unsigned irq_number)
|
||||||
:
|
:
|
||||||
THREAD(_construct_name(irq_number)),
|
_irq_number(irq_number),
|
||||||
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
|
_mutex(Genode::Lock::UNLOCKED), _num_sharers(0),
|
||||||
_mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false)
|
_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
|
* Acknowledgements of clients
|
||||||
*/
|
*/
|
||||||
virtual bool ack_irq()
|
virtual bool ack_irq()
|
||||||
{
|
{
|
||||||
Lock::Guard lock_guard(_mutex);
|
Genode::Lock::Guard lock_guard(_mutex);
|
||||||
|
|
||||||
_num_acknowledgers++;
|
_num_acknowledgers++;
|
||||||
|
|
||||||
@ -170,7 +83,6 @@ class Genode::Irq_proxy : public THREAD,
|
|||||||
* before and this client is the last aspired acknowledger.
|
* before and this client is the last aspired acknowledger.
|
||||||
*/
|
*/
|
||||||
if (!_woken_up && _num_acknowledgers == _num_sharers) {
|
if (!_woken_up && _num_acknowledgers == _num_sharers) {
|
||||||
_sleep.up();
|
|
||||||
_woken_up = true;
|
_woken_up = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,9 +92,9 @@ class Genode::Irq_proxy : public THREAD,
|
|||||||
/**
|
/**
|
||||||
* Notify all clients about irq
|
* 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 */
|
/* reset acknowledger state */
|
||||||
_num_acknowledgers = 0;
|
_num_acknowledgers = 0;
|
||||||
@ -197,7 +109,7 @@ class Genode::Irq_proxy : public THREAD,
|
|||||||
|
|
||||||
virtual bool add_sharer(Irq_sigh *s)
|
virtual bool add_sharer(Irq_sigh *s)
|
||||||
{
|
{
|
||||||
Lock::Guard lock_guard(_mutex);
|
Genode::Lock::Guard lock_guard(_mutex);
|
||||||
|
|
||||||
++_num_sharers;
|
++_num_sharers;
|
||||||
_sigh_list.insert(s);
|
_sigh_list.insert(s);
|
||||||
@ -207,7 +119,7 @@ class Genode::Irq_proxy : public THREAD,
|
|||||||
|
|
||||||
virtual bool remove_sharer(Irq_sigh *s)
|
virtual bool remove_sharer(Irq_sigh *s)
|
||||||
{
|
{
|
||||||
Lock::Guard lock_guard(_mutex);
|
Genode::Lock::Guard lock_guard(_mutex);
|
||||||
|
|
||||||
_sigh_list.remove(s);
|
_sigh_list.remove(s);
|
||||||
--_num_sharers;
|
--_num_sharers;
|
||||||
@ -216,38 +128,11 @@ class Genode::Irq_proxy : public THREAD,
|
|||||||
return _num_sharers == 0;
|
return _num_sharers == 0;
|
||||||
|
|
||||||
if (_num_acknowledgers == _num_sharers) {
|
if (_num_acknowledgers == _num_sharers) {
|
||||||
_sleep.up();
|
|
||||||
_woken_up = true;
|
_woken_up = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _num_sharers == 0;
|
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_ */
|
#endif /* _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ */
|
||||||
|
@ -11,13 +11,12 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <base/attached_rom_dataspace.h>
|
||||||
#include <base/component.h>
|
#include <base/component.h>
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
|
|
||||||
#include <util/reconstructible.h>
|
#include <util/reconstructible.h>
|
||||||
|
|
||||||
#include <os/attached_rom_dataspace.h>
|
|
||||||
|
|
||||||
#include "pci_session_component.h"
|
#include "pci_session_component.h"
|
||||||
#include "pci_device_config.h"
|
#include "pci_device_config.h"
|
||||||
#include "device_pd.h"
|
#include "device_pd.h"
|
||||||
@ -119,15 +118,15 @@ struct Platform::Main
|
|||||||
|
|
||||||
if (_system_rom) {
|
if (_system_rom) {
|
||||||
/* wait for system state changes, e.g. reset and acpi_ready */
|
/* 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);
|
system_state->sigh(_system_report);
|
||||||
acpi_ready.construct("acpi_ready");
|
acpi_ready.construct(env, "acpi_ready");
|
||||||
acpi_ready->sigh(_system_report);
|
acpi_ready->sigh(_system_report);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_for_acpi == "yes") {
|
if (wait_for_acpi == "yes") {
|
||||||
/* for ACPI support, wait for the first valid acpi report */
|
/* for ACPI support, wait for the first valid acpi report */
|
||||||
acpi_rom.construct("acpi");
|
acpi_rom.construct(env, "acpi");
|
||||||
acpi_rom->sigh(_acpi_report);
|
acpi_rom->sigh(_acpi_report);
|
||||||
/* check if already valid */
|
/* check if already valid */
|
||||||
acpi_update();
|
acpi_update();
|
||||||
|
@ -36,12 +36,14 @@ class Nonpci::Ps2 : public Platform::Device_component
|
|||||||
|
|
||||||
public:
|
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),
|
Platform::Device_component(env, session, IRQ_KEYBOARD, heap_for_irq),
|
||||||
_ep(ep),
|
_ep(env.ep().rpc_ep()),
|
||||||
_irq_mouse(IRQ_MOUSE, ~0UL),
|
_irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq),
|
||||||
_data(REG_DATA, ACCESS_WIDTH), _status(REG_STATUS, ACCESS_WIDTH)
|
_data(env, REG_DATA, ACCESS_WIDTH),
|
||||||
|
_status(env, REG_STATUS, ACCESS_WIDTH)
|
||||||
{
|
{
|
||||||
_ep.manage(&_irq_mouse);
|
_ep.manage(&_irq_mouse);
|
||||||
}
|
}
|
||||||
@ -97,10 +99,11 @@ class Nonpci::Pit : public Platform::Device_component
|
|||||||
|
|
||||||
public:
|
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),
|
Platform::Device_component(env, session, IRQ_PIT, heap_for_irq),
|
||||||
_ports(PIT_PORT, PORTS_WIDTH)
|
_ports(env, PIT_PORT, PORTS_WIDTH)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Genode::Io_port_session_capability io_port(Genode::uint8_t io_port) override
|
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) {
|
switch(devices_i) {
|
||||||
case 0:
|
case 0:
|
||||||
dev = new (_md_alloc) Nonpci::Ps2(_ep, *this);
|
dev = new (_md_alloc) Nonpci::Ps2(_env, *this, _global_heap);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
dev = new (_md_alloc) Nonpci::Pit(_ep, *this);
|
dev = new (_md_alloc) Nonpci::Pit(_env, *this, _global_heap);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return Device_capability();
|
return Device_capability();
|
||||||
}
|
}
|
||||||
|
|
||||||
_device_list.insert(dev);
|
_device_list.insert(dev);
|
||||||
return _ep.manage(dev);
|
return _env.ep().rpc_ep().manage(dev);
|
||||||
} catch (Genode::Allocator::Out_of_memory) {
|
} catch (Genode::Allocator::Out_of_memory) {
|
||||||
throw Out_of_metadata();
|
throw Out_of_metadata();
|
||||||
} catch (Genode::Parent::Service_denied) {
|
} catch (Genode::Parent::Service_denied) {
|
||||||
|
@ -24,6 +24,8 @@ namespace Platform {
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Genode::Env &_env;
|
||||||
|
|
||||||
enum { REG_ADDR = 0xcf8, REG_DATA = 0xcfc, REG_SIZE = 4 };
|
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
|
* Once created, each I/O-port session persists until
|
||||||
* the PCI driver gets killed by its parent.
|
* 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;
|
return &io_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +81,8 @@ namespace Platform {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Config_access(Genode::Env &env) : _env(env) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read value from config space of specified device/function
|
* Read value from config space of specified device/function
|
||||||
*
|
*
|
||||||
|
@ -32,7 +32,7 @@ Genode::Io_port_session_capability Platform::Device_component::io_port(Genode::u
|
|||||||
return _io_port_conn[v_id]->cap();
|
return _io_port_conn[v_id]->cap();
|
||||||
|
|
||||||
try {
|
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();
|
return _io_port_conn[v_id]->cap();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
return Genode::Io_port_session_capability();
|
return Genode::Io_port_session_capability();
|
||||||
@ -68,7 +68,8 @@ Genode::Io_mem_session_capability Platform::Device_component::io_mem(Genode::uin
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
bool const wc = caching == Genode::Cache_attribute::WRITE_COMBINED;
|
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);
|
res_size, wc);
|
||||||
_io_mem[i].insert(io_mem);
|
_io_mem[i].insert(io_mem);
|
||||||
return io_mem->cap();
|
return io_mem->cap();
|
||||||
@ -144,16 +145,19 @@ Genode::Irq_session_capability Platform::Device_component::irq(Genode::uint8_t i
|
|||||||
if (!_device_config.valid()) {
|
if (!_device_config.valid()) {
|
||||||
/* Non PCI devices */
|
/* Non PCI devices */
|
||||||
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
_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();
|
return _irq_session->cap();
|
||||||
}
|
}
|
||||||
|
|
||||||
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
_irq_session = construct_at<Irq_session_component>(_mem_irq_component,
|
||||||
_configure_irq(_irq_line),
|
_configure_irq(_irq_line),
|
||||||
(!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space);
|
(!_session.msi_usage() || !_msi_cap()) ? ~0UL : _config_space,
|
||||||
_ep.manage(_irq_session);
|
_env, _global_heap);
|
||||||
|
_env.ep().rpc_ep().manage(_irq_session);
|
||||||
|
|
||||||
Genode::uint16_t msi_cap = _msi_cap();
|
Genode::uint16_t msi_cap = _msi_cap();
|
||||||
|
|
||||||
|
@ -34,22 +34,25 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Genode::Env &_env;
|
||||||
Device_config _device_config;
|
Device_config _device_config;
|
||||||
Genode::addr_t _config_space;
|
Genode::addr_t _config_space;
|
||||||
Config_access _config_access;
|
Config_access _config_access = { _env };
|
||||||
Genode::Rpc_entrypoint &_ep;
|
|
||||||
Platform::Session_component &_session;
|
Platform::Session_component &_session;
|
||||||
unsigned short _irq_line;
|
unsigned short _irq_line;
|
||||||
Irq_session_component *_irq_session = nullptr;
|
Irq_session_component *_irq_session = nullptr;
|
||||||
|
|
||||||
Genode::Constructible<Genode::Io_mem_connection> _io_mem_config_extended;
|
Genode::Constructible<Genode::Io_mem_connection> _io_mem_config_extended;
|
||||||
|
|
||||||
|
Genode::Allocator &_global_heap;
|
||||||
|
|
||||||
class Io_mem : public Genode::Io_mem_connection,
|
class Io_mem : public Genode::Io_mem_connection,
|
||||||
public Genode::List<Io_mem>::Element
|
public Genode::List<Io_mem>::Element
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Io_mem (Genode::addr_t base, Genode::size_t size, bool wc)
|
Io_mem (Genode::Env &env, Genode::addr_t base,
|
||||||
: Genode::Io_mem_connection(base, size, wc) { }
|
Genode::size_t size, bool wc)
|
||||||
|
: Genode::Io_mem_connection(env, base, size, wc) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -182,15 +185,18 @@ class Platform::Device_component : public Genode::Rpc_object<Platform::Device>,
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Device_component(Device_config device_config, Genode::addr_t addr,
|
Device_component(Genode::Env &env,
|
||||||
Genode::Rpc_entrypoint &ep,
|
Device_config device_config, Genode::addr_t addr,
|
||||||
Platform::Session_component &session,
|
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),
|
_device_config(device_config), _config_space(addr),
|
||||||
_ep(ep), _session(session),
|
_session(session),
|
||||||
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
|
||||||
Platform::Device::ACCESS_8BIT)),
|
Platform::Device::ACCESS_8BIT)),
|
||||||
|
_global_heap(global_heap),
|
||||||
_slab_ioport(&md_alloc, &_slab_ioport_block_data),
|
_slab_ioport(&md_alloc, &_slab_ioport_block_data),
|
||||||
_slab_iomem(&md_alloc, &_slab_iomem_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
|
* Constructor for non PCI devices
|
||||||
*/
|
*/
|
||||||
Device_component(Genode::Rpc_entrypoint &ep,
|
Device_component(Genode::Env &env,
|
||||||
Platform::Session_component &session, unsigned irq)
|
Platform::Session_component &session, unsigned irq,
|
||||||
|
Genode::Allocator &global_heap)
|
||||||
:
|
:
|
||||||
|
_env(env),
|
||||||
_config_space(~0UL),
|
_config_space(~0UL),
|
||||||
_ep(ep), _session(session),
|
_session(session),
|
||||||
_irq_line(irq),
|
_irq_line(irq),
|
||||||
|
_global_heap(global_heap),
|
||||||
_slab_ioport(nullptr, &_slab_ioport_block_data),
|
_slab_ioport(nullptr, &_slab_ioport_block_data),
|
||||||
_slab_iomem(nullptr, &_slab_iomem_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()
|
~Device_component()
|
||||||
{
|
{
|
||||||
if (_irq_session) {
|
if (_irq_session) {
|
||||||
_ep.dissolve(_irq_session);
|
_env.ep().rpc_ep().dissolve(_irq_session);
|
||||||
_irq_session->~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()) {
|
if (!_io_mem_config_extended.constructed()) {
|
||||||
try {
|
try {
|
||||||
_io_mem_config_extended.construct(_config_space, 0x1000);
|
_io_mem_config_extended.construct(_env, _config_space, 0x1000);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
_config_space = ~0UL;
|
_config_space = ~0UL;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
struct Platform::Device_pd_component : Genode::Rpc_object<Device_pd,
|
||||||
Device_pd_component>
|
Device_pd_component>
|
||||||
{
|
{
|
||||||
|
Genode::Env &_env;
|
||||||
Genode::Region_map &_address_space;
|
Genode::Region_map &_address_space;
|
||||||
|
|
||||||
Device_pd_component(Genode::Region_map &address_space)
|
Device_pd_component(Genode::Region_map &address_space, Genode::Env &env)
|
||||||
: _address_space(address_space) { }
|
: _env(env), _address_space(address_space) { }
|
||||||
|
|
||||||
void attach_dma_mem(Genode::Dataspace_capability);
|
void attach_dma_mem(Genode::Dataspace_capability);
|
||||||
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);
|
void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t);
|
||||||
|
@ -37,12 +37,13 @@
|
|||||||
#include "device_pd.h"
|
#include "device_pd.h"
|
||||||
|
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
bool bus_valid(int bus = 0);
|
|
||||||
unsigned short bridge_bdf(unsigned char bus);
|
unsigned short bridge_bdf(unsigned char bus);
|
||||||
|
|
||||||
|
class Pci_buses;
|
||||||
|
class Ram_dataspace;
|
||||||
class Rmrr;
|
class Rmrr;
|
||||||
class Root;
|
class Root;
|
||||||
class Ram_dataspace;
|
class Session_component;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Platform::Ram_dataspace : public Genode::List<Ram_dataspace>::Element {
|
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)
|
: _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 bus = config.bus_number();
|
||||||
Genode::uint8_t device = config.device_number();
|
Genode::uint8_t device = config.device_number();
|
||||||
@ -105,7 +107,7 @@ class Platform::Rmrr : public Genode::List<Platform::Rmrr>::Element
|
|||||||
if (_cap.valid())
|
if (_cap.valid())
|
||||||
return _cap;
|
return _cap;
|
||||||
|
|
||||||
_io_mem.construct(_start, _end - _start + 1);
|
_io_mem.construct(env, _start, _end - _start + 1);
|
||||||
_cap = _io_mem->dataspace();
|
_cap = _io_mem->dataspace();
|
||||||
return _cap;
|
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>
|
class Platform::Session_component : public Genode::Rpc_object<Session>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Genode::Rpc_entrypoint &_ep;
|
Genode::Env &_env;
|
||||||
Genode::Rpc_entrypoint &_device_pd_ep;
|
Genode::Rpc_entrypoint &_device_pd_ep;
|
||||||
Genode::Ram_session_guard _env_ram;
|
Genode::Ram_session_guard _env_ram;
|
||||||
Genode::Ram_session_capability _env_ram_cap;
|
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_label const _label;
|
||||||
Genode::Session_policy const _policy { _label };
|
Genode::Session_policy const _policy { _label };
|
||||||
Genode::List<Device_component> _device_list;
|
Genode::List<Device_component> _device_list;
|
||||||
|
Platform::Pci_buses &_pci_bus;
|
||||||
|
Genode::Heap &_global_heap;
|
||||||
bool _no_device_pd = false;
|
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
|
* Restrict physical address to 3G on 32bit, 4G on 64bit
|
||||||
*/
|
*/
|
||||||
Genode::Ram_connection _ram {
|
Genode::Ram_connection _ram { _env, _label.string(), 0,
|
||||||
_label.string(), 0, (sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
|
(sizeof(void *) == 4) ? 0xc0000000UL : 0x100000000UL };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Associate session RAM session with platform_drv _ram session and
|
* 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;
|
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
|
* List containing extended PCI config space information
|
||||||
@ -565,17 +595,19 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
|||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Session_component(Genode::Env &env,
|
Session_component(Genode::Env &env,
|
||||||
Genode::Rpc_entrypoint &ep,
|
|
||||||
Genode::Rpc_entrypoint &device_pd_ep,
|
Genode::Rpc_entrypoint &device_pd_ep,
|
||||||
|
Platform::Pci_buses &buses,
|
||||||
|
Genode::Heap &global_heap,
|
||||||
char const *args)
|
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(),
|
_env_ram(env.ram(), env.ram_session_cap(),
|
||||||
Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
|
Genode::Arg_string::find_arg(args, "ram_quota").long_value(0)),
|
||||||
_env_ram_cap(env.ram_session_cap()),
|
_env_ram_cap(env.ram_session_cap()),
|
||||||
_local_rm(env.rm()),
|
_local_rm(env.rm()),
|
||||||
_md_alloc(_env_ram, 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 */
|
/* non-pci devices */
|
||||||
_policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) {
|
_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,
|
static void add_config_space(Genode::uint32_t bdf_start,
|
||||||
Genode::uint32_t func_count,
|
Genode::uint32_t func_count,
|
||||||
Genode::addr_t base)
|
Genode::addr_t base,
|
||||||
|
Genode::Allocator &heap)
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
Config_space * space =
|
Config_space * space =
|
||||||
new (env()->heap()) Config_space(bdf_start, func_count,
|
new (heap) Config_space(bdf_start, func_count, base);
|
||||||
base);
|
|
||||||
config_space_list().insert(space);
|
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.
|
* Create the interface to the PCI config space.
|
||||||
* This involves the creation of I/O port sessions.
|
* This involves the creation of I/O port sessions.
|
||||||
*/
|
*/
|
||||||
Config_access config_access;
|
Config_access config_access(_env);
|
||||||
|
|
||||||
/* lookup device component for previous device */
|
/* lookup device component for previous device */
|
||||||
auto lambda = [&] (Device_component *prev)
|
auto lambda = [&] (Device_component *prev)
|
||||||
@ -759,7 +791,7 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
function += 1;
|
function += 1;
|
||||||
if (!_find_next(bus, device, function, &config,
|
if (!_pci_bus.find_next(bus, device, function, &config,
|
||||||
&config_access))
|
&config_access))
|
||||||
return Device_capability();
|
return Device_capability();
|
||||||
|
|
||||||
@ -788,8 +820,8 @@ class Platform::Session_component : public Genode::Rpc_object<Session>
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
Device_component * dev = new (_md_alloc)
|
Device_component * dev = new (_md_alloc)
|
||||||
Device_component(config, config_space, _ep, *this,
|
Device_component(_env, config, config_space, *this,
|
||||||
_md_alloc);
|
_md_alloc, _global_heap);
|
||||||
|
|
||||||
/* 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(Device_config::MAX_BUSES * bus +
|
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);
|
function, 1);
|
||||||
|
|
||||||
_device_list.insert(dev);
|
_device_list.insert(dev);
|
||||||
return _ep.manage(dev);
|
return _env.ep().rpc_ep().manage(dev);
|
||||||
} catch (Genode::Allocator::Out_of_memory) {
|
} catch (Genode::Allocator::Out_of_memory) {
|
||||||
throw Out_of_metadata();
|
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
|
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_config::MAX_DEVICES * dev + func, 1);
|
||||||
|
|
||||||
_device_list.remove(device);
|
_device_list.remove(device);
|
||||||
_ep.dissolve(device);
|
_env.ep().rpc_ep().dissolve(device);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* lookup device component for previous device */
|
/* lookup device component for previous device */
|
||||||
_ep.apply(device_cap, lambda);
|
_env.ep().rpc_ep().apply(device_cap, lambda);
|
||||||
|
|
||||||
if (!device) return;
|
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());
|
_device_pd->session().assign_pci(io_mem, device->config().bdf());
|
||||||
|
|
||||||
for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) {
|
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())
|
if (rmrr_cap.valid())
|
||||||
_device_pd->session().attach_dma_mem(rmrr_cap);
|
_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::Env &_env;
|
||||||
Genode::Rpc_entrypoint _device_pd_ep;
|
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;
|
using namespace Genode;
|
||||||
|
|
||||||
Config_access config_access;
|
Config_access config_access(env);
|
||||||
|
|
||||||
Xml_node xml_acpi(acpi_rom);
|
Xml_node xml_acpi(acpi_rom);
|
||||||
if (!xml_acpi.has_type("acpi"))
|
if (!xml_acpi.has_type("acpi"))
|
||||||
@ -1016,7 +1050,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
node.attribute("base").value(&base);
|
node.attribute("base").value(&base);
|
||||||
|
|
||||||
Session_component::add_config_space(bdf_start, func_count,
|
Session_component::add_config_space(bdf_start, func_count,
|
||||||
base);
|
base, _heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.has_type("irq_override")) {
|
if (node.has_type("irq_override")) {
|
||||||
@ -1029,8 +1063,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
node.attribute("flags").value(&flags);
|
node.attribute("flags").value(&flags);
|
||||||
|
|
||||||
using Platform::Irq_override;
|
using Platform::Irq_override;
|
||||||
Irq_override * o = new (env()->heap()) Irq_override(irq,
|
Irq_override * o = new (_heap) Irq_override(irq, gsi,
|
||||||
gsi,
|
|
||||||
flags);
|
flags);
|
||||||
Irq_override::list()->insert(o);
|
Irq_override::list()->insert(o);
|
||||||
}
|
}
|
||||||
@ -1043,7 +1076,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
if (node.num_sub_nodes() == 0)
|
if (node.num_sub_nodes() == 0)
|
||||||
throw 2;
|
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);
|
Rmrr::list()->insert(rmrr);
|
||||||
|
|
||||||
for (unsigned s = 0; s < node.num_sub_nodes(); s++) {
|
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);
|
Device::ACCESS_8BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
rmrr->add(new (env()->heap()) Rmrr::Bdf(bus, dev,
|
rmrr->add(new (_heap) Rmrr::Bdf(bus, dev, func));
|
||||||
func));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,10 +1148,8 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
*/
|
*/
|
||||||
bridge_bdf = 0;
|
bridge_bdf = 0;
|
||||||
|
|
||||||
Irq_routing * r = new (env()->heap()) Irq_routing(gsi,
|
Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf,
|
||||||
bridge_bdf,
|
device, device_pin);
|
||||||
device,
|
|
||||||
device_pin);
|
|
||||||
Irq_routing::list()->insert(r);
|
Irq_routing::list()->insert(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1130,7 +1160,7 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return new (md_alloc())
|
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) {
|
catch (Genode::Session_policy::No_policy_defined) {
|
||||||
Genode::error("Invalid session request, no matching policy for ",
|
Genode::error("Invalid session request, no matching policy for ",
|
||||||
@ -1164,12 +1194,9 @@ class Platform::Root : public Genode::Root_component<Session_component>
|
|||||||
_env(env),
|
_env(env),
|
||||||
_device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave")
|
_device_pd_ep(&env.pd(), STACK_SIZE, "device_pd_slave")
|
||||||
{
|
{
|
||||||
/* enforce initial bus scan */
|
|
||||||
bus_valid();
|
|
||||||
|
|
||||||
if (acpi_rom) {
|
if (acpi_rom) {
|
||||||
try {
|
try {
|
||||||
_parse_report_rom(acpi_rom);
|
_parse_report_rom(env, acpi_rom);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Genode::error("PCI config space data could not be parsed.");
|
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)
|
if (!io_port_space)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Config_access config_access;
|
Config_access config_access(_env);
|
||||||
const unsigned raw_access_size = Fadt::Gas::Access_size::get(fadt.reset_type);
|
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);
|
const bool reset_support = config_access.reset_support(fadt.reset_addr, raw_access_size);
|
||||||
if (!reset_support)
|
if (!reset_support)
|
||||||
|
@ -33,19 +33,8 @@ unsigned short Platform::bridge_bdf(unsigned char bus)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Platform::Pci_buses::scan_bus(Config_access &config_access,
|
||||||
/**
|
Genode::Allocator &heap, unsigned char bus)
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
struct Valid_buses
|
|
||||||
{
|
|
||||||
bool valid[Device_config::MAX_BUSES];
|
|
||||||
|
|
||||||
void scan_bus(Config_access &config_access, unsigned char bus = 0)
|
|
||||||
{
|
{
|
||||||
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
|
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
|
||||||
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
|
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
|
||||||
@ -60,32 +49,26 @@ bool Platform::bus_valid(int bus)
|
|||||||
* There is at least one device on the current bus, so
|
* There is at least one device on the current bus, so
|
||||||
* we mark it as valid.
|
* we mark it as valid.
|
||||||
*/
|
*/
|
||||||
valid[bus] = true;
|
if (!_valid.get(bus, 1))
|
||||||
|
_valid.set(bus, 1);
|
||||||
|
|
||||||
/* scan behind bridge */
|
/* scan behind bridge */
|
||||||
if (config.pci_bridge()) {
|
if (config.pci_bridge()) {
|
||||||
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
|
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
|
||||||
unsigned char sec_bus = config.read(&config_access,
|
unsigned char sec_bus = config.read(&config_access, 0x19,
|
||||||
0x19, Device::ACCESS_8BIT);
|
Device::ACCESS_8BIT);
|
||||||
unsigned char sub_bus = config.read(&config_access,
|
unsigned char sub_bus = config.read(&config_access, 0x20,
|
||||||
0x20, Device::ACCESS_8BIT);
|
Device::ACCESS_8BIT);
|
||||||
|
|
||||||
bridges()->insert(new (Genode::env()->heap()) Bridge(bus, dev, fun, sec_bus, sub_bus));
|
bridges()->insert(new (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];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
using Platform::Session_component;
|
using Platform::Session_component;
|
||||||
using Genode::Bit_array;
|
using Genode::Bit_array;
|
||||||
|
Reference in New Issue
Block a user