From faa25e1df6e44393fc0874162114762abc75acdd Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 17 Mar 2015 15:41:47 +0100 Subject: [PATCH] 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 --- .../src/core/include/irq_session_component.h | 72 ------- .../src/core/irq_session_component.cc | 120 ++++++++--- .../src/core/irq_session_component.cc | 186 ++++++++++------- repos/base-foc/src/core/arndale/target.mk | 1 - repos/base-foc/src/core/imx53/target.mk | 1 - .../core/include/arm/irq_proxy_component.h | 29 --- .../src/core/include/irq_session_component.h | 78 -------- .../core/include/x86/irq_proxy_component.h | 24 --- .../src/core/irq_session_component.cc | 185 +++++++++++------ repos/base-foc/src/core/panda/target.mk | 1 - repos/base-foc/src/core/pbxa9/target.mk | 1 - repos/base-foc/src/core/vea9x4/target.mk | 1 - repos/base-foc/src/core/x86/target.mk | 2 - repos/base-hw/include/kernel/interface.h | 7 +- repos/base-hw/src/base/irq/platform.cc | 23 --- repos/base-hw/src/base/signal/signal.cc | 2 +- .../src/core/include/irq_session_component.h | 94 ++++----- .../src/core/include/kernel/core_interface.h | 10 +- repos/base-hw/src/core/include/kernel/irq.h | 52 ++--- .../base-hw/src/core/irq_session_component.cc | 73 +++---- repos/base-hw/src/core/kernel/thread.cc | 22 +- .../spec/arm_v7/virtualization/kernel/vm.cc | 6 +- repos/base-linux/lib/mk/base-common.mk | 1 + .../src/core/include/irq_session_component.h | 64 +++--- .../src/core/include/irq_session_component.h | 75 ------- .../src/core/irq_session_component.cc | 69 +++++-- .../src/core/irq_session_component.cc | 76 ++++--- .../src/core/irq_session_component.cc | 188 ++++++++++++------ repos/base/include/irq_session/client.h | 12 +- repos/base/include/irq_session/connection.h | 57 ++++-- repos/base/include/irq_session/irq_session.h | 32 +-- repos/base/src/base/irq/platform.cc | 15 +- repos/base/src/core/include/irq_proxy.h | 157 ++++++--------- repos/base/src/core/include/irq_root.h | 112 +++-------- .../src/core/include/irq_session_component.h | 153 ++++---------- repos/base/src/core/main.cc | 3 +- 36 files changed, 872 insertions(+), 1132 deletions(-) delete mode 100644 repos/base-codezero/src/core/include/irq_session_component.h delete mode 100644 repos/base-foc/src/core/include/arm/irq_proxy_component.h delete mode 100644 repos/base-foc/src/core/include/irq_session_component.h delete mode 100644 repos/base-foc/src/core/include/x86/irq_proxy_component.h delete mode 100644 repos/base-hw/src/base/irq/platform.cc delete mode 100644 repos/base-nova/src/core/include/irq_session_component.h diff --git a/repos/base-codezero/src/core/include/irq_session_component.h b/repos/base-codezero/src/core/include/irq_session_component.h deleted file mode 100644 index 734de0531f..0000000000 --- a/repos/base-codezero/src/core/include/irq_session_component.h +++ /dev/null @@ -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 -#include - -#include - -namespace Genode { - - class Irq_session_component : public Rpc_object, - public List::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_ */ diff --git a/repos/base-codezero/src/core/irq_session_component.cc b/repos/base-codezero/src/core/irq_session_component.cc index 6a6d3556fd..08e40ad040 100644 --- a/repos/base-codezero/src/core/irq_session_component.cc +++ b/repos/base-codezero/src/core/irq_session_component.cc @@ -22,57 +22,123 @@ #include +namespace Genode { + typedef Irq_proxy > 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_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); } diff --git a/repos/base-fiasco/src/core/irq_session_component.cc b/repos/base-fiasco/src/core/irq_session_component.cc index e7b738a863..a2d649ca14 100644 --- a/repos/base-fiasco/src/core/irq_session_component.cc +++ b/repos/base-fiasco/src/core/irq_session_component.cc @@ -18,6 +18,7 @@ #include /* core includes */ +#include #include #include @@ -28,101 +29,150 @@ namespace Fiasco { #include } +namespace Genode { + typedef Irq_proxy > 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_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); } diff --git a/repos/base-foc/src/core/arndale/target.mk b/repos/base-foc/src/core/arndale/target.mk index 6a182a0b0e..4b79b46f82 100644 --- a/repos/base-foc/src/core/arndale/target.mk +++ b/repos/base-foc/src/core/arndale/target.mk @@ -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) diff --git a/repos/base-foc/src/core/imx53/target.mk b/repos/base-foc/src/core/imx53/target.mk index 77717ad4ab..f26500ed68 100644 --- a/repos/base-foc/src/core/imx53/target.mk +++ b/repos/base-foc/src/core/imx53/target.mk @@ -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 diff --git a/repos/base-foc/src/core/include/arm/irq_proxy_component.h b/repos/base-foc/src/core/include/arm/irq_proxy_component.h deleted file mode 100644 index ef7c896b91..0000000000 --- a/repos/base-foc/src/core/include/arm/irq_proxy_component.h +++ /dev/null @@ -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 - -namespace Genode { - -/** - * On ARM we disable shared interrupts - */ -typedef Irq_proxy_single Irq_proxy_base; - -} - -#endif /* _CORE__INCLUDE__ARM__IRQ_PROXY_COMPONENT_H_ */ - diff --git a/repos/base-foc/src/core/include/irq_session_component.h b/repos/base-foc/src/core/include/irq_session_component.h deleted file mode 100644 index b6f4bf5ed1..0000000000 --- a/repos/base-foc/src/core/include/irq_session_component.h +++ /dev/null @@ -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 -#include -#include -#include - -#include - -namespace Genode { - - class Irq_proxy_component; - - class Irq_session_component : public Rpc_object, - public List::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_ */ diff --git a/repos/base-foc/src/core/include/x86/irq_proxy_component.h b/repos/base-foc/src/core/include/x86/irq_proxy_component.h deleted file mode 100644 index c9625aaab9..0000000000 --- a/repos/base-foc/src/core/include/x86/irq_proxy_component.h +++ /dev/null @@ -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 - -namespace Genode { - typedef Irq_proxy > Irq_proxy_base; -} - -#endif /* _CORE__INCLUDE__X86__IRQ_PROXY_COMPONENT_H_ */ - diff --git a/repos/base-foc/src/core/irq_session_component.cc b/repos/base-foc/src/core/irq_session_component.cc index deb058b03d..2125f218e3 100644 --- a/repos/base-foc/src/core/irq_session_component.cc +++ b/repos/base-foc/src/core/irq_session_component.cc @@ -21,7 +21,6 @@ /* core includes */ #include -#include #include #include #include @@ -39,6 +38,7 @@ using namespace Genode; namespace Genode { class Interrupt_handler; class Irq_proxy_component; + typedef Irq_proxy > 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_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_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); } diff --git a/repos/base-foc/src/core/panda/target.mk b/repos/base-foc/src/core/panda/target.mk index 23cc6be317..c48250925c 100644 --- a/repos/base-foc/src/core/panda/target.mk +++ b/repos/base-foc/src/core/panda/target.mk @@ -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) diff --git a/repos/base-foc/src/core/pbxa9/target.mk b/repos/base-foc/src/core/pbxa9/target.mk index 2ec8396d95..a031b0dacf 100644 --- a/repos/base-foc/src/core/pbxa9/target.mk +++ b/repos/base-foc/src/core/pbxa9/target.mk @@ -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 diff --git a/repos/base-foc/src/core/vea9x4/target.mk b/repos/base-foc/src/core/vea9x4/target.mk index 06e95dbf05..6292d97a80 100644 --- a/repos/base-foc/src/core/vea9x4/target.mk +++ b/repos/base-foc/src/core/vea9x4/target.mk @@ -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 diff --git a/repos/base-foc/src/core/x86/target.mk b/repos/base-foc/src/core/x86/target.mk index d36e32095c..f04ab9298c 100644 --- a/repos/base-foc/src/core/x86/target.mk +++ b/repos/base-foc/src/core/x86/target.mk @@ -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 diff --git a/repos/base-hw/include/kernel/interface.h b/repos/base-hw/include/kernel/interface.h index be951cbcc7..79c6b6ab29 100644 --- a/repos/base-hw/include/kernel/interface.h +++ b/repos/base-hw/include/kernel/interface.h @@ -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); } diff --git a/repos/base-hw/src/base/irq/platform.cc b/repos/base-hw/src/base/irq/platform.cc deleted file mode 100644 index 181ff2f7e7..0000000000 --- a/repos/base-hw/src/base/irq/platform.cc +++ /dev/null @@ -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 - -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"); - } -} diff --git a/repos/base-hw/src/base/signal/signal.cc b/repos/base-hw/src/base/signal/signal.cc index 0653b421a3..c296103cab 100644 --- a/repos/base-hw/src/base/signal/signal.cc +++ b/repos/base-hw/src/base/signal/signal.cc @@ -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()); } diff --git a/repos/base-hw/src/core/include/irq_session_component.h b/repos/base-hw/src/core/include/irq_session_component.h index ee1c1e91f8..ddd36bb2b8 100644 --- a/repos/base-hw/src/core/include/irq_session_component.h +++ b/repos/base-hw/src/core/include/irq_session_component.h @@ -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 #include #include -namespace Genode -{ - /** - * Backend for IRQ sessions to core - */ - class Irq_session_component - : - public Rpc_object, - public List::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, + public List::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_ */ diff --git a/repos/base-hw/src/core/include/kernel/core_interface.h b/repos/base-hw/src/core/include/kernel/core_interface.h index 99262b1665..9104918503 100644 --- a/repos/base-hw/src/core/include/kernel/core_interface.h +++ b/repos/base-hw/src/core/include/kernel/core_interface.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); } /** diff --git a/repos/base-hw/src/core/include/kernel/irq.h b/repos/base-hw/src/core/include/kernel/irq.h index 5273eeff3f..83ec010da8 100644 --- a/repos/base-hw/src/core/include/kernel/irq.h +++ b/repos/base-hw/src/core/include/kernel/irq.h @@ -47,8 +47,14 @@ namespace Genode class Kernel::Irq : public Object_pool::Item { + public: + + using Pool = Object_pool; + protected: + Pool &_pool; + /** * Get kernel name of the interrupt */ @@ -56,16 +62,6 @@ class Kernel::Irq : public Object_pool::Item public: - using Pool = Object_pool; - - /** - * 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::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::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(); } diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc index 561dca7dd8..891e7bea53 100644 --- a/repos/base-hw/src/core/irq_session_component.cc +++ b/repos/base-hw/src/core/irq_session_component.cc @@ -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(&_kernel_object); _irq_alloc->free((void *)(addr_t)static_cast(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(&_kernel_object); - _signal = { kirq->receiver_id(), kirq->context_id() }; - _cap = Irq_session_capability(irq_session_ep()->manage(this)); } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index cb0dcc3a19..e545fb3582 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -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(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() { diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index 90e03f0fde..1931e0a85c 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -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); diff --git a/repos/base-linux/lib/mk/base-common.mk b/repos/base-linux/lib/mk/base-common.mk index 4f275331df..14aa27d52d 100644 --- a/repos/base-linux/lib/mk/base-common.mk +++ b/repos/base-linux/lib/mk/base-common.mk @@ -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 diff --git a/repos/base-linux/src/core/include/irq_session_component.h b/repos/base-linux/src/core/include/irq_session_component.h index ff6bbbf881..f45e54ec94 100644 --- a/repos/base-linux/src/core/include/irq_session_component.h +++ b/repos/base-linux/src/core/include/irq_session_component.h @@ -15,46 +15,38 @@ #define _CORE__INCLUDE__LINUX__IRQ_SESSION_COMPONENT_H_ #include -#include #include #include namespace Genode { - - class Irq_session_component : public List::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, + public List::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_ */ diff --git a/repos/base-nova/src/core/include/irq_session_component.h b/repos/base-nova/src/core/include/irq_session_component.h deleted file mode 100644 index 89dd6d8335..0000000000 --- a/repos/base-nova/src/core/include/irq_session_component.h +++ /dev/null @@ -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 -#include -#include - -#include - -namespace Genode { - - class Irq_proxy_component; - - class Irq_session_component : public Rpc_object, - public List::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_ */ diff --git a/repos/base-nova/src/core/irq_session_component.cc b/repos/base-nova/src/core/irq_session_component.cc index 61aab161c3..9c1e89e416 100644 --- a/repos/base-nova/src/core/irq_session_component.cc +++ b/repos/base-nova/src/core/irq_session_component.cc @@ -170,43 +170,68 @@ class Genode::Irq_proxy_component : public Irq_proxy }; -typedef Irq_proxy 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_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 Proxy; + _proxy = Proxy::get_irq_proxy(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); } diff --git a/repos/base-okl4/src/core/irq_session_component.cc b/repos/base-okl4/src/core/irq_session_component.cc index 5806b6c41e..5ef06c72f5 100644 --- a/repos/base-okl4/src/core/irq_session_component.cc +++ b/repos/base-okl4/src/core/irq_session_component.cc @@ -12,10 +12,12 @@ * under the terms of the GNU General Public License version 2. */ -#include +/* Genode includes */ +#include +#include /* core includes */ -#include +#include /* OKL4 includes */ namespace Okl4 { extern "C" { @@ -30,12 +32,6 @@ using namespace Okl4; using namespace Genode; -/** - * Proxy class with generic thread - */ -typedef Irq_proxy > 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 > 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_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_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_number, irq_alloc); - if (!irq_proxy) { + _proxy = Irq_proxy_component::get_irq_proxy(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); } diff --git a/repos/base-pistachio/src/core/irq_session_component.cc b/repos/base-pistachio/src/core/irq_session_component.cc index df67eb1f39..c985d862ad 100644 --- a/repos/base-pistachio/src/core/irq_session_component.cc +++ b/repos/base-pistachio/src/core/irq_session_component.cc @@ -18,6 +18,7 @@ #include /* core includes */ +#include #include #include @@ -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 > 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_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_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); } diff --git a/repos/base/include/irq_session/client.h b/repos/base/include/irq_session/client.h index c19218aef0..d0cecef3bc 100644 --- a/repos/base/include/irq_session/client.h +++ b/repos/base/include/irq_session/client.h @@ -26,11 +26,6 @@ namespace Genode { struct Irq_session_client; } */ struct Genode::Irq_session_client : Rpc_client { - /* - * 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 */ explicit Irq_session_client(Irq_session_capability const & session) : - Rpc_client(session), - irq_signal(signal()) + Rpc_client(session) { } @@ -47,9 +41,9 @@ struct Genode::Irq_session_client : Rpc_client ** Irq_session ** *****************/ - Irq_signal signal() override { return call(); } + void ack_irq() override; - void wait_for_irq() override; + void sigh(Signal_context_capability sigh) override { call(sigh); } }; #endif /* _INCLUDE__IRQ_SESSION__CLIENT_H_ */ diff --git a/repos/base/include/irq_session/connection.h b/repos/base/include/irq_session/connection.h index 70012b2a30..cdf3ada81b 100644 --- a/repos/base/include/irq_session/connection.h +++ b/repos/base/include/irq_session/connection.h @@ -21,22 +21,47 @@ namespace Genode { struct Irq_connection; } struct Genode::Irq_connection : Connection, 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( - 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( + 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_ */ diff --git a/repos/base/include/irq_session/irq_session.h b/repos/base/include/irq_session/irq_session.h index 0fd7c1955f..a204700100 100644 --- a/repos/base/include/irq_session/irq_session.h +++ b/repos/base/include/irq_session/irq_session.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 #include #include 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_ */ diff --git a/repos/base/src/base/irq/platform.cc b/repos/base/src/base/irq/platform.cc index e2bc9cd7c8..73c837b018 100644 --- a/repos/base/src/base/irq/platform.cc +++ b/repos/base/src/base/irq/platform.cc @@ -11,9 +11,18 @@ * under the terms of the GNU General Public License version 2. */ -#include +#include -void Genode::Irq_session_client::wait_for_irq() +void Genode::Irq_session_client::ack_irq() { - call(); + call(); +} + + +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()); } diff --git a/repos/base/src/core/include/irq_proxy.h b/repos/base/src/core/include/irq_proxy.h index ff4a9cd4aa..463957948a 100644 --- a/repos/base/src/core/include/irq_proxy.h +++ b/repos/base/src/core/include/irq_proxy.h @@ -9,36 +9,34 @@ #define _CORE__INCLUDE__IRQ_PROXY_H_ #include -#include -#include namespace Genode { - class Irq_blocker; + class Irq_sigh; template class Irq_proxy; - class Irq_thread_dummy; - class Irq_proxy_single; } -class Genode::Irq_blocker : public Genode::List::Element +class Genode::Irq_sigh : public Genode::Signal_context_capability, + public Genode::List::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 _blocker_list; - int _num_blockers; /* number of currently blocked clients */ + List _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 @@ -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 -{ - 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_ */ diff --git a/repos/base/src/core/include/irq_root.h b/repos/base/src/core/include/irq_root.h index 794e9a8380..573aa77dd0 100644 --- a/repos/base/src/core/include/irq_root.h +++ b/repos/base/src/core/include/irq_root.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 -#include -#include -#include - -/* core includes */ +#include #include -namespace Genode { +namespace Genode { class Irq_root; } - class Irq_root : public Rpc_object > - { +class Genode::Irq_root : public Root_component +{ - private: + private: - Cap_session *_cap_session; - Range_allocator *_irq_alloc; /* platform irq allocator */ - Allocator *_md_alloc; /* meta-data allocator */ - List _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(session_ep, md_alloc), + _irq_alloc(irq_alloc) { } +}; #endif /* _CORE__INCLUDE__IRQ_ROOT_H_ */ diff --git a/repos/base/src/core/include/irq_session_component.h b/repos/base/src/core/include/irq_session_component.h index ea016af2a6..49249b635d 100644 --- a/repos/base/src/core/include/irq_session_component.h +++ b/repos/base/src/core/include/irq_session_component.h @@ -14,128 +14,51 @@ #ifndef _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ #define _CORE__INCLUDE__IRQ_SESSION_COMPONENT_H_ -#include #include #include #include #include #include - -/* 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=") -> 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 namespace Genode { - - class Irq_session_component : public Rpc_object, - public List::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_client(Capability cap) - : Rpc_client(cap) { } - - bool associate_to_irq(unsigned irq_number) { - return call(irq_number); } - }; - - struct Irq_control_component : Rpc_object - { - /** - * 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 _control_cap; /* capability for ctrl server */ - Irq_control_client _control_client; /* ctrl client */ - Capability _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 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, + public List::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_ */ diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc index cf300aca67..282817eda3 100644 --- a/repos/base/src/core/main.cc +++ b/repos/base/src/core/main.cc @@ -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); /*