mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-08 20:30:17 +00:00
base: make irq_session asynchronous
second step options: factor out common parts of irq_session_component.cc options: use on foc arm no proxy threads Fixes #1456
This commit is contained in:
parent
e2cbc7c5b3
commit
faa25e1df6
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* \brief IRQ session interface for NOVA
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <base/lock.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
enum { STACK_SIZE = 4096 };
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator *_irq_alloc;
|
||||
Rpc_entrypoint _entrypoint;
|
||||
Irq_session_capability _cap;
|
||||
bool _attached;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* If an initialization error occurs, returned capability is invalid.
|
||||
*/
|
||||
Irq_session_capability cap() const { return _cap; }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq();
|
||||
Irq_signal signal();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
@ -22,57 +22,123 @@
|
||||
#include <codezero/syscalls.h>
|
||||
|
||||
|
||||
namespace Genode {
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
class Irq_proxy_component;
|
||||
}
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Platform-specific proxy code
|
||||
*/
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
{
|
||||
using namespace Codezero;
|
||||
private:
|
||||
|
||||
/* attach thread to IRQ when first called */
|
||||
if (!_attached) {
|
||||
int ret = l4_irq_control(IRQ_CONTROL_REGISTER, 0, _irq_number);
|
||||
if (ret < 0) {
|
||||
PERR("l4_irq_control(IRQ_CONTROL_REGISTER) returned %d", ret);
|
||||
sleep_forever();
|
||||
bool _irq_attached;
|
||||
|
||||
protected:
|
||||
|
||||
bool _associate() { return true; }
|
||||
|
||||
void _wait_for_irq()
|
||||
{
|
||||
using namespace Codezero;
|
||||
|
||||
/* attach thread to IRQ when first called */
|
||||
if (!_irq_attached) {
|
||||
int ret = l4_irq_control(IRQ_CONTROL_REGISTER, 0, _irq_number);
|
||||
if (ret < 0) {
|
||||
PERR("l4_irq_control(IRQ_CONTROL_REGISTER) returned %d", ret);
|
||||
sleep_forever();
|
||||
}
|
||||
_irq_attached = true;
|
||||
}
|
||||
|
||||
/* block for IRQ */
|
||||
int ret = l4_irq_control(IRQ_CONTROL_WAIT, 0, _irq_number);
|
||||
if (ret < 0)
|
||||
PWRN("l4_irq_control(IRQ_CONTROL_WAIT) returned %d", ret);
|
||||
}
|
||||
_attached = true;
|
||||
|
||||
void _ack_irq() { }
|
||||
|
||||
public:
|
||||
|
||||
Irq_proxy_component(long irq_number)
|
||||
:
|
||||
Irq_proxy(irq_number),
|
||||
_irq_attached(false)
|
||||
{
|
||||
_start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***************************
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
/* block for IRQ */
|
||||
int ret = l4_irq_control(IRQ_CONTROL_WAIT, 0, _irq_number);
|
||||
if (ret < 0)
|
||||
PWRN("l4_irq_control(IRQ_CONTROL_WAIT) returned %d", ret);
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_irq_alloc(irq_alloc),
|
||||
_entrypoint(cap_session, STACK_SIZE, "irq"),
|
||||
_attached(false)
|
||||
_irq_alloc(irq_alloc)
|
||||
{
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (!irq_alloc || (irq_number == -1)||
|
||||
irq_alloc->alloc_addr(1, irq_number).is_error()) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
return;
|
||||
if (irq_number == -1) {
|
||||
PERR("invalid IRQ number requested");
|
||||
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
/* check if IRQ thread was started before */
|
||||
_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
_irq_number = irq_number;
|
||||
_cap = Irq_session_capability(_entrypoint.manage(this));
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
PERR("not yet implemented");
|
||||
if (!_proxy) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <util/arg_string.h>
|
||||
|
||||
/* core includes */
|
||||
#include <irq_proxy.h>
|
||||
#include <irq_root.h>
|
||||
#include <util.h>
|
||||
|
||||
@ -28,101 +29,150 @@ namespace Fiasco {
|
||||
#include <l4/sys/types.h>
|
||||
}
|
||||
|
||||
namespace Genode {
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
class Irq_proxy_component;
|
||||
}
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq_number)
|
||||
/**
|
||||
* Platform-specific proxy code
|
||||
*/
|
||||
|
||||
class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
{
|
||||
using namespace Fiasco;
|
||||
protected:
|
||||
|
||||
int err;
|
||||
l4_threadid_t irq_tid;
|
||||
l4_umword_t dw0, dw1;
|
||||
l4_msgdope_t result;
|
||||
bool _associate()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_make_taskid_from_irq(irq_number, &irq_tid);
|
||||
int err;
|
||||
l4_threadid_t irq_tid;
|
||||
l4_umword_t dw0, dw1;
|
||||
l4_msgdope_t result;
|
||||
|
||||
/* boost thread to IRQ priority */
|
||||
enum { IRQ_PRIORITY = 0xC0 };
|
||||
l4_make_taskid_from_irq(_irq_number, &irq_tid);
|
||||
|
||||
l4_sched_param_t param = {sp:{prio:IRQ_PRIORITY, small:0, state:0, time_exp:0, time_man:0}};
|
||||
l4_threadid_t ext_preempter = L4_INVALID_ID;
|
||||
l4_threadid_t partner = L4_INVALID_ID;
|
||||
l4_sched_param_t old_param;
|
||||
l4_thread_schedule(l4_myself(), param, &ext_preempter, &partner, &old_param);
|
||||
/* boost thread to IRQ priority */
|
||||
enum { IRQ_PRIORITY = 0xC0 };
|
||||
|
||||
err = l4_ipc_receive(irq_tid,
|
||||
L4_IPC_SHORT_MSG, &dw0, &dw1,
|
||||
L4_IPC_BOTH_TIMEOUT_0, &result);
|
||||
l4_sched_param_t param = {sp:{prio:IRQ_PRIORITY, small:0, state:0,
|
||||
time_exp:0, time_man:0}};
|
||||
l4_threadid_t ext_preempter = L4_INVALID_ID;
|
||||
l4_threadid_t partner = L4_INVALID_ID;
|
||||
l4_sched_param_t old_param;
|
||||
l4_thread_schedule(l4_myself(), param, &ext_preempter, &partner,
|
||||
&old_param);
|
||||
|
||||
if (err != L4_IPC_RETIMEOUT) PERR("IRQ association failed");
|
||||
err = l4_ipc_receive(irq_tid,
|
||||
L4_IPC_SHORT_MSG, &dw0, &dw1,
|
||||
L4_IPC_BOTH_TIMEOUT_0, &result);
|
||||
|
||||
return (err == L4_IPC_RETIMEOUT);
|
||||
if (err != L4_IPC_RETIMEOUT) PERR("IRQ association failed");
|
||||
|
||||
return (err == L4_IPC_RETIMEOUT);
|
||||
}
|
||||
|
||||
void _wait_for_irq()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_threadid_t irq_tid;
|
||||
l4_umword_t dw0=0, dw1=0;
|
||||
l4_msgdope_t result;
|
||||
|
||||
l4_make_taskid_from_irq(_irq_number, &irq_tid);
|
||||
|
||||
do {
|
||||
l4_ipc_call(irq_tid,
|
||||
L4_IPC_SHORT_MSG, 0, 0,
|
||||
L4_IPC_SHORT_MSG, &dw0, &dw1,
|
||||
L4_IPC_NEVER, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
PERR("Ipc error %lx", L4_IPC_ERROR(result));
|
||||
} while (L4_IPC_IS_ERROR(result));
|
||||
}
|
||||
|
||||
void _ack_irq() { }
|
||||
|
||||
public:
|
||||
|
||||
Irq_proxy_component(long irq_number)
|
||||
:
|
||||
Irq_proxy(irq_number)
|
||||
{
|
||||
_start();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***************************
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_threadid_t irq_tid;
|
||||
l4_umword_t dw0=0, dw1=0;
|
||||
l4_msgdope_t result;
|
||||
|
||||
l4_make_taskid_from_irq(_irq_number, &irq_tid);
|
||||
|
||||
do {
|
||||
l4_ipc_call(irq_tid,
|
||||
L4_IPC_SHORT_MSG, 0, 0,
|
||||
L4_IPC_SHORT_MSG, &dw0, &dw1,
|
||||
L4_IPC_NEVER, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result)) PERR("Ipc error %lx", L4_IPC_ERROR(result));
|
||||
} while (L4_IPC_IS_ERROR(result));
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_irq_alloc(irq_alloc),
|
||||
_ep(cap_session, STACK_SIZE, "irqctrl"),
|
||||
_control_cap(_ep.manage(&_control_component)),
|
||||
_control_client(_control_cap)
|
||||
_irq_alloc(irq_alloc)
|
||||
{
|
||||
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
||||
if (shared) {
|
||||
PWRN("IRQ sharing not supported");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (irq_number == -1 || !irq_alloc ||
|
||||
irq_alloc->alloc_addr(1, irq_number).is_error()) {
|
||||
PERR("Unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Invalid_args();
|
||||
if (irq_number == -1) {
|
||||
PERR("invalid IRQ number requested");
|
||||
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
/* check if IRQ thread was started before */
|
||||
_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
_irq_number = irq_number;
|
||||
|
||||
if (!_control_client.associate_to_irq(irq_number)) {
|
||||
PWRN("IRQ association failed");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
/* initialize capability */
|
||||
_irq_cap = Irq_session_capability(_ep.manage(this));
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
PERR("Implement me, immediately!");
|
||||
if (!_proxy) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
@ -4,6 +4,5 @@ LD_TEXT_ADDR = 0x80100000
|
||||
|
||||
REQUIRES += arm foc_arndale
|
||||
SRC_CC += arm/platform_arm.cc
|
||||
INC_DIR += $(REP_DIR)/src/core/include/arm
|
||||
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)
|
||||
|
@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
|
||||
|
||||
REQUIRES += arm foc_imx53
|
||||
SRC_CC += arm/platform_arm.cc
|
||||
INC_DIR += $(REP_DIR)/src/core/include/arm
|
||||
|
||||
LD_TEXT_ADDR = 0x70140000
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* \brief Base class for shared interrupts on ARM
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2012-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_
|
||||
|
||||
#include <irq_proxy.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* On ARM we disable shared interrupts
|
||||
*/
|
||||
typedef Irq_proxy_single Irq_proxy_base;
|
||||
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_ */
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* \brief IRQ session interface for Fiasco.OC
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-01-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <base/lock.h>
|
||||
#include <base/semaphore.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_proxy_component;
|
||||
|
||||
class Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
/*
|
||||
* Each IRQ session uses a dedicated server activation
|
||||
*/
|
||||
enum { STACK_SIZE = 2048 };
|
||||
Rpc_entrypoint _ep;
|
||||
|
||||
Irq_session_capability _irq_cap;
|
||||
Irq_proxy_component *_proxy;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* If an initialization error occurs, returned capability is invalid.
|
||||
*/
|
||||
Irq_session_capability cap() const { return _irq_cap; }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq();
|
||||
Irq_signal signal();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* \brief Base class for shared interrupts on x86
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2012-10-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_
|
||||
|
||||
#include <irq_proxy.h>
|
||||
|
||||
namespace Genode {
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_ */
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_proxy_component.h>
|
||||
#include <irq_session_component.h>
|
||||
#include <platform.h>
|
||||
#include <util.h>
|
||||
@ -39,6 +38,7 @@ using namespace Genode;
|
||||
namespace Genode {
|
||||
class Interrupt_handler;
|
||||
class Irq_proxy_component;
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,10 +69,10 @@ class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
{
|
||||
private:
|
||||
|
||||
Cap_index *_cap;
|
||||
Semaphore _sem;
|
||||
long _trigger; /* interrupt trigger */
|
||||
long _polarity; /* interrupt polarity */
|
||||
Cap_index *_cap;
|
||||
Semaphore _sem;
|
||||
Irq_session::Trigger _trigger; /* interrupt trigger */
|
||||
Irq_session::Polarity _polarity; /* interrupt polarity */
|
||||
|
||||
Native_thread _capability() const { return _cap->kcap(); }
|
||||
|
||||
@ -123,107 +123,162 @@ class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
:
|
||||
Irq_proxy_base(irq_number),
|
||||
_cap(cap_map()->insert(platform_specific()->cap_id_alloc()->alloc())),
|
||||
_sem(), _trigger(-1), _polarity(-1) { }
|
||||
|
||||
Semaphore *semaphore() { return &_sem; }
|
||||
|
||||
void start(long trigger, long polarity)
|
||||
_sem(), _trigger(Irq_session::TRIGGER_UNCHANGED),
|
||||
_polarity(Irq_session::POLARITY_UNCHANGED)
|
||||
{
|
||||
_trigger = trigger;
|
||||
_polarity = polarity;
|
||||
_start();
|
||||
}
|
||||
|
||||
bool match_mode(long trigger, long polarity)
|
||||
Semaphore *semaphore() { return &_sem; }
|
||||
|
||||
Irq_session::Trigger trigger() const { return _trigger; }
|
||||
Irq_session::Polarity polarity() const { return _polarity; }
|
||||
|
||||
void setup_irq_mode(Irq_session::Trigger t, Irq_session::Polarity p)
|
||||
{
|
||||
if (trigger == Irq_session::TRIGGER_UNCHANGED &&
|
||||
polarity == Irq_session::POLARITY_UNCHANGED)
|
||||
return true;
|
||||
_trigger = t;
|
||||
_polarity = p;
|
||||
|
||||
if (_trigger < 0 && _polarity < 0)
|
||||
return true;
|
||||
|
||||
return _trigger == trigger && _polarity == polarity;
|
||||
/* set interrupt mode */
|
||||
Platform::setup_irq_mode(_irq_number, _trigger, _polarity);
|
||||
}
|
||||
|
||||
long trigger() const { return _trigger; }
|
||||
long polarity() const { return _polarity; }
|
||||
};
|
||||
|
||||
|
||||
/********************************
|
||||
** IRQ session implementation **
|
||||
********************************/
|
||||
/***************************
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_ep(cap_session, STACK_SIZE, "irqctrl"),
|
||||
_proxy(0)
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (irq_number == -1) {
|
||||
PERR("Unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Invalid_args();
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
long irq_trigger = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
|
||||
irq_trigger = irq_trigger == -1 ? 0 : irq_trigger;
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
long irq_polarity = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
|
||||
irq_polarity = irq_polarity == -1 ? 0 : irq_polarity;
|
||||
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
{
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (irq_number == -1) {
|
||||
PERR("invalid IRQ number requested");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
long irq_t = Arg_string::find_arg(args, "irq_trigger").long_value(-1);
|
||||
long irq_p = Arg_string::find_arg(args, "irq_polarity").long_value(-1);
|
||||
|
||||
Irq_session::Trigger irq_trigger;
|
||||
Irq_session::Polarity irq_polarity;
|
||||
|
||||
switch(irq_t) {
|
||||
case -1:
|
||||
case Irq_session::TRIGGER_UNCHANGED:
|
||||
irq_trigger = Irq_session::TRIGGER_UNCHANGED;
|
||||
break;
|
||||
case Irq_session::TRIGGER_EDGE:
|
||||
irq_trigger = Irq_session::TRIGGER_EDGE;
|
||||
break;
|
||||
case Irq_session::TRIGGER_LEVEL:
|
||||
irq_trigger = Irq_session::TRIGGER_LEVEL;
|
||||
break;
|
||||
default:
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
switch(irq_p) {
|
||||
case -1:
|
||||
case POLARITY_UNCHANGED:
|
||||
irq_polarity = POLARITY_UNCHANGED;
|
||||
break;
|
||||
case POLARITY_HIGH:
|
||||
irq_polarity = POLARITY_HIGH;
|
||||
break;
|
||||
case POLARITY_LOW:
|
||||
irq_polarity = POLARITY_LOW;
|
||||
break;
|
||||
default:
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
/*
|
||||
* temorary hack for fiasco.oc using the local-apic,
|
||||
* temporary hack for fiasco.oc using the local-apic,
|
||||
* where old pic-line 0 maps to 2
|
||||
*/
|
||||
if (irq_number == 0)
|
||||
irq_number = 2;
|
||||
|
||||
if (!(_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number,
|
||||
irq_alloc))) {
|
||||
PERR("No proxy for IRQ %lu found", irq_number);
|
||||
/* check if IRQ thread was started before */
|
||||
_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
bool setup = false;
|
||||
bool fail = false;
|
||||
|
||||
/* sanity check */
|
||||
if (!_proxy->match_mode(irq_trigger, irq_polarity)) {
|
||||
PERR("Interrupt mode mismatch: IRQ %ld current mode: t: %ld p: %ld"
|
||||
"request mode: trg: %ld p: %ld",
|
||||
if (irq_trigger != TRIGGER_UNCHANGED && _proxy->trigger() != irq_trigger) {
|
||||
if (_proxy->trigger() == TRIGGER_UNCHANGED)
|
||||
setup = true;
|
||||
else
|
||||
fail = true;
|
||||
}
|
||||
|
||||
if (irq_polarity != POLARITY_UNCHANGED && _proxy->polarity() != irq_polarity) {
|
||||
if (_proxy->polarity() == POLARITY_UNCHANGED)
|
||||
setup = true;
|
||||
else
|
||||
fail = true;
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
PERR("Interrupt mode mismatch: IRQ %ld current mode: t: %d p: %d "
|
||||
"request mode: trg: %d p: %d",
|
||||
irq_number, _proxy->trigger(), _proxy->polarity(),
|
||||
irq_trigger, irq_polarity);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
/* set interrupt mode and start proxy */
|
||||
_proxy->start(irq_trigger, irq_polarity);
|
||||
if (setup)
|
||||
/* set interrupt mode */
|
||||
_proxy->setup_irq_mode(irq_trigger, irq_polarity);
|
||||
|
||||
if (!_proxy->add_sharer())
|
||||
throw Root::Unavailable();
|
||||
|
||||
/* initialize capability */
|
||||
_irq_cap = _ep.manage(this);
|
||||
_irq_number = irq_number;
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
_proxy->wait_for_irq();
|
||||
if (!_proxy) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component() {
|
||||
_proxy->remove_sharer(); }
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,6 +4,5 @@ LD_TEXT_ADDR = 0x80140000
|
||||
|
||||
REQUIRES += arm foc_panda
|
||||
SRC_CC += arm/platform_arm.cc
|
||||
INC_DIR += $(REP_DIR)/src/core/include/arm
|
||||
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)
|
||||
|
@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
|
||||
|
||||
REQUIRES += arm foc_pbxa9
|
||||
SRC_CC += arm/platform_arm.cc
|
||||
INC_DIR += $(REP_DIR)/src/core/include/arm
|
||||
|
||||
LD_TEXT_ADDR = 0x70490000
|
||||
|
||||
|
@ -2,7 +2,6 @@ include $(PRG_DIR)/../target.inc
|
||||
|
||||
REQUIRES += arm foc_vea9x4
|
||||
SRC_CC += arm/platform_arm.cc
|
||||
INC_DIR += $(REP_DIR)/src/core/include/arm
|
||||
|
||||
LD_TEXT_ADDR = 0x60490000
|
||||
|
||||
|
@ -5,7 +5,5 @@ REQUIRES += x86
|
||||
SRC_CC += io_port_session_component.cc \
|
||||
x86/platform_x86.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/core/include/x86
|
||||
|
||||
vpath io_port_session_component.cc $(GEN_CORE_DIR)/x86
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)/x86
|
||||
|
@ -207,12 +207,10 @@ namespace Kernel
|
||||
* Await any context of a receiver and optionally ack a context before
|
||||
*
|
||||
* \param receiver_id kernel name of the targeted signal receiver
|
||||
* \param context_id kernel name of a context that shall be acknowledged
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If context is set to 0, the call doesn't acknowledge any context.
|
||||
* If this call returns 0, an instance of 'Signal::Data' is located at the
|
||||
* base of the callers UTCB. Every occurence of a signal is provided
|
||||
* through this function until it gets delivered through this function or
|
||||
@ -223,10 +221,9 @@ namespace Kernel
|
||||
* deliver again unless its last delivery has been acknowledged via
|
||||
* ack_signal.
|
||||
*/
|
||||
inline int await_signal(unsigned const receiver_id,
|
||||
unsigned const context_id)
|
||||
inline int await_signal(unsigned const receiver_id)
|
||||
{
|
||||
return call(call_id_await_signal(), receiver_id, context_id);
|
||||
return call(call_id_await_signal(), receiver_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* \brief Client-side IRQ session interface - specific for base-hw
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <irq_session/client.h>
|
||||
|
||||
void Genode::Irq_session_client::wait_for_irq()
|
||||
{
|
||||
while (Kernel::await_signal(irq_signal.receiver_id,
|
||||
irq_signal.context_id))
|
||||
{
|
||||
PERR("failed to receive interrupt");
|
||||
}
|
||||
}
|
@ -189,7 +189,7 @@ bool Signal_receiver::pending() { return Kernel::signal_pending(_cap.dst()); }
|
||||
Signal Signal_receiver::wait_for_signal()
|
||||
{
|
||||
/* await a signal */
|
||||
if (Kernel::await_signal(_cap.dst(), 0)) {
|
||||
if (Kernel::await_signal(_cap.dst())) {
|
||||
PERR("failed to receive signal");
|
||||
return Signal(Signal::Data());
|
||||
}
|
||||
|
@ -5,71 +5,59 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
* Copyright (C) 2013-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define _INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define __INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/list.h>
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Backend for IRQ sessions to core
|
||||
*/
|
||||
class Irq_session_component
|
||||
:
|
||||
public Rpc_object<Irq_session, Irq_session_component>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Range_allocator * const _irq_alloc;
|
||||
Irq_session_capability _cap;
|
||||
Irq_signal _signal;
|
||||
Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc interrupt allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session * const cap_session,
|
||||
Range_allocator * const irq_alloc,
|
||||
const char * const args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* If an initialization error occurs, returned _cap is invalid.
|
||||
*/
|
||||
Irq_session_capability cap() const { return _cap; }
|
||||
|
||||
|
||||
/*****************
|
||||
** Irq_session **
|
||||
*****************/
|
||||
|
||||
void wait_for_irq();
|
||||
|
||||
Irq_signal signal();
|
||||
};
|
||||
namespace Genode {
|
||||
class Irq_session_component;
|
||||
}
|
||||
|
||||
class Genode::Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator *_irq_alloc;
|
||||
Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
|
||||
|
||||
Signal_context_capability _sig_cap;
|
||||
|
||||
unsigned _find_irq_number(const char * const args);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void ack_irq();
|
||||
void sigh(Signal_context_capability) override;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
||||
|
@ -353,12 +353,14 @@ namespace Kernel
|
||||
/**
|
||||
* Create an interrupt object
|
||||
*
|
||||
* \param p memory donation for the irq object
|
||||
* \param irq_nr interrupt number
|
||||
* \param p memory donation for the irq object
|
||||
* \param irq_nr interrupt number
|
||||
* \param signal_context_id kernel name of the signal context
|
||||
*/
|
||||
inline void new_irq(addr_t const p, unsigned irq_nr)
|
||||
inline int new_irq(addr_t const p, unsigned irq_nr,
|
||||
unsigned signal_context_id)
|
||||
{
|
||||
call(call_id_new_irq(), (Call_arg) p, irq_nr);
|
||||
return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,8 +47,14 @@ namespace Genode
|
||||
|
||||
class Kernel::Irq : public Object_pool<Irq>::Item
|
||||
{
|
||||
public:
|
||||
|
||||
using Pool = Object_pool<Irq>;
|
||||
|
||||
protected:
|
||||
|
||||
Pool &_pool;
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt
|
||||
*/
|
||||
@ -56,16 +62,6 @@ class Kernel::Irq : public Object_pool<Irq>::Item
|
||||
|
||||
public:
|
||||
|
||||
using Pool = Object_pool<Irq>;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
*/
|
||||
Irq(unsigned const irq_id)
|
||||
: Pool::Item(irq_id) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -73,14 +69,9 @@ class Kernel::Irq : public Object_pool<Irq>::Item
|
||||
* \param pool pool this interrupt shall belong to
|
||||
*/
|
||||
Irq(unsigned const irq_id, Pool &pool)
|
||||
: Irq(irq_id) { pool.insert(this); }
|
||||
: Pool::Item(irq_id), _pool(pool) { _pool.insert(this); }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* By now, there is no use case to destruct interrupts
|
||||
*/
|
||||
virtual ~Irq() { PERR("destruction of interrupts not implemented"); }
|
||||
virtual ~Irq() { _pool.remove(this); }
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
@ -102,12 +93,12 @@ class Kernel::Irq : public Object_pool<Irq>::Item
|
||||
class Kernel::User_irq
|
||||
:
|
||||
public Kernel::Irq,
|
||||
public Signal_receiver,
|
||||
public Signal_context,
|
||||
public Signal_ack_handler
|
||||
{
|
||||
private:
|
||||
|
||||
Signal_context &_context;
|
||||
|
||||
/**
|
||||
* Get map that provides all user interrupts by their kernel names
|
||||
*/
|
||||
@ -127,30 +118,25 @@ class Kernel::User_irq
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
*/
|
||||
User_irq(unsigned const irq_id)
|
||||
: Irq(irq_id), Signal_context(this, 0)
|
||||
User_irq(unsigned const irq_id, Signal_context &context)
|
||||
: Irq(irq_id, *_pool()), _context(context)
|
||||
{
|
||||
_pool()->insert(this);
|
||||
disable();
|
||||
Signal_context::ack_handler(this);
|
||||
_context.ack_handler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt-signal receiver
|
||||
*/
|
||||
unsigned receiver_id() const { return Signal_receiver::Object::id(); }
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt-signal context
|
||||
*/
|
||||
unsigned context_id() const { return Signal_context::Object::id(); }
|
||||
~User_irq()
|
||||
{
|
||||
_context.ack_handler(nullptr);
|
||||
disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
*/
|
||||
void occurred()
|
||||
{
|
||||
Signal_context::submit(1);
|
||||
_context.submit(1);
|
||||
disable();
|
||||
}
|
||||
|
||||
|
@ -22,64 +22,53 @@
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* On other platforms, every IRQ session component creates its entrypoint.
|
||||
* However, on base-hw this isn't necessary as users can wait for their
|
||||
* interrupts directly. Instead of replacing cores generic irq_root.h and
|
||||
* main.cc with base-hw specific versions, we simply use a local singleton.h
|
||||
*/
|
||||
static Rpc_entrypoint * irq_session_ep()
|
||||
|
||||
unsigned Irq_session_component::_find_irq_number(const char * const args)
|
||||
{
|
||||
enum { STACK_SIZE = 2048 };
|
||||
static Rpc_entrypoint
|
||||
_ep(core_env()->cap_session(), STACK_SIZE, "irq_session_ep");
|
||||
return &_ep;
|
||||
return Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
}
|
||||
|
||||
void Irq_session_component::wait_for_irq() { PERR("not implemented"); }
|
||||
|
||||
Irq_signal Irq_session_component::signal() { return _signal; }
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
Kernel::ack_signal(_sig_cap.dst());
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::sigh(Signal_context_capability cap)
|
||||
{
|
||||
if (_sig_cap.valid()) {
|
||||
PWRN("signal handler already registered for IRQ %u", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
_sig_cap = cap;
|
||||
|
||||
if (Kernel::new_irq((addr_t)&_kernel_object, _irq_number, _sig_cap.dst()))
|
||||
PWRN("invalid signal handler for IRQ %u", _irq_number);
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
irq_session_ep()->dissolve(this);
|
||||
User_irq * kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||
_irq_alloc->free((void *)(addr_t)static_cast<Kernel::Irq*>(kirq)->id());
|
||||
Kernel::delete_irq(kirq);
|
||||
if (_sig_cap.valid())
|
||||
Kernel::delete_irq(kirq);
|
||||
}
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session * const cap_session,
|
||||
Range_allocator * const irq_alloc,
|
||||
const char * const args)
|
||||
: _irq_alloc(irq_alloc)
|
||||
|
||||
Irq_session_component::Irq_session_component(Range_allocator * const irq_alloc,
|
||||
const char * const args)
|
||||
:
|
||||
_irq_number(Platform::irq(_find_irq_number(args))),
|
||||
_irq_alloc(irq_alloc)
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
/* check arguments */
|
||||
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
||||
if (shared) {
|
||||
PERR("shared interrupts not supported");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
/* allocate interrupt */
|
||||
long irq_nr = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
bool error = irq_nr < 0 || !_irq_alloc;
|
||||
|
||||
/* enable platform specific code to apply mappings */
|
||||
long const plat_irq_nr = Platform::irq(irq_nr);
|
||||
|
||||
error |= _irq_alloc->alloc_addr(1, plat_irq_nr).is_error();
|
||||
if (error) {
|
||||
if (_irq_alloc->alloc_addr(1, _irq_number).is_error()) {
|
||||
PERR("unavailable interrupt requested");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
/* make interrupt accessible */
|
||||
new_irq((addr_t)&_kernel_object, plat_irq_nr);
|
||||
User_irq * kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||
_signal = { kirq->receiver_id(), kirq->context_id() };
|
||||
_cap = Irq_session_capability(irq_session_ep()->manage(this));
|
||||
}
|
||||
|
@ -582,13 +582,6 @@ void Thread::_call_new_signal_context()
|
||||
|
||||
void Thread::_call_await_signal()
|
||||
{
|
||||
/* check wether to acknowledge a context */
|
||||
unsigned const context_id = user_arg_2();
|
||||
if (context_id) {
|
||||
Signal_context * const c = Signal_context::pool()->object(context_id);
|
||||
if (c) { c->ack(); }
|
||||
else { PWRN("failed to acknowledge signal context"); }
|
||||
}
|
||||
/* lookup receiver */
|
||||
unsigned const receiver_id = user_arg_1();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(receiver_id);
|
||||
@ -688,8 +681,19 @@ void Thread::_call_delete_signal_receiver() {
|
||||
reinterpret_cast<Signal_receiver*>(user_arg_1())->~Signal_receiver(); }
|
||||
|
||||
|
||||
void Thread::_call_new_irq() {
|
||||
new ((void *)user_arg_1()) User_irq(user_arg_2()); }
|
||||
void Thread::_call_new_irq()
|
||||
{
|
||||
Signal_context * const c = Signal_context::pool()->object(user_arg_3());
|
||||
if (!c) {
|
||||
PWRN("%s -> %s: invalid signal context for interrupt",
|
||||
pd_label(), label());
|
||||
user_arg_0(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
new ((void *)user_arg_1()) User_irq(user_arg_2(), *c);
|
||||
user_arg_0(0);
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_delete_irq() {
|
||||
|
@ -49,7 +49,7 @@ extern Genode::addr_t _vt_host_context_ptr;
|
||||
|
||||
struct Kernel::Vm_irq : Kernel::Irq
|
||||
{
|
||||
Vm_irq(unsigned const irq) : Kernel::Irq(irq) {}
|
||||
Vm_irq(unsigned const irq) : Kernel::Irq(irq, *cpu_pool()->executing_cpu()) {}
|
||||
|
||||
/**
|
||||
* A VM interrupt gets injected into the VM scheduled on the current CPU
|
||||
@ -180,10 +180,6 @@ struct Kernel::Virtual_timer
|
||||
|
||||
void Kernel::prepare_hypervisor()
|
||||
{
|
||||
Cpu * cpu = cpu_pool()->executing_cpu();
|
||||
cpu->insert(&Virtual_timer::timer().irq);
|
||||
cpu->insert(&Virtual_pic::pic().irq);
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::hyp_exception_entry_at(&_vt_host_entry);
|
||||
|
||||
|
@ -20,6 +20,7 @@ SRC_CC += env/rm_session_mmap.cc env/debug.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/trace.cc thread/thread_env.cc thread/context_allocator.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/base/lock $(BASE_DIR)/src/base/lock
|
||||
INC_DIR += $(REP_DIR)/src/base/ipc
|
||||
|
@ -15,46 +15,38 @@
|
||||
#define _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_session_component : public List<Irq_session_component>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component() { }
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* Capability is always invalid under Linux.
|
||||
*/
|
||||
Session_capability cap() const { return Session_capability(); }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq() { }
|
||||
};
|
||||
class Irq_session_component;
|
||||
}
|
||||
|
||||
class Genode::Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component() { }
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void ack_irq() { }
|
||||
void sigh(Signal_context_capability) override { }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_ */
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* \brief IRQ session interface for NOVA
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <base/lock.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_proxy_component;
|
||||
|
||||
class Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Each IRQ session uses a dedicated server activation
|
||||
*/
|
||||
enum { STACK_SIZE = 2048 };
|
||||
Rpc_entrypoint _ep;
|
||||
Irq_session_capability _irq_cap;
|
||||
Irq_proxy_component *_proxy;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* If an initialization error occurs, returned capability is invalid.
|
||||
*/
|
||||
Irq_session_capability cap() const { return _irq_cap; }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq();
|
||||
Irq_signal signal();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
@ -170,43 +170,68 @@ class Genode::Irq_proxy_component : public Irq_proxy<Irq_thread>
|
||||
};
|
||||
|
||||
|
||||
typedef Irq_proxy<Irq_thread> Proxy;
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
/***************************
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
_proxy->wait_for_irq();
|
||||
/* interrupt ocurred and proxy woke us up */
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_ep(cap_session, STACK_SIZE, "irq")
|
||||
{
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
|
||||
/* check if IRQ thread was started before */
|
||||
_proxy = Proxy::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (irq_number == -1 || !_proxy) {
|
||||
PERR("Unavailable IRQ %lx requested", irq_number);
|
||||
if (irq_number == -1) {
|
||||
PERR("invalid IRQ number requested");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
_proxy->add_sharer();
|
||||
/* check if IRQ thread was started before */
|
||||
typedef Irq_proxy<Irq_thread> Proxy;
|
||||
_proxy = Proxy::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
/* initialize capability */
|
||||
_irq_cap = _ep.manage(this);
|
||||
_irq_number = irq_number;
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component() { }
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (_proxy) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
@ -12,10 +12,12 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <irq_proxy.h>
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <util/arg_string.h>
|
||||
|
||||
/* core includes */
|
||||
#include <irq_root.h>
|
||||
#include <irq_session_component.h>
|
||||
|
||||
/* OKL4 includes */
|
||||
namespace Okl4 { extern "C" {
|
||||
@ -30,12 +32,6 @@ using namespace Okl4;
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Proxy class with generic thread
|
||||
*/
|
||||
typedef Irq_proxy<Thread<0x1000> > Proxy;
|
||||
|
||||
|
||||
/* XXX move this functionality to a central place instead of duplicating it */
|
||||
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
|
||||
{
|
||||
@ -44,11 +40,15 @@ static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
|
||||
return myself;
|
||||
}
|
||||
|
||||
namespace Genode {
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
class Irq_proxy_component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform-specific proxy code
|
||||
*/
|
||||
class Irq_proxy_component : public Proxy
|
||||
class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
{
|
||||
protected:
|
||||
|
||||
@ -80,13 +80,14 @@ class Irq_proxy_component : public Proxy
|
||||
|
||||
/* prepare ourself to receive asynchronous IRQ notifications */
|
||||
L4_Set_NotifyMask(1 << IRQ_NOTIFY_BIT);
|
||||
L4_Accept(L4_NotifyMsgAcceptor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void _wait_for_irq()
|
||||
{
|
||||
L4_Accept(L4_NotifyMsgAcceptor);
|
||||
|
||||
/* wait for asynchronous interrupt notification */
|
||||
L4_ThreadId_t partner = L4_nilthread;
|
||||
L4_ReplyWait(partner, &partner);
|
||||
@ -111,35 +112,23 @@ class Irq_proxy_component : public Proxy
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
/* block at interrupt proxy */
|
||||
Proxy *p = Proxy::get_irq_proxy<Irq_proxy_component>(_irq_number);
|
||||
if (!p) {
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
p->wait_for_irq();
|
||||
|
||||
/* interrupt ocurred and proxy woke us up */
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_irq_alloc(irq_alloc),
|
||||
_ep(cap_session, STACK_SIZE, "irqctrl"),
|
||||
_irq_attached(false),
|
||||
_control_client(Capability<Irq_session_component::Irq_control>())
|
||||
_irq_alloc(irq_alloc)
|
||||
{
|
||||
/*
|
||||
* XXX Removed irq_shared argument as this is the default now. If we need
|
||||
@ -154,30 +143,39 @@ Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
}
|
||||
|
||||
/* check if IRQ thread was started before */
|
||||
Proxy *irq_proxy = Proxy::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!irq_proxy) {
|
||||
_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
irq_proxy->add_sharer();
|
||||
_irq_number = irq_number;
|
||||
|
||||
/* initialize capability */
|
||||
_irq_cap = _ep.manage(this);
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
PERR("not yet implemented");
|
||||
/* TODO del_sharer() resp. put_sharer() */
|
||||
if (!_proxy) return;
|
||||
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <util/arg_string.h>
|
||||
|
||||
/* core includes */
|
||||
#include <irq_proxy.h>
|
||||
#include <irq_root.h>
|
||||
#include <util.h>
|
||||
|
||||
@ -39,102 +40,161 @@ static inline L4_ThreadId_t irqno_to_threadid(unsigned int irqno)
|
||||
}
|
||||
|
||||
|
||||
bool Irq_session_component::Irq_control_component::associate_to_irq(unsigned)
|
||||
{
|
||||
/*
|
||||
* We defer the association with the IRQ to the first call of the
|
||||
* 'wait_for_irq' function.
|
||||
*/
|
||||
return true;
|
||||
namespace Genode {
|
||||
typedef Irq_proxy<Thread<1024 * sizeof(addr_t)> > Irq_proxy_base;
|
||||
class Irq_proxy_component;
|
||||
}
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq()
|
||||
/**
|
||||
* Platform-specific proxy code
|
||||
*/
|
||||
|
||||
class Genode::Irq_proxy_component : public Irq_proxy_base
|
||||
{
|
||||
L4_ThreadId_t irq_thread = irqno_to_threadid(_irq_number);
|
||||
private:
|
||||
|
||||
/* attach to IRQ when called for the first time */
|
||||
L4_MsgTag_t res;
|
||||
if (!_irq_attached) {
|
||||
/*
|
||||
* On Pistachio, an IRQ is unmasked right after attaching.
|
||||
* Hence, the kernel may send an IRQ IPC when the IRQ hander is
|
||||
* not explicitly waiting for an IRQ but when it is waiting for
|
||||
* a client's 'wait_for_irq' RPC call. To avoid this conflict, we
|
||||
* lazily associate to the IRQ when calling the 'wait_for_irq'
|
||||
* function for the first time. We use the '_irq_attached' flag
|
||||
* for detecting the first call.
|
||||
*/
|
||||
bool _irq_attached; /* true if IRQ is already attached */
|
||||
|
||||
if (L4_AssociateInterrupt(irq_thread, L4_Myself()) != true) {
|
||||
PERR("L4_AssociateInterrupt failed");
|
||||
return;
|
||||
protected:
|
||||
|
||||
bool _associate() { return true; }
|
||||
|
||||
void _wait_for_irq()
|
||||
{
|
||||
L4_ThreadId_t irq_thread = irqno_to_threadid(_irq_number);
|
||||
|
||||
/* attach to IRQ when called for the first time */
|
||||
L4_MsgTag_t res;
|
||||
if (!_irq_attached) {
|
||||
|
||||
if (L4_AssociateInterrupt(irq_thread, L4_Myself()) != true) {
|
||||
PERR("L4_AssociateInterrupt failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Right after associating with an interrupt, the interrupt is
|
||||
* unmasked. Hence, we do not need to send an unmask message
|
||||
* to the IRQ thread but just wait for the IRQ.
|
||||
*/
|
||||
L4_Set_MsgTag(L4_Niltag);
|
||||
res = L4_Receive(irq_thread);
|
||||
|
||||
/*
|
||||
* Now, the IRQ is masked. To receive the next IRQ we have to send
|
||||
* an unmask message to the IRQ thread first.
|
||||
*/
|
||||
_irq_attached = true;
|
||||
|
||||
/* receive subsequent interrupt */
|
||||
} else {
|
||||
|
||||
/* send unmask message and wait for new IRQ */
|
||||
L4_Set_MsgTag(L4_Niltag);
|
||||
res = L4_Call(irq_thread);
|
||||
}
|
||||
|
||||
if (L4_IpcFailed(res)) {
|
||||
PERR("ipc error while waiting for interrupt.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Right after associating with an interrupt, the interrupt is
|
||||
* unmasked. Hence, we do not need to send an unmask message
|
||||
* to the IRQ thread but just wait for the IRQ.
|
||||
*/
|
||||
L4_Set_MsgTag(L4_Niltag);
|
||||
res = L4_Receive(irq_thread);
|
||||
void _ack_irq() { }
|
||||
|
||||
/*
|
||||
* Now, the IRQ is masked. To receive the next IRQ we have to send
|
||||
* an unmask message to the IRQ thread first.
|
||||
*/
|
||||
_irq_attached = true;
|
||||
public:
|
||||
|
||||
/* receive subsequent interrupt */
|
||||
} else {
|
||||
Irq_proxy_component(long irq_number)
|
||||
:
|
||||
Irq_proxy(irq_number),
|
||||
_irq_attached(false)
|
||||
{
|
||||
_start();
|
||||
}
|
||||
|
||||
/* send unmask message and wait for new IRQ */
|
||||
L4_Set_MsgTag(L4_Niltag);
|
||||
res = L4_Call(irq_thread);
|
||||
}
|
||||
~Irq_proxy_component()
|
||||
{
|
||||
L4_ThreadId_t const thread_id = irqno_to_threadid(_irq_number);
|
||||
L4_Word_t const res = L4_DeassociateInterrupt(thread_id);
|
||||
|
||||
if (L4_IpcFailed(res)) {
|
||||
PERR("ipc error while waiting for interrupt.");
|
||||
if (res != 1)
|
||||
PERR("L4_DeassociateInterrupt failed");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***************************
|
||||
** IRQ session component **
|
||||
***************************/
|
||||
|
||||
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
if (!_proxy) {
|
||||
PERR("Expected to find IRQ proxy for IRQ %02x", _irq_number);
|
||||
return;
|
||||
}
|
||||
|
||||
_proxy->ack_irq();
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Irq_session_component::Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args)
|
||||
:
|
||||
_irq_alloc(irq_alloc),
|
||||
_ep(cap_session, STACK_SIZE, "irqctrl"),
|
||||
_irq_attached(false),
|
||||
_control_client(Capability<Irq_session_component::Irq_control>())
|
||||
_irq_alloc(irq_alloc)
|
||||
{
|
||||
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
||||
if (shared) {
|
||||
PWRN("IRQ sharing not supported");
|
||||
|
||||
/* FIXME error condition -> exception */
|
||||
return;
|
||||
}
|
||||
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (irq_number == -1 || !irq_alloc ||
|
||||
irq_alloc->alloc_addr(1, irq_number).is_error()) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
if (irq_number == -1) {
|
||||
PERR("invalid IRQ number requested");
|
||||
|
||||
/* FIXME error condition -> exception */
|
||||
return;
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
_irq_number = irq_number;
|
||||
|
||||
/* initialize capability */
|
||||
_irq_cap = _ep.manage(this);
|
||||
/* check if IRQ thread was started before */
|
||||
_proxy = Irq_proxy_component::get_irq_proxy<Irq_proxy_component>(irq_number, irq_alloc);
|
||||
if (!_proxy) {
|
||||
PERR("unavailable IRQ %lx requested", irq_number);
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
_irq_number = irq_number;
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
L4_Word_t res = L4_DeassociateInterrupt(irqno_to_threadid(_irq_number));
|
||||
if (!_proxy) return;
|
||||
|
||||
if (res != 1) {
|
||||
PERR("L4_DeassociateInterrupt failed");
|
||||
}
|
||||
if (_irq_sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
}
|
||||
|
||||
|
||||
Irq_signal Irq_session_component::signal()
|
||||
void Irq_session_component::sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
PDBG("not implemented;");
|
||||
return Irq_signal();
|
||||
if (!_proxy) {
|
||||
PERR("signal handler got not registered - irq thread unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::Signal_context_capability old = _irq_sigh;
|
||||
|
||||
if (old.valid() && !sigh.valid())
|
||||
_proxy->remove_sharer(&_irq_sigh);
|
||||
|
||||
_irq_sigh = sigh;
|
||||
|
||||
if (!old.valid() && sigh.valid())
|
||||
_proxy->add_sharer(&_irq_sigh);
|
||||
}
|
||||
|
@ -26,11 +26,6 @@ namespace Genode { struct Irq_session_client; }
|
||||
*/
|
||||
struct Genode::Irq_session_client : Rpc_client<Irq_session>
|
||||
{
|
||||
/*
|
||||
* FIXME: This is used only client-internal and could thus be protected.
|
||||
*/
|
||||
Irq_signal const irq_signal;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -38,8 +33,7 @@ struct Genode::Irq_session_client : Rpc_client<Irq_session>
|
||||
*/
|
||||
explicit Irq_session_client(Irq_session_capability const & session)
|
||||
:
|
||||
Rpc_client<Irq_session>(session),
|
||||
irq_signal(signal())
|
||||
Rpc_client<Irq_session>(session)
|
||||
{ }
|
||||
|
||||
|
||||
@ -47,9 +41,9 @@ struct Genode::Irq_session_client : Rpc_client<Irq_session>
|
||||
** Irq_session **
|
||||
*****************/
|
||||
|
||||
Irq_signal signal() override { return call<Rpc_signal>(); }
|
||||
void ack_irq() override;
|
||||
|
||||
void wait_for_irq() override;
|
||||
void sigh(Signal_context_capability sigh) override { call<Rpc_sigh>(sigh); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__IRQ_SESSION__CLIENT_H_ */
|
||||
|
@ -21,22 +21,47 @@ namespace Genode { struct Irq_connection; }
|
||||
|
||||
struct Genode::Irq_connection : Connection<Irq_session>, Irq_session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq physical interrupt number
|
||||
* \param trigger interrupt trigger (e.g., level/edge)
|
||||
* \param polarity interrupt trigger polarity (e.g., low/high)
|
||||
*/
|
||||
Irq_connection(unsigned irq,
|
||||
Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
|
||||
Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED)
|
||||
:
|
||||
Connection<Irq_session>(
|
||||
session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u",
|
||||
irq, trigger, polarity)),
|
||||
Irq_session_client(cap())
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
||||
Genode::Signal_receiver _sig_rec;
|
||||
Genode::Signal_context _sigh_ctx;
|
||||
Genode::Signal_context_capability _sigh_cap;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq physical interrupt number
|
||||
* \param trigger interrupt trigger (e.g., level/edge)
|
||||
* \param polarity interrupt trigger polarity (e.g., low/high)
|
||||
*/
|
||||
Irq_connection(unsigned irq,
|
||||
Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED,
|
||||
Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED)
|
||||
:
|
||||
Connection<Irq_session>(
|
||||
session("ram_quota=4K, irq_number=%u, irq_trigger=%u, irq_polarity=%u",
|
||||
irq, trigger, polarity)),
|
||||
Irq_session_client(cap()),
|
||||
_sigh_cap(_sig_rec.manage(&_sigh_ctx))
|
||||
{
|
||||
/* register default signal handler */
|
||||
Irq_session_client::sigh(_sigh_cap);
|
||||
}
|
||||
|
||||
~Irq_connection()
|
||||
{
|
||||
Irq_session_client::sigh(Genode::Signal_context_capability());
|
||||
_sig_rec.dissolve(&_sigh_ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to acknowledge last IRQ and to block calling
|
||||
* thread until next IRQ fires.
|
||||
*/
|
||||
void wait_for_irq();
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__IRQ_SESSION__CONNECTION_H_ */
|
||||
|
@ -6,8 +6,7 @@
|
||||
*
|
||||
* An open IRQ session represents a valid IRQ attachment/association.
|
||||
* Initially, the interrupt is masked and will only occur if enabled. This is
|
||||
* done by calling wait_for_irq(). When the interrupt is delivered to the
|
||||
* client, it was acknowledged and masked at the interrupt controller before.
|
||||
* done by calling ack_irq().
|
||||
*
|
||||
* Disassociation from an IRQ is done by closing the session.
|
||||
*/
|
||||
@ -22,25 +21,15 @@
|
||||
#ifndef _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_
|
||||
#define _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_
|
||||
|
||||
#include <base/signal.h>
|
||||
#include <base/capability.h>
|
||||
#include <session/session.h>
|
||||
|
||||
namespace Genode {
|
||||
struct Irq_session;
|
||||
struct Irq_signal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Information that enables a user to await and ack an IRQ directly
|
||||
*/
|
||||
struct Genode::Irq_signal
|
||||
{
|
||||
unsigned receiver_id;
|
||||
unsigned context_id;
|
||||
};
|
||||
|
||||
|
||||
struct Genode::Irq_session : Session
|
||||
{
|
||||
/**
|
||||
@ -59,17 +48,14 @@ struct Genode::Irq_session : Session
|
||||
virtual ~Irq_session() { }
|
||||
|
||||
/**
|
||||
* Await the next occurence of the interrupt of this session
|
||||
* Acknowledge handling of last interrupt - re-enables interrupt reception
|
||||
*/
|
||||
virtual void wait_for_irq() = 0;
|
||||
virtual void ack_irq() = 0;
|
||||
|
||||
/**
|
||||
* Get information for direct interrupt handling
|
||||
*
|
||||
* FIXME: This is used only client-internal and could thus be protected.
|
||||
* Register irq signal handler
|
||||
*/
|
||||
virtual Irq_signal signal() = 0;
|
||||
|
||||
virtual void sigh(Genode::Signal_context_capability sigh) = 0;
|
||||
|
||||
/*************
|
||||
** Session **
|
||||
@ -82,9 +68,9 @@ struct Genode::Irq_session : Session
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC(Rpc_wait_for_irq, void, wait_for_irq);
|
||||
GENODE_RPC(Rpc_signal, Irq_signal, signal);
|
||||
GENODE_RPC_INTERFACE(Rpc_wait_for_irq, Rpc_signal);
|
||||
GENODE_RPC(Rpc_ack_irq, void, ack_irq);
|
||||
GENODE_RPC(Rpc_sigh, void, sigh, Genode::Signal_context_capability);
|
||||
GENODE_RPC_INTERFACE(Rpc_ack_irq, Rpc_sigh);
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__IRQ_SESSION__IRQ_SESSION_H_ */
|
||||
|
@ -11,9 +11,18 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <irq_session/client.h>
|
||||
#include <irq_session/connection.h>
|
||||
|
||||
void Genode::Irq_session_client::wait_for_irq()
|
||||
void Genode::Irq_session_client::ack_irq()
|
||||
{
|
||||
call<Rpc_wait_for_irq>();
|
||||
call<Rpc_ack_irq>();
|
||||
}
|
||||
|
||||
|
||||
void Genode::Irq_connection::wait_for_irq()
|
||||
{
|
||||
ack_irq();
|
||||
Signal s = _sig_rec.wait_for_signal();
|
||||
if (s.num() != 1)
|
||||
PWRN("unexpected number of IRqs received %u", s.num());
|
||||
}
|
||||
|
@ -9,36 +9,34 @@
|
||||
#define _CORE__INCLUDE__IRQ_PROXY_H_
|
||||
|
||||
#include <base/env.h>
|
||||
#include <util.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
|
||||
namespace Genode {
|
||||
class Irq_blocker;
|
||||
class Irq_sigh;
|
||||
template <typename THREAD> class Irq_proxy;
|
||||
class Irq_thread_dummy;
|
||||
class Irq_proxy_single;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Irq_blocker : public Genode::List<Genode::Irq_blocker>::Element
|
||||
class Genode::Irq_sigh : public Genode::Signal_context_capability,
|
||||
public Genode::List<Genode::Irq_sigh>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _wait_lock;
|
||||
|
||||
public:
|
||||
|
||||
Irq_blocker() : _wait_lock(Lock::LOCKED) { }
|
||||
inline Irq_sigh * operator= (const Signal_context_capability &cap)
|
||||
{
|
||||
Signal_context_capability::operator=(cap);
|
||||
return this;
|
||||
}
|
||||
|
||||
void block() { _wait_lock.lock(); }
|
||||
void unblock() { _wait_lock.unlock(); }
|
||||
Irq_sigh() { }
|
||||
|
||||
void notify() { Genode::Signal_transmitter(*this).submit(1); }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Proxy thread that associates to the interrupt and unblocks waiting irqctrl
|
||||
* threads. Maybe, we should utilize our signals for interrupt delivery...
|
||||
* threads.
|
||||
*
|
||||
* XXX resources are not accounted as the interrupt is shared
|
||||
*/
|
||||
@ -56,8 +54,8 @@ class Genode::Irq_proxy : public THREAD,
|
||||
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_blocker> _blocker_list;
|
||||
int _num_blockers; /* number of currently blocked clients */
|
||||
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 */
|
||||
@ -102,20 +100,8 @@ class Genode::Irq_proxy : public THREAD,
|
||||
while (1) {
|
||||
_wait_for_irq();
|
||||
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
/* inform blocked clients */
|
||||
Irq_blocker *b;
|
||||
while ((b = _blocker_list.first())) {
|
||||
_blocker_list.remove(b);
|
||||
b->unblock();
|
||||
}
|
||||
|
||||
/* reset blocker state */
|
||||
_num_blockers = 0;
|
||||
_woken_up = false;
|
||||
}
|
||||
/* notify all */
|
||||
notify_about_irq(1);
|
||||
|
||||
/*
|
||||
* We must wait for all clients to ack their interrupt,
|
||||
@ -146,7 +132,8 @@ class Genode::Irq_proxy : public THREAD,
|
||||
:
|
||||
THREAD(_construct_name(irq_number)),
|
||||
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
|
||||
_mutex(Lock::UNLOCKED), _num_sharers(0), _num_blockers(0), _woken_up(false)
|
||||
_mutex(Lock::UNLOCKED), _num_sharers(0), _num_acknowledgers(0), _woken_up(false)
|
||||
|
||||
{ }
|
||||
|
||||
/**
|
||||
@ -163,43 +150,68 @@ class Genode::Irq_proxy : public THREAD,
|
||||
}
|
||||
|
||||
/**
|
||||
* Block until interrupt occured
|
||||
* Acknowledgements of clients
|
||||
*/
|
||||
virtual void wait_for_irq()
|
||||
virtual bool ack_irq()
|
||||
{
|
||||
Irq_blocker blocker;
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
_blocker_list.insert(&blocker);
|
||||
_num_blockers++;
|
||||
_num_acknowledgers++;
|
||||
|
||||
/*
|
||||
* The proxy thread is woken up if no client woke it up before
|
||||
* and this client is the last aspired blocker.
|
||||
*/
|
||||
if (!_woken_up && _num_blockers == _num_sharers) {
|
||||
_sleep.up();
|
||||
_woken_up = true;
|
||||
}
|
||||
/*
|
||||
* The proxy thread has to be woken up if no client woke it up
|
||||
* before and this client is the last aspired acknowledger.
|
||||
*/
|
||||
if (!_woken_up && _num_acknowledgers == _num_sharers) {
|
||||
_sleep.up();
|
||||
_woken_up = true;
|
||||
}
|
||||
blocker.block();
|
||||
|
||||
return _woken_up;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all clients about irq
|
||||
*/
|
||||
void notify_about_irq(unsigned)
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
/* reset acknowledger state */
|
||||
_num_acknowledgers = 0;
|
||||
_woken_up = false;
|
||||
|
||||
/* inform blocked clients */
|
||||
for (Irq_sigh * s = _sigh_list.first(); s ; s = s->next())
|
||||
s->notify();
|
||||
}
|
||||
|
||||
long irq_number() const { return _irq_number; }
|
||||
|
||||
virtual bool add_sharer()
|
||||
virtual bool add_sharer(Irq_sigh *s)
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
++_num_sharers;
|
||||
_sigh_list.insert(s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void remove_sharer()
|
||||
virtual void remove_sharer(Irq_sigh *s)
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
_sigh_list.remove(s);
|
||||
--_num_sharers;
|
||||
|
||||
if (_woken_up)
|
||||
return;
|
||||
|
||||
if (_num_acknowledgers == _num_sharers) {
|
||||
_sleep.up();
|
||||
_woken_up = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PROXY>
|
||||
@ -225,51 +237,4 @@ class Genode::Irq_proxy : public THREAD,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Dummy thread
|
||||
*/
|
||||
class Genode::Irq_thread_dummy
|
||||
{
|
||||
public:
|
||||
|
||||
Irq_thread_dummy(char const *name) { }
|
||||
void start() { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Non-threaded proxy that disables shared interrupts
|
||||
*/
|
||||
class Genode::Irq_proxy_single : public Genode::Irq_proxy<Genode::Irq_thread_dummy>
|
||||
{
|
||||
protected:
|
||||
|
||||
void _start()
|
||||
{
|
||||
_associate();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Irq_proxy_single(long irq_number) : Irq_proxy(irq_number) { }
|
||||
|
||||
bool add_sharer()
|
||||
{
|
||||
Lock::Guard lock_guard(_mutex);
|
||||
|
||||
if (_num_sharers)
|
||||
return false;
|
||||
|
||||
_num_sharers = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void wait_for_irq()
|
||||
{
|
||||
_wait_for_irq();
|
||||
_ack_irq();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_PROXY_H_ */
|
||||
|
@ -1,13 +1,12 @@
|
||||
/*
|
||||
* \brief IRQ root interface
|
||||
* \author Christian Helmuth
|
||||
* \author Alexander Boettcher
|
||||
* \date 2007-09-13
|
||||
*
|
||||
* FIXME locking
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2007-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
@ -16,98 +15,37 @@
|
||||
#ifndef _CORE__INCLUDE__IRQ_ROOT_H_
|
||||
#define _CORE__INCLUDE__IRQ_ROOT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <base/allocator.h>
|
||||
#include <root/root.h>
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
/* core includes */
|
||||
#include <root/component.h>
|
||||
#include <irq_session_component.h>
|
||||
|
||||
namespace Genode {
|
||||
namespace Genode { class Irq_root; }
|
||||
|
||||
class Irq_root : public Rpc_object<Typed_root<Irq_session> >
|
||||
{
|
||||
class Genode::Irq_root : public Root_component<Irq_session_component>
|
||||
{
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
Cap_session *_cap_session;
|
||||
Range_allocator *_irq_alloc; /* platform irq allocator */
|
||||
Allocator *_md_alloc; /* meta-data allocator */
|
||||
List<Irq_session_component> _sessions; /* started irq sessions */
|
||||
Range_allocator *_irq_alloc; /* platform irq allocator */
|
||||
|
||||
public:
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability allocator
|
||||
* \param irq_alloc IRQ range that can be assigned to clients
|
||||
* \param md_alloc meta-data allocator to be used by root component
|
||||
*/
|
||||
Irq_root(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
Allocator *md_alloc)
|
||||
: _cap_session(cap_session), _irq_alloc(irq_alloc), _md_alloc(md_alloc) { }
|
||||
Irq_session_component *_create_session(const char *args) {
|
||||
return new (md_alloc()) Irq_session_component(_irq_alloc, args); }
|
||||
|
||||
public:
|
||||
|
||||
/********************
|
||||
** Root interface **
|
||||
********************/
|
||||
|
||||
Session_capability session(Session_args const &args, Affinity const &affinity)
|
||||
{
|
||||
if (!args.is_valid_string()) throw Invalid_args();
|
||||
|
||||
/*
|
||||
* We need to decrease 'ram_quota' by
|
||||
* the size of the session object.
|
||||
*/
|
||||
size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0);
|
||||
long remaining_ram_quota = ram_quota - sizeof(Irq_session_component) -
|
||||
_md_alloc->overhead(sizeof(Irq_session_component));
|
||||
if (remaining_ram_quota < 0) {
|
||||
PERR("Insufficient ram quota, provided=%zu, required=%zu",
|
||||
ram_quota, sizeof(Irq_session_component) +
|
||||
_md_alloc->overhead(sizeof(Irq_session_component)));
|
||||
return Session_capability();
|
||||
}
|
||||
|
||||
Irq_session_component *s;
|
||||
try {
|
||||
s = new (_md_alloc) Irq_session_component(_cap_session, _irq_alloc, args.string());
|
||||
} catch (Allocator::Out_of_memory) { return Session_capability(); }
|
||||
|
||||
if (!s->cap().valid())
|
||||
return Session_capability();
|
||||
|
||||
_sessions.insert(s);
|
||||
|
||||
return s->cap();
|
||||
}
|
||||
|
||||
void upgrade(Session_capability, Upgrade_args const &)
|
||||
{
|
||||
/* there is no need to upgrade an IRQ session */
|
||||
}
|
||||
|
||||
void close(Session_capability session)
|
||||
{
|
||||
Irq_session_component *s = _sessions.first();
|
||||
|
||||
for (; s; s = s->next()) {
|
||||
if (s->cap().local_name() == session.local_name())
|
||||
break;
|
||||
}
|
||||
if (!s) return;
|
||||
|
||||
_sessions.remove(s);
|
||||
|
||||
/* XXX Currently we support only one client... */
|
||||
destroy(_md_alloc, s);
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session_ep entry point for managing irq session objects
|
||||
* \param irq_alloc IRQ range that can be assigned to clients
|
||||
* \param md_alloc meta-data allocator to be used by root component
|
||||
*/
|
||||
Irq_root(Rpc_entrypoint *session_ep, Range_allocator *irq_alloc,
|
||||
Allocator *md_alloc)
|
||||
:
|
||||
Root_component<Irq_session_component>(session_ep, md_alloc),
|
||||
_irq_alloc(irq_alloc) { }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_ROOT_H_ */
|
||||
|
@ -14,128 +14,51 @@
|
||||
#ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_
|
||||
|
||||
#include <base/lock.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <util/list.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
/* XXX Notes
|
||||
*
|
||||
* - each H/W IRQ is an irq thread
|
||||
* - each irq thread has an Rpc_entrypoint
|
||||
* -> irq thread is special Server_activation
|
||||
* -> IRQ session is Rpc_object
|
||||
*
|
||||
* - session("IRQ", "irq_num=<num>") -> Native_capability(irq_thread, cap)
|
||||
* - cap must be generated at CAP
|
||||
* - cap must be managed by irq_thread-local Rpc_entrypoint
|
||||
*
|
||||
* - irq thread states
|
||||
* 1. wait_for_client --[ client calls wait_for_irq ]--> 2.
|
||||
* 2. wait_for_irq --[ kernel signals irq ]--> 3.
|
||||
* 3. irq_occured --[ inform client about occurence ]--> 1.
|
||||
*
|
||||
* - irq thread roles
|
||||
* - Irq_server (Ipc_server) for client
|
||||
* - Fiasco_irq_client (Ipc_client) at kernel
|
||||
*/
|
||||
#include <irq_proxy.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
struct Irq_control
|
||||
{
|
||||
GENODE_RPC(Rpc_associate_to_irq, bool, associate_to_irq, unsigned);
|
||||
GENODE_RPC_INTERFACE(Rpc_associate_to_irq);
|
||||
};
|
||||
|
||||
struct Irq_control_client : Rpc_client<Irq_control>
|
||||
{
|
||||
Irq_control_client(Capability<Irq_control> cap)
|
||||
: Rpc_client<Irq_control>(cap) { }
|
||||
|
||||
bool associate_to_irq(unsigned irq_number) {
|
||||
return call<Rpc_associate_to_irq>(irq_number); }
|
||||
};
|
||||
|
||||
struct Irq_control_component : Rpc_object<Irq_control,
|
||||
Irq_control_component>
|
||||
{
|
||||
/**
|
||||
* Associate to IRQ at Fiasco
|
||||
*
|
||||
* This is executed by the IRQ server activation itself.
|
||||
*/
|
||||
bool associate_to_irq(unsigned irq_number);
|
||||
};
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator *_irq_alloc;
|
||||
|
||||
enum { STACK_SIZE = 2048 };
|
||||
Rpc_entrypoint _ep;
|
||||
|
||||
/*
|
||||
* On Pistachio, an IRQ is unmasked right after attaching.
|
||||
* Hence, the kernel may send an IRQ IPC when the IRQ hander is
|
||||
* not explicitly waiting for an IRQ but when it is waiting for
|
||||
* a client's 'wait_for_irq' RPC call. To avoid this conflict, we
|
||||
* lazily associate to the IRQ when calling the 'wait_for_irq'
|
||||
* function for the first time. We use the '_irq_attached' flag
|
||||
* for detecting the first call. On other kernels, this variable
|
||||
* may be unused.
|
||||
*/
|
||||
unsigned _irq_attached; /* true if IRQ is already attached */
|
||||
|
||||
|
||||
/********************************************
|
||||
** IRQ control server (internal use only) **
|
||||
********************************************/
|
||||
|
||||
Irq_control_component _control_component; /* ctrl component */
|
||||
Capability<Irq_control> _control_cap; /* capability for ctrl server */
|
||||
Irq_control_client _control_client; /* ctrl client */
|
||||
Capability<Irq_session> _irq_cap; /* capability for IRQ */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param cap_session capability session to use
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Cap_session *cap_session,
|
||||
Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/**
|
||||
* Return capability to this session
|
||||
*
|
||||
* If an initialization error occurs, returned _cap is invalid.
|
||||
*/
|
||||
Capability<Irq_session> cap() const { return _irq_cap; }
|
||||
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void wait_for_irq();
|
||||
Irq_signal signal();
|
||||
};
|
||||
class Irq_proxy_component;
|
||||
class Irq_session_component;
|
||||
}
|
||||
|
||||
class Genode::Irq_session_component : public Rpc_object<Irq_session>,
|
||||
public List<Irq_session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator *_irq_alloc;
|
||||
Irq_proxy_component *_proxy;
|
||||
|
||||
Irq_sigh _irq_sigh;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_alloc platform-dependent IRQ allocator
|
||||
* \param args session construction arguments
|
||||
*/
|
||||
Irq_session_component(Range_allocator *irq_alloc,
|
||||
const char *args);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_session_component();
|
||||
|
||||
/***************************
|
||||
** Irq session interface **
|
||||
***************************/
|
||||
|
||||
void ack_irq();
|
||||
void sigh(Signal_context_capability) override;
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
||||
|
@ -220,8 +220,7 @@ int main()
|
||||
static Log_root log_root (e, &sliced_heap);
|
||||
static Io_mem_root io_mem_root (e, e, platform()->io_mem_alloc(),
|
||||
platform()->ram_alloc(), &sliced_heap);
|
||||
static Irq_root irq_root (core_env()->cap_session(),
|
||||
platform()->irq_alloc(), &sliced_heap);
|
||||
static Irq_root irq_root (e, platform()->irq_alloc(), &sliced_heap);
|
||||
static Trace::Root trace_root (e, &sliced_heap, trace_sources, trace_policies);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user