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));
}