From 93e2eecc524587bc46bf6a02313fcc660d4cb069 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 29 Jun 2016 23:06:22 +0200 Subject: [PATCH] sel4: add irq support Fixes #1718 Issue #2044 --- repos/base-sel4/src/core/include/irq_object.h | 48 ++++++++++ .../src/core/irq_session_component.cc | 89 +++++++++++++++++-- repos/base-sel4/src/core/stack_area.cc | 20 ++++- repos/base-sel4/src/core/thread_start.cc | 14 ++- 4 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 repos/base-sel4/src/core/include/irq_object.h diff --git a/repos/base-sel4/src/core/include/irq_object.h b/repos/base-sel4/src/core/include/irq_object.h new file mode 100644 index 000000000..9808b175b --- /dev/null +++ b/repos/base-sel4/src/core/include/irq_object.h @@ -0,0 +1,48 @@ +/* + * \brief Core-specific instance of the IRQ session interface + * \author Christian Helmuth + * \date 2007-09-13 + */ + +/* + * 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. + */ + +#ifndef _CORE__INCLUDE__IRQ_OBJECT_H_ +#define _CORE__INCLUDE__IRQ_OBJECT_H_ + +#include +#include + +namespace Genode { class Irq_object; } + +class Genode::Irq_object : public Thread_deprecated<4096> { + + private: + + Signal_context_capability _sig_cap; + Lock _sync_bootup; + unsigned _irq; + Cap_sel _kernel_irq_sel; + Cap_sel _kernel_notify_sel; + + void _wait_for_irq(); + + void entry() override; + + public: + + Irq_object(unsigned irq); + + void sigh(Signal_context_capability cap) { _sig_cap = cap; } + void notify() { Genode::Signal_transmitter(_sig_cap).submit(1); } + void ack_irq(); + + void start() override; + bool associate(Irq_session::Trigger const, Irq_session::Polarity const); +}; + +#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */ diff --git a/repos/base-sel4/src/core/irq_session_component.cc b/repos/base-sel4/src/core/irq_session_component.cc index dafbd337e..6971c7f0c 100644 --- a/repos/base-sel4/src/core/irq_session_component.cc +++ b/repos/base-sel4/src/core/irq_session_component.cc @@ -12,41 +12,104 @@ */ /* Genode includes */ -#include +#include /* core includes */ +#include #include +#include +#include using namespace Genode; -bool Irq_object::_associate() { return true; } +bool Irq_object::associate(Irq_session::Trigger const irq_trigger, + Irq_session::Polarity const irq_polarity) +{ + /* allocate notification object within core's CNode */ + Platform &platform = *platform_specific(); + Range_allocator &phys_alloc = *platform.ram_alloc(); + + create(phys_alloc, platform.core_cnode().sel(), + _kernel_notify_sel); + + enum { IRQ_EDGE = 0, IRQ_LEVEL = 1 }; + enum { IRQ_HIGH = 0, IRQ_LOW = 1 }; + + seL4_Word level = (_irq < 16) ? IRQ_EDGE : IRQ_LEVEL; + seL4_Word polarity = (_irq < 16) ? IRQ_HIGH : IRQ_LOW; + + if (irq_trigger != Irq_session::TRIGGER_UNCHANGED) + level = (irq_trigger == Irq_session::TRIGGER_LEVEL) ? IRQ_LEVEL : IRQ_EDGE; + + if (irq_polarity != Irq_session::POLARITY_UNCHANGED) + polarity = (irq_polarity == Irq_session::POLARITY_HIGH) ? IRQ_HIGH : IRQ_LOW; + + /* setup irq */ + seL4_CNode root = seL4_CapInitThreadCNode; + seL4_Word index = _kernel_irq_sel.value(); + seL4_Uint8 depth = 32; + seL4_Word ioapic = 0; + seL4_Word pin = _irq ? _irq : 2; + seL4_Word vector = _irq; + int res = seL4_IRQControl_GetIOAPIC(seL4_CapIRQControl, root, index, depth, + ioapic, pin, level, polarity, vector); + if (res != seL4_NoError) + return false; + + seL4_CPtr irq_handler = _kernel_irq_sel.value(); + seL4_CPtr notification = _kernel_notify_sel.value(); + + res = seL4_IRQHandler_SetNotification(irq_handler, notification); + + return (res == seL4_NoError); +} void Irq_object::_wait_for_irq() { - PDBG("not implemented"); + seL4_Wait(_kernel_notify_sel.value(), nullptr); } void Irq_object::start() { - PDBG("not implemented"); + ::Thread::start(); + _sync_bootup.lock(); } void Irq_object::entry() { - PDBG("not implemented"); + /* thread is up and ready */ + _sync_bootup.unlock(); + + while (true) { + + _wait_for_irq(); + + if (!_sig_cap.valid()) + continue; + + notify(); + } } +void Genode::Irq_object::ack_irq() +{ + int res = seL4_IRQHandler_Ack(_kernel_irq_sel.value()); + if (res != seL4_NoError) + Genode::error("ack_irq failed - ", res); +} Irq_object::Irq_object(unsigned irq) : Thread_deprecated<4096>("irq"), - _sync_ack(Lock::LOCKED), _sync_bootup(Lock::LOCKED), - _irq(irq) + _sync_bootup(Lock::LOCKED), + _irq(irq), + _kernel_irq_sel(platform_specific()->core_sel_alloc().alloc()), + _kernel_notify_sel(platform_specific()->core_sel_alloc().alloc()) { } @@ -62,7 +125,15 @@ Irq_session_component::Irq_session_component(Range_allocator *irq_alloc, throw Root::Unavailable(); if (!irq_alloc || irq_alloc->alloc_addr(1, _irq_number).error()) { - PERR("Unavailable IRQ 0x%x requested", _irq_number); + Genode::error("Unavailable IRQ ", _irq_number, " requested"); + throw Root::Unavailable(); + } + + + Irq_args const irq_args(args); + + if (!_irq_object.associate(irq_args.trigger(), irq_args.polarity())) { + Genode::error("Could not associate with IRQ ", irq_args.irq_number()); throw Root::Unavailable(); } @@ -72,7 +143,7 @@ Irq_session_component::Irq_session_component(Range_allocator *irq_alloc, Irq_session_component::~Irq_session_component() { - PERR("Not yet implemented."); + Genode::error(__PRETTY_FUNCTION__, "- not yet implemented."); } diff --git a/repos/base-sel4/src/core/stack_area.cc b/repos/base-sel4/src/core/stack_area.cc index 457f673e4..bd4c45a85 100644 --- a/repos/base-sel4/src/core/stack_area.cc +++ b/repos/base-sel4/src/core/stack_area.cc @@ -98,7 +98,25 @@ class Stack_area_region_map : public Region_map return local_addr; } - void detach(Local_addr) override { PWRN("Not implemented!"); } + void detach(Local_addr local_addr) override + { + using Genode::addr_t; + + if ((addr_t)local_addr >= stack_area_virtual_size()) + return; + + addr_t const detach = stack_area_virtual_base() + (addr_t)local_addr; + addr_t const stack = stack_virtual_size(); + addr_t const pages = ((detach & ~(stack - 1)) + stack - detach) + >> get_page_size_log2(); + + unmap_local(detach, pages); + + /* XXX missing XXX */ + warning(__PRETTY_FUNCTION__, ": not implemented"); + // Untyped_memory::convert_to_untyped_frames(phys_addr, phys_size) + // Untyped_memory::free_pages(phys_alloc, num_pages); + } void fault_handler(Signal_context_capability) override { } diff --git a/repos/base-sel4/src/core/thread_start.cc b/repos/base-sel4/src/core/thread_start.cc index 633f74fff..50955f07e 100644 --- a/repos/base-sel4/src/core/thread_start.cc +++ b/repos/base-sel4/src/core/thread_start.cc @@ -59,7 +59,19 @@ void Thread::_init_platform_thread(size_t, Type type) void Thread::_deinit_platform_thread() { - PDBG("not implemented"); + addr_t const utcb_virt_addr = (addr_t)&_stack->utcb(); + + bool ret = unmap_local(utcb_virt_addr, 1); + ASSERT(ret); + + int res = seL4_CNode_Delete(seL4_CapInitThreadCNode, + native_thread().lock_sel, 32); + if (res) + error(__PRETTY_FUNCTION__, ": seL4_CNode_Delete (", + Hex(native_thread().lock_sel), ") returned ", res); + + Platform &platform = *platform_specific(); + platform.core_sel_alloc().free(Cap_sel(native_thread().lock_sel)); }