mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-23 04:25:21 +00:00
parent
b88d7e3370
commit
47744e0019
62
base-hw/include/irq_session/client.h
Normal file
62
base-hw/include/irq_session/client.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Client-side IRQ session interface
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 _IRQ_SESSION__CLIENT_H_
|
||||
#define _IRQ_SESSION__CLIENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <irq_session/capability.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Client-side IRQ session interface
|
||||
*/
|
||||
struct 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
|
||||
*
|
||||
* \param session pointer to the session backend
|
||||
*/
|
||||
explicit Irq_session_client(Irq_session_capability const & session)
|
||||
:
|
||||
Rpc_client<Irq_session>(session),
|
||||
irq_signal(signal())
|
||||
{ }
|
||||
|
||||
|
||||
/*****************
|
||||
** Irq_session **
|
||||
*****************/
|
||||
|
||||
Irq_signal signal() { return call<Rpc_signal>(); }
|
||||
|
||||
void wait_for_irq()
|
||||
{
|
||||
while (Kernel::await_signal(irq_signal.receiver_id,
|
||||
irq_signal.context_id))
|
||||
{
|
||||
PERR("failed to receive interrupt");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _IRQ_SESSION__CLIENT_H_ */
|
82
base-hw/include/irq_session/irq_session.h
Normal file
82
base-hw/include/irq_session/irq_session.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* \brief IRQ session interface
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 _IRQ_SESSION__IRQ_SESSION_H_
|
||||
#define _IRQ_SESSION__IRQ_SESSION_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/capability.h>
|
||||
#include <session/session.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Information that enables a user to await and ack an IRQ directly
|
||||
*/
|
||||
struct Irq_signal
|
||||
{
|
||||
unsigned receiver_id;
|
||||
unsigned context_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* IRQ session interface
|
||||
*/
|
||||
struct Irq_session : Session
|
||||
{
|
||||
/**
|
||||
* Interrupt trigger
|
||||
*/
|
||||
enum Trigger { TRIGGER_UNCHANGED = 0, TRIGGER_LEVEL, TRIGGER_EDGE };
|
||||
|
||||
/**
|
||||
* Interrupt trigger polarity
|
||||
*/
|
||||
enum Polarity { POLARITY_UNCHANGED = 0, POLARITY_HIGH, POLARITY_LOW };
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~Irq_session() { }
|
||||
|
||||
/**
|
||||
* Await the next occurence of the interrupt of this session
|
||||
*/
|
||||
virtual void wait_for_irq() = 0;
|
||||
|
||||
/**
|
||||
* Get information for direct interrupt handling
|
||||
*
|
||||
* FIXME: This is used only client-internal and could thus be protected.
|
||||
*/
|
||||
virtual Irq_signal signal() = 0;
|
||||
|
||||
|
||||
/*************
|
||||
** Session **
|
||||
*************/
|
||||
|
||||
static const char * service_name() { return "IRQ"; }
|
||||
|
||||
|
||||
/*********************
|
||||
** 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);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _IRQ_SESSION__IRQ_SESSION_H_ */
|
@ -64,11 +64,6 @@ namespace Kernel
|
||||
NEW_PD = 13,
|
||||
KILL_PD = 34,
|
||||
|
||||
/* interrupt handling */
|
||||
ALLOCATE_IRQ = 14,
|
||||
AWAIT_IRQ = 15,
|
||||
FREE_IRQ = 16,
|
||||
|
||||
/* debugging */
|
||||
PRINT_CHAR = 17,
|
||||
|
||||
@ -392,40 +387,6 @@ namespace Kernel
|
||||
inline void print_char(char const c)
|
||||
{ syscall(PRINT_CHAR, (Syscall_arg)c); }
|
||||
|
||||
/**
|
||||
* Allocate an IRQ to the caller if the IRQ is not allocated already
|
||||
*
|
||||
* \param id ID of the targeted IRQ
|
||||
*
|
||||
* \return wether the IRQ has been allocated to this thread or not
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline bool allocate_irq(unsigned const id) {
|
||||
return syscall(ALLOCATE_IRQ, (Syscall_arg)id); }
|
||||
|
||||
|
||||
/**
|
||||
* Free an IRQ from allocation if it is allocated by the caller
|
||||
*
|
||||
* \param id ID of the targeted IRQ
|
||||
*
|
||||
* \return wether the IRQ has been freed or not
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline bool free_irq(unsigned const id) {
|
||||
return syscall(FREE_IRQ, (Syscall_arg)id); }
|
||||
|
||||
|
||||
/**
|
||||
* Block caller for the occurence of its IRQ
|
||||
*
|
||||
* Restricted to core threads. Blocks the caller forever
|
||||
* if he has not allocated any IRQ.
|
||||
*/
|
||||
inline void await_irq() { syscall(AWAIT_IRQ); }
|
||||
|
||||
|
||||
/**
|
||||
* Copy the current state of a thread to the callers UTCB
|
||||
@ -492,25 +453,29 @@ namespace Kernel
|
||||
|
||||
|
||||
/**
|
||||
* Wait for the occurence of any context of a receiver
|
||||
* Await any context of a receiver and optionally ack a context before
|
||||
*
|
||||
* \param receiver kernel name of the targeted signal receiver
|
||||
* \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.
|
||||
* If multiple threads listen at the same receiver, and/or
|
||||
* multiple contexts of the receiver trigger simultanously, there is no
|
||||
* assertion about wich thread receives, and from wich context. A context
|
||||
* that delivered once doesn't deliver again unless its last delivery has
|
||||
* been acknowledged via 'ack_signal'.
|
||||
* through this function until it gets delivered through this function or
|
||||
* context respectively receiver get destructed. If multiple threads
|
||||
* listen at the same receiver, and/or multiple contexts of the receiver
|
||||
* trigger simultanously, there is no assertion about wich thread
|
||||
* receives, and from wich context. A context that delivered once doesn't
|
||||
* deliver again unless its last delivery has been acknowledged via
|
||||
* ack_signal.
|
||||
*/
|
||||
inline int await_signal(unsigned const receiver)
|
||||
inline int await_signal(unsigned const receiver_id,
|
||||
unsigned const context_id)
|
||||
{
|
||||
return syscall(AWAIT_SIGNAL, receiver);
|
||||
return syscall(AWAIT_SIGNAL, receiver_id, context_id);
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +177,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())) {
|
||||
if (Kernel::await_signal(_cap.dst(), 0)) {
|
||||
PERR("failed to receive signal");
|
||||
return Signal(Signal::Data());
|
||||
}
|
||||
|
@ -16,10 +16,43 @@
|
||||
#include <platform.h>
|
||||
#include <pic.h>
|
||||
#include <timer.h>
|
||||
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::PWM_IRQ_0,
|
||||
Board::USB_HOST20_IRQ,
|
||||
Board::USB_DRD30_IRQ,
|
||||
Board::SATA_IRQ,
|
||||
Board::I2C_HDMI_IRQ,
|
||||
Board::SDMMC0_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -31,26 +64,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Kernel::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ Kernel::Timer::IRQ, 1 },
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -15,9 +15,38 @@
|
||||
#include <platform.h>
|
||||
#include <board.h>
|
||||
#include <pic.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::EPIT_2_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -29,30 +58,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Imx31::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Board::EPIT_1_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::UART_1_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -15,9 +15,54 @@
|
||||
#include <platform.h>
|
||||
#include <board.h>
|
||||
#include <pic.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::EPIT_2_IRQ,
|
||||
Board::GPIO1_IRQL,
|
||||
Board::GPIO1_IRQH,
|
||||
Board::GPIO2_IRQL,
|
||||
Board::GPIO2_IRQH,
|
||||
Board::GPIO3_IRQL,
|
||||
Board::GPIO3_IRQH,
|
||||
Board::GPIO4_IRQL,
|
||||
Board::GPIO4_IRQH,
|
||||
Board::GPIO5_IRQL,
|
||||
Board::GPIO5_IRQH,
|
||||
Board::GPIO6_IRQL,
|
||||
Board::GPIO6_IRQH,
|
||||
Board::GPIO7_IRQL,
|
||||
Board::GPIO7_IRQH,
|
||||
Board::I2C_2_IRQ,
|
||||
Board::I2C_3_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -29,30 +74,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Imx53::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Board::EPIT_1_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::UART_1_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
74
base-hw/src/core/include/irq_session_component.h
Normal file
74
base-hw/src/core/include/irq_session_component.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* \brief Backend for IRQ sessions served by core
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 _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;
|
||||
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__IRQ_SESSION_COMPONENT_H_ */
|
@ -17,6 +17,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/sync_allocator.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
#include <kernel/log.h>
|
||||
#include <kernel/syscalls.h>
|
||||
|
||||
@ -52,7 +53,6 @@ namespace Genode {
|
||||
*/
|
||||
static Native_region * _ram_regions(unsigned i);
|
||||
static Native_region * _mmio_regions(unsigned i);
|
||||
static Native_region * _irq_regions(unsigned i);
|
||||
|
||||
/**
|
||||
* Get one of the consecutively numbered core regions
|
||||
@ -66,7 +66,16 @@ namespace Genode {
|
||||
*/
|
||||
static Native_region * _core_only_ram_regions(unsigned i);
|
||||
static Native_region * _core_only_mmio_regions(unsigned i);
|
||||
static Native_region * _core_only_irq_regions(unsigned i);
|
||||
|
||||
/**
|
||||
* Get one of the consecutively numbered user interrupts
|
||||
*
|
||||
* \param i index of interrupt
|
||||
*
|
||||
* \return >0 pointer to the name of the requested interrupt
|
||||
* 0 no interrupt for that index
|
||||
*/
|
||||
static unsigned * _irq(unsigned const i);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Implementation of IRQ session component
|
||||
* \brief Backend for IRQ sessions served by core
|
||||
* \author Martin Stein
|
||||
* \date 2012-02-12
|
||||
*/
|
||||
@ -15,56 +15,54 @@
|
||||
#include <kernel/syscalls.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/irq.h>
|
||||
#include <irq_root.h>
|
||||
#include <core_env.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
bool
|
||||
Irq_session_component::Irq_control_component::associate_to_irq(unsigned irq)
|
||||
{ return Kernel::allocate_irq(irq); }
|
||||
|
||||
|
||||
void Irq_session_component::wait_for_irq() { Kernel::await_irq(); }
|
||||
|
||||
|
||||
Irq_session_component::~Irq_session_component()
|
||||
/**
|
||||
* 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()
|
||||
{
|
||||
/* free IRQ for other threads */
|
||||
if (Kernel::free_irq(_irq_number))
|
||||
PERR("Could not free IRQ %u", _irq_number);
|
||||
enum { STACK_SIZE = 2048 };
|
||||
static Rpc_entrypoint
|
||||
_ep(core_env()->cap_session(), STACK_SIZE, "irq_session_ep");
|
||||
return &_ep;
|
||||
}
|
||||
|
||||
void Irq_session_component::wait_for_irq() { PERR("not implemented"); }
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session * cap_session,
|
||||
Range_allocator * irq_alloc,
|
||||
const char * args)
|
||||
Irq_signal Irq_session_component::signal() { return _signal; }
|
||||
|
||||
Irq_session_component::~Irq_session_component() { PERR("not implemented"); }
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Cap_session * const cap_session,
|
||||
Range_allocator * const irq_alloc,
|
||||
const char * const 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)
|
||||
{
|
||||
/* check arguments */
|
||||
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
||||
if (shared) {
|
||||
PERR("IRQ sharing not supported");
|
||||
PERR("shared interrupts not supported");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
/* allocate IRQ */
|
||||
/* allocate interrupt */
|
||||
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||
if (irq_number < 0 || !irq_alloc ||
|
||||
irq_alloc->alloc_addr(1, irq_number).is_error())
|
||||
{
|
||||
PERR("Unavailable IRQ %lu requested", irq_number);
|
||||
bool error = irq_number < 0 || !_irq_alloc;
|
||||
error |= _irq_alloc->alloc_addr(1, irq_number).is_error();
|
||||
if (error) {
|
||||
PERR("unavailable interrupt requested");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
_irq_number = irq_number;
|
||||
|
||||
/* configure control client */
|
||||
if (!_control_client.associate_to_irq(irq_number)) {
|
||||
PERR("IRQ association failed");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
/* create IRQ capability */
|
||||
_irq_cap = Irq_session_capability(_ep.manage(this));
|
||||
/* make interrupt accessible */
|
||||
_signal = Irq::signal(irq_number);
|
||||
_cap = Irq_session_capability(irq_session_ep()->manage(this));
|
||||
}
|
||||
|
@ -25,9 +25,11 @@
|
||||
/* core includes */
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/vm.h>
|
||||
#include <kernel/irq.h>
|
||||
#include <platform_pd.h>
|
||||
#include <trustzone.h>
|
||||
#include <timer.h>
|
||||
#include <pic.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <singleton.h>
|
||||
@ -42,9 +44,16 @@ extern "C" void CORE_MAIN();
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Return interrupt-controller singleton
|
||||
*/
|
||||
Pic * pic() { return unsynchronized_singleton<Pic>(); }
|
||||
|
||||
/* import Genode types */
|
||||
typedef Genode::umword_t umword_t;
|
||||
typedef Genode::Core_tlb Core_tlb;
|
||||
|
||||
void init_platform();
|
||||
}
|
||||
|
||||
namespace Kernel
|
||||
@ -142,10 +151,10 @@ namespace Kernel
|
||||
void handle_interrupt()
|
||||
{
|
||||
/* determine handling for specific interrupt */
|
||||
unsigned irq;
|
||||
if (pic()->take_request(irq))
|
||||
unsigned irq_id;
|
||||
if (pic()->take_request(irq_id))
|
||||
{
|
||||
switch (irq) {
|
||||
switch (irq_id) {
|
||||
|
||||
case Timer::IRQ: {
|
||||
|
||||
@ -156,9 +165,7 @@ namespace Kernel
|
||||
|
||||
default: {
|
||||
|
||||
Irq_receiver * const o = Irq_receiver::receiver(irq);
|
||||
assert(o);
|
||||
o->receive_irq(irq);
|
||||
Irq::occurred(irq_id);
|
||||
break; }
|
||||
}
|
||||
}
|
||||
@ -180,7 +187,7 @@ extern "C" void kernel()
|
||||
{
|
||||
static bool initial_call = true;
|
||||
|
||||
/* an exception occured */
|
||||
/* an exception occurred */
|
||||
if (!initial_call)
|
||||
{
|
||||
/* handle exception that interrupted the last user */
|
||||
@ -189,8 +196,6 @@ extern "C" void kernel()
|
||||
/* kernel initialization */
|
||||
} else {
|
||||
|
||||
Genode::printf("Kernel started!\n");
|
||||
|
||||
/* enable kernel timer */
|
||||
pic()->unmask(Timer::IRQ);
|
||||
|
||||
@ -221,8 +226,8 @@ extern "C" void kernel()
|
||||
static Thread t((Platform_thread *)0);
|
||||
t.init(ip, sp, 0, core_id(), &utcb, &utcb, 1, 1);
|
||||
}
|
||||
|
||||
/* kernel initialization finished */
|
||||
init_platform();
|
||||
reset_lap_time();
|
||||
initial_call = false;
|
||||
}
|
||||
|
24
base-hw/src/core/kernel/irq.cc
Normal file
24
base-hw/src/core/kernel/irq.cc
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* \brief Kernel back-end and core front-end for user interrupts
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/irq.h>
|
||||
#include <pic.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
namespace Kernel { Pic * pic(); }
|
||||
|
||||
void Irq::_disable() const { pic()->mask(_id()); }
|
||||
|
||||
void Irq::_enable() const { pic()->unmask(_id()); }
|
182
base-hw/src/core/kernel/irq.h
Normal file
182
base-hw/src/core/kernel/irq.h
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* \brief Kernel back-end and core front-end for user interrupts
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-28
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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 _KERNEL__IRQ_H_
|
||||
#define _KERNEL__IRQ_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/native_types.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/signal_receiver.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Kernel back-end of a user interrupt
|
||||
*/
|
||||
class Irq;
|
||||
}
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Core front-end of a user interrupt
|
||||
*/
|
||||
class Irq;
|
||||
}
|
||||
|
||||
class Kernel::Irq
|
||||
:
|
||||
public Object_pool<Irq>::Item,
|
||||
public Signal_receiver,
|
||||
public Signal_context
|
||||
{
|
||||
friend class Genode::Irq;
|
||||
|
||||
private:
|
||||
|
||||
typedef Object_pool<Irq> Pool;
|
||||
|
||||
/**
|
||||
* Get map that provides all user interrupts by their kernel names
|
||||
*/
|
||||
static Pool * _pool()
|
||||
{
|
||||
static Pool p;
|
||||
return &p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent interrupt from occurring
|
||||
*/
|
||||
void _disable() const;
|
||||
|
||||
/**
|
||||
* Allow interrupt to occur
|
||||
*/
|
||||
void _enable() const;
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt
|
||||
*/
|
||||
unsigned _id() const { return Pool::Item::id(); };
|
||||
|
||||
/**
|
||||
* 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(); }
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
*/
|
||||
void _occurred()
|
||||
{
|
||||
Signal_context::submit(1);
|
||||
_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information that enables a user to handle an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static Genode::Irq_signal _genode_signal(unsigned const irq_id)
|
||||
{
|
||||
typedef Genode::Irq_signal Irq_signal;
|
||||
static Irq_signal const invalid = { 0, 0 };
|
||||
Irq * const irq = _pool()->object(irq_id);
|
||||
if (irq) {
|
||||
Irq_signal s = { irq->_receiver_id(), irq->_context_id() };
|
||||
return s;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* By now, there is no use case to destruct user interrupts
|
||||
*/
|
||||
~Irq() { PERR("method not implemented"); }
|
||||
|
||||
|
||||
/********************
|
||||
** Signal_context **
|
||||
********************/
|
||||
|
||||
void _signal_context_acknowledged() { _enable(); }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Placement-new operator
|
||||
*
|
||||
* \param p destination of new object
|
||||
*
|
||||
* \return destination of new object
|
||||
*/
|
||||
void * operator new (size_t, void * p) { return p; }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
*/
|
||||
Irq(unsigned const irq_id)
|
||||
:
|
||||
Pool::Item(irq_id),
|
||||
Signal_context(this)
|
||||
{
|
||||
_pool()->insert(this);
|
||||
_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle occurence of an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static void occurred(unsigned const irq_id)
|
||||
{
|
||||
Irq * const irq = _pool()->object(irq_id);
|
||||
if (!irq) {
|
||||
PERR("unknown interrupt occurred");
|
||||
return;
|
||||
}
|
||||
irq->_occurred();
|
||||
}
|
||||
};
|
||||
|
||||
class Genode::Irq
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get information that enables a user to handle an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static Irq_signal signal(unsigned const irq_id)
|
||||
{
|
||||
return Kernel::Irq::_genode_signal(irq_id);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _KERNEL__IRQ_H_ */
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* \brief Exclusive ownership and handling of interrupts
|
||||
* \author Martin Stein
|
||||
* \date 2012-11-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _KERNEL__IRQ_RECEIVER_H_
|
||||
#define _KERNEL__IRQ_RECEIVER_H_
|
||||
|
||||
/* core includes */
|
||||
#include <pic.h>
|
||||
#include <assert.h>
|
||||
#include <kernel/object.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Exclusive ownership and handling of one interrupt at a time
|
||||
*/
|
||||
class Irq_receiver;
|
||||
|
||||
/**
|
||||
* Return interrupt-controller singleton
|
||||
*/
|
||||
static Pic * pic() { return unsynchronized_singleton<Pic>(); }
|
||||
}
|
||||
|
||||
class Kernel::Irq_receiver : public Object_pool<Irq_receiver>::Item
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Object_pool<Irq_receiver> Pool;
|
||||
|
||||
/**
|
||||
* Return map that maps assigned interrupts to their receivers
|
||||
*/
|
||||
static Pool * _pool() { static Pool _pool; return &_pool; }
|
||||
|
||||
/**
|
||||
* Translate receiver ID 'id' to interrupt ID
|
||||
*/
|
||||
static unsigned _id_to_irq(unsigned id) { return id - 1; }
|
||||
|
||||
/**
|
||||
* Translate interrupt ID 'id' to receiver ID
|
||||
*/
|
||||
static unsigned _irq_to_id(unsigned irq) { return irq + 1; }
|
||||
|
||||
/**
|
||||
* Free interrupt of this receiver without sanity checks
|
||||
*/
|
||||
void _free_irq()
|
||||
{
|
||||
_pool()->remove(this);
|
||||
_id = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop receiver from waiting for its interrupt without sanity checks
|
||||
*/
|
||||
void _cancel_waiting() { pic()->mask(_id_to_irq(_id)); }
|
||||
|
||||
/**
|
||||
* Gets called as soon as the receivers interrupt occurs
|
||||
*/
|
||||
virtual void _received_irq() = 0;
|
||||
|
||||
/**
|
||||
* Gets called when receiver starts waiting for its interrupt
|
||||
*/
|
||||
virtual void _awaits_irq() = 0;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Irq_receiver() : Pool::Item(0) { }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Irq_receiver()
|
||||
{
|
||||
if (_id) {
|
||||
_cancel_waiting();
|
||||
_free_irq();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign interrupt 'irq' to the receiver
|
||||
*
|
||||
* \return wether the assignment succeeded
|
||||
*/
|
||||
bool allocate_irq(unsigned const irq)
|
||||
{
|
||||
/* check if an allocation is needed and possible */
|
||||
unsigned const id = _irq_to_id(irq);
|
||||
if (_id) { return _id == id; }
|
||||
if (_pool()->object(id)) { return 0; }
|
||||
|
||||
/* allocate and mask the interrupt */
|
||||
pic()->mask(irq);
|
||||
_id = id;
|
||||
_pool()->insert(this);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unassign interrupt 'irq' if it is assigned to the receiver
|
||||
*
|
||||
* \return wether the unassignment succeeded
|
||||
*/
|
||||
bool free_irq(unsigned const irq)
|
||||
{
|
||||
if (_id != _irq_to_id(irq)) { return 0; }
|
||||
_free_irq();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmask and await interrupt that is assigned to the receiver
|
||||
*/
|
||||
void await_irq()
|
||||
{
|
||||
if (!_id) {
|
||||
PERR("waiting for imaginary interrupt");
|
||||
return;
|
||||
}
|
||||
unsigned const irq = _id_to_irq(_id);
|
||||
pic()->unmask(irq);
|
||||
_awaits_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop waiting for the interrupt of the receiver
|
||||
*/
|
||||
void cancel_waiting() { if (_id) { _cancel_waiting(); } }
|
||||
|
||||
/**
|
||||
* Denote that the receivers interrupt 'irq' occured and mask it
|
||||
*/
|
||||
void receive_irq(unsigned const irq)
|
||||
{
|
||||
assert(_id == _irq_to_id(irq));
|
||||
pic()->mask(irq);
|
||||
_received_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get receiver of IRQ 'irq' or 0 if the IRQ isn't assigned
|
||||
*/
|
||||
static Irq_receiver * receiver(unsigned irq)
|
||||
{
|
||||
return _pool()->object(_irq_to_id(irq));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _KERNEL__IRQ_RECEIVER_H_ */
|
@ -44,3 +44,11 @@ void Signal_context::_deliverable()
|
||||
|
||||
Signal_context::~Signal_context() { _receiver->_context_killed(this); }
|
||||
|
||||
|
||||
Signal_context::Signal_context(Signal_receiver * const r)
|
||||
:
|
||||
_deliver_fe(this), _contexts_fe(this), _receiver(r),
|
||||
_imprint(Object::id()), _submits(0), _ack(1), _kill(0), _killer(0)
|
||||
{
|
||||
r->add_context(this);
|
||||
}
|
||||
|
@ -232,12 +232,7 @@ class Kernel::Signal_context
|
||||
void _killer_cancelled() { _killer = 0; }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Signal_context();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructor that is used by signal receivers
|
||||
*
|
||||
* \param r receiver that the context is assigned to
|
||||
* \param imprint userland identification of the context
|
||||
@ -248,6 +243,25 @@ class Kernel::Signal_context
|
||||
_imprint(imprint), _submits(0), _ack(1), _kill(0), _killer(0)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Hook to install in-kernel handler for acks at specific signal types
|
||||
*/
|
||||
virtual void _signal_context_acknowledged() { };
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Constructor that is used by
|
||||
*
|
||||
* \param r receiver that the context is assigned to
|
||||
*/
|
||||
Signal_context(Signal_receiver * const r);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Signal_context();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -271,6 +285,7 @@ class Kernel::Signal_context
|
||||
*/
|
||||
void ack()
|
||||
{
|
||||
_signal_context_acknowledged();
|
||||
if (_ack) { return; }
|
||||
if (!_kill) {
|
||||
_ack = 1;
|
||||
@ -441,6 +456,9 @@ class Kernel::Signal_receiver
|
||||
/**
|
||||
* Create a context that is assigned to the receiver
|
||||
*
|
||||
* \param p memory destination
|
||||
* \param imprint userland identification of context
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
@ -453,6 +471,19 @@ class Kernel::Signal_receiver
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign context 'c' to the receiver
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
int add_context(Signal_context * const c)
|
||||
{
|
||||
if (_kill) { return -1; }
|
||||
_contexts.enqueue(&c->_contexts_fe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wether any of the contexts of this receiver is deliverable
|
||||
*/
|
||||
|
@ -161,20 +161,6 @@ void Thread::_await_ipc_failed()
|
||||
}
|
||||
|
||||
|
||||
void Thread::_received_irq()
|
||||
{
|
||||
assert(_state == AWAITS_IRQ);
|
||||
_schedule();
|
||||
}
|
||||
|
||||
|
||||
void Thread::_awaits_irq()
|
||||
{
|
||||
cpu_scheduler()->remove(this);
|
||||
_state = AWAITS_IRQ;
|
||||
}
|
||||
|
||||
|
||||
int Thread::_resume()
|
||||
{
|
||||
switch (_state) {
|
||||
@ -192,9 +178,6 @@ int Thread::_resume()
|
||||
case AWAITS_IPC:
|
||||
Ipc_node::cancel_waiting();
|
||||
return 0;
|
||||
case AWAITS_IRQ:
|
||||
Irq_receiver::cancel_waiting();
|
||||
return 0;
|
||||
case AWAITS_SIGNAL:
|
||||
Signal_handler::cancel_waiting();
|
||||
return 0;
|
||||
@ -688,38 +671,6 @@ void Thread::_syscall_update_region()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
void Thread::_syscall_allocate_irq()
|
||||
{
|
||||
assert(_core());
|
||||
unsigned irq = user_arg_1();
|
||||
user_arg_0(allocate_irq(irq));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
void Thread::_syscall_free_irq()
|
||||
{
|
||||
assert(_core());
|
||||
unsigned irq = user_arg_1();
|
||||
user_arg_0(free_irq(irq));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
void Thread::_syscall_await_irq()
|
||||
{
|
||||
assert(_core());
|
||||
await_irq();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
@ -767,7 +718,7 @@ void Thread::_syscall_new_signal_receiver()
|
||||
return;
|
||||
}
|
||||
/* create receiver */
|
||||
void * p = (void *)user_arg_1();
|
||||
void * const p = (void *)user_arg_1();
|
||||
Signal_receiver * const r = new (p) Signal_receiver();
|
||||
user_arg_0(r->id());
|
||||
}
|
||||
@ -785,7 +736,7 @@ void Thread::_syscall_new_signal_context()
|
||||
return;
|
||||
}
|
||||
/* lookup receiver */
|
||||
unsigned id = user_arg_2();
|
||||
unsigned const id = user_arg_2();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(id);
|
||||
if (!r) {
|
||||
PERR("unknown signal receiver");
|
||||
@ -793,8 +744,8 @@ void Thread::_syscall_new_signal_context()
|
||||
return;
|
||||
}
|
||||
/* create and assign context*/
|
||||
void * p = (void *)user_arg_1();
|
||||
unsigned imprint = user_arg_3();
|
||||
void * const p = (void *)user_arg_1();
|
||||
unsigned const imprint = user_arg_3();
|
||||
if (r->new_context(p, imprint)) {
|
||||
PERR("failed to create signal context");
|
||||
user_arg_0(0);
|
||||
@ -811,9 +762,16 @@ void Thread::_syscall_new_signal_context()
|
||||
*/
|
||||
void Thread::_syscall_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 { PERR("failed to acknowledge signal context"); }
|
||||
}
|
||||
/* lookup receiver */
|
||||
unsigned id = user_arg_1();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(id);
|
||||
unsigned const receiver_id = user_arg_1();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(receiver_id);
|
||||
if (!r) {
|
||||
PERR("unknown signal receiver");
|
||||
user_arg_0(-1);
|
||||
@ -835,7 +793,7 @@ void Thread::_syscall_await_signal()
|
||||
void Thread::_syscall_signal_pending()
|
||||
{
|
||||
/* lookup signal receiver */
|
||||
unsigned id = user_arg_1();
|
||||
unsigned const id = user_arg_1();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(id);
|
||||
if (!r) {
|
||||
PERR("unknown signal receiver");
|
||||
@ -876,7 +834,7 @@ void Thread::_syscall_submit_signal()
|
||||
void Thread::_syscall_ack_signal()
|
||||
{
|
||||
/* lookup signal context */
|
||||
unsigned id = user_arg_1();
|
||||
unsigned const id = user_arg_1();
|
||||
Signal_context * const c = Signal_context::pool()->object(id);
|
||||
if (!c) {
|
||||
PERR("unknown signal context");
|
||||
@ -899,7 +857,7 @@ void Thread::_syscall_kill_signal_context()
|
||||
return;
|
||||
}
|
||||
/* lookup signal context */
|
||||
unsigned id = user_arg_1();
|
||||
unsigned const id = user_arg_1();
|
||||
Signal_context * const c = Signal_context::pool()->object(id);
|
||||
if (!c) {
|
||||
PERR("unknown signal context");
|
||||
@ -928,7 +886,7 @@ void Thread::_syscall_kill_signal_receiver()
|
||||
return;
|
||||
}
|
||||
/* lookup signal receiver */
|
||||
unsigned id = user_arg_1();
|
||||
unsigned const id = user_arg_1();
|
||||
Signal_receiver * const r = Signal_receiver::pool()->object(id);
|
||||
if (!r) {
|
||||
PERR("unknown signal receiver");
|
||||
@ -1028,9 +986,6 @@ void Thread::_syscall()
|
||||
case UPDATE_PD: _syscall_update_pd(); return;
|
||||
case UPDATE_REGION: _syscall_update_region(); return;
|
||||
case NEW_PD: _syscall_new_pd(); return;
|
||||
case ALLOCATE_IRQ: _syscall_allocate_irq(); return;
|
||||
case AWAIT_IRQ: _syscall_await_irq(); return;
|
||||
case FREE_IRQ: _syscall_free_irq(); return;
|
||||
case PRINT_CHAR: _syscall_print_char(); return;
|
||||
case NEW_SIGNAL_RECEIVER: _syscall_new_signal_receiver(); return;
|
||||
case NEW_SIGNAL_CONTEXT: _syscall_new_signal_context(); return;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/signal_receiver.h>
|
||||
#include <kernel/ipc_node.h>
|
||||
#include <kernel/irq_receiver.h>
|
||||
#include <cpu.h>
|
||||
|
||||
namespace Genode
|
||||
@ -56,7 +55,6 @@ class Kernel::Thread
|
||||
public Object<Thread, MAX_THREADS, Thread_ids, thread_ids, thread_pool>,
|
||||
public Execution_context,
|
||||
public Ipc_node,
|
||||
public Irq_receiver,
|
||||
public Signal_context_killer,
|
||||
public Signal_receiver_killer,
|
||||
public Signal_handler
|
||||
@ -73,7 +71,6 @@ class Kernel::Thread
|
||||
AWAITS_RESUME = 4,
|
||||
AWAITS_PAGER = 5,
|
||||
AWAITS_PAGER_IPC = 6,
|
||||
AWAITS_IRQ = 7,
|
||||
AWAITS_SIGNAL = 8,
|
||||
AWAITS_SIGNAL_CONTEXT_KILL = 9,
|
||||
AWAITS_SIGNAL_RECEIVER_KILL = 10,
|
||||
@ -160,9 +157,6 @@ class Kernel::Thread
|
||||
void _syscall_set_pager();
|
||||
void _syscall_update_pd();
|
||||
void _syscall_update_region();
|
||||
void _syscall_allocate_irq();
|
||||
void _syscall_free_irq();
|
||||
void _syscall_await_irq();
|
||||
void _syscall_print_char();
|
||||
void _syscall_read_thread_state();
|
||||
void _syscall_write_thread_state();
|
||||
@ -212,14 +206,6 @@ class Kernel::Thread
|
||||
void _await_ipc_succeeded(size_t const s);
|
||||
void _await_ipc_failed();
|
||||
|
||||
|
||||
/***************
|
||||
** Irq_owner **
|
||||
***************/
|
||||
|
||||
void _received_irq();
|
||||
void _awaits_irq();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
@ -16,9 +16,47 @@
|
||||
#include <board.h>
|
||||
#include <cpu.h>
|
||||
#include <pic.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::GP_TIMER_3_IRQ,
|
||||
Board::TL16C750_1_IRQ,
|
||||
Board::TL16C750_2_IRQ,
|
||||
Board::TL16C750_4_IRQ,
|
||||
Board::GPIO1_IRQ,
|
||||
Board::GPIO2_IRQ,
|
||||
Board::GPIO3_IRQ,
|
||||
Board::GPIO4_IRQ,
|
||||
Board::GPIO5_IRQ,
|
||||
Board::GPIO6_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -30,30 +68,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Kernel::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Genode::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::TL16C750_3_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -16,10 +16,46 @@
|
||||
#include <board.h>
|
||||
#include <cpu.h>
|
||||
#include <pic.h>
|
||||
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::SP804_0_1_IRQ,
|
||||
Board::KMI_0_IRQ,
|
||||
Board::KMI_1_IRQ,
|
||||
Board::ETHERNET_IRQ,
|
||||
Board::PL011_1_IRQ,
|
||||
Board::PL011_2_IRQ,
|
||||
Board::PL011_3_IRQ,
|
||||
Board::PL180_IRQ_0,
|
||||
Board::PL180_IRQ_1
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -32,30 +68,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Kernel::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -122,7 +122,13 @@ Platform::Platform() :
|
||||
enum { VERBOSE = 0 };
|
||||
unsigned const psl2 = get_page_size_log2();
|
||||
init_alloc(&_core_mem_alloc, _ram_regions, _core_only_ram_regions, psl2);
|
||||
init_alloc(&_irq_alloc, _irq_regions, _core_only_irq_regions);
|
||||
|
||||
/* make interrupts available to the interrupt allocator */
|
||||
for (unsigned i = 0; ; i++) {
|
||||
unsigned * const irq = _irq(i);
|
||||
if (!irq) { break; }
|
||||
_irq_alloc.add_range(*irq, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use byte granuarity for MMIO regions because on some platforms, devices
|
||||
|
@ -14,9 +14,38 @@
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <board.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::TIMER_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -28,31 +57,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, 64 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* system timer */
|
||||
{ Board::SYSTEM_TIMER_IRQ, 1 },
|
||||
|
||||
/* UART */
|
||||
{ Board::PL011_0_IRQ, 1 },
|
||||
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -50,6 +50,7 @@ SRC_CC += console.cc \
|
||||
kernel/thread.cc \
|
||||
kernel/vm.cc \
|
||||
kernel/signal_receiver.cc \
|
||||
kernel/irq.cc \
|
||||
rm_session_support.cc \
|
||||
kernel_support.cc \
|
||||
trustzone.cc \
|
||||
|
@ -16,9 +16,46 @@
|
||||
#include <board.h>
|
||||
#include <cpu.h>
|
||||
#include <pic.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::SP804_0_1_IRQ,
|
||||
Board::KMI_0_IRQ,
|
||||
Board::KMI_1_IRQ,
|
||||
Board::LAN9118_IRQ,
|
||||
Board::PL180_0_IRQ,
|
||||
Board::PL180_1_IRQ,
|
||||
Board::PL011_1_IRQ,
|
||||
Board::PL011_2_IRQ,
|
||||
Board::PL011_3_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -33,30 +70,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, Kernel::Pic::MAX_INTERRUPT_ID + 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* Core timer */
|
||||
{ Genode::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
@ -16,9 +16,45 @@
|
||||
#include <platform.h>
|
||||
#include <pic/vea9x4_trustzone.h>
|
||||
#include <cpu/cortex_a9.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Kernel { void init_platform(); }
|
||||
|
||||
/**
|
||||
* Interrupts that core shall provide to users
|
||||
*
|
||||
* Interrupts that are used by the non-secure world are also
|
||||
* not provided to the secure-world Genode to prevent contention.
|
||||
*/
|
||||
static unsigned irq_ids[] =
|
||||
{
|
||||
Board::PL180_0_IRQ,
|
||||
Board::PL180_1_IRQ,
|
||||
Board::PL011_1_IRQ,
|
||||
Board::PL011_2_IRQ,
|
||||
Board::PL011_3_IRQ
|
||||
};
|
||||
|
||||
enum { IRQ_IDS_SIZE = sizeof(irq_ids)/sizeof(irq_ids[0]) };
|
||||
|
||||
|
||||
void Kernel::init_platform()
|
||||
{
|
||||
/* make user IRQs become known by cores IRQ session backend and kernel */
|
||||
static uint8_t _irqs[IRQ_IDS_SIZE][sizeof(Irq)];
|
||||
for (unsigned i = 0; i < IRQ_IDS_SIZE; i++) {
|
||||
new (_irqs[i]) Irq(irq_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned * Platform::_irq(unsigned const i)
|
||||
{
|
||||
return i < IRQ_IDS_SIZE ? &irq_ids[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
@ -30,33 +66,6 @@ Native_region * Platform::_ram_regions(unsigned const i)
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, 34 },
|
||||
{ 37, 3 },
|
||||
{ 46, 1 },
|
||||
{ 49, Vea9x4_trustzone::Pic::MAX_INTERRUPT_ID - 49 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* Core timer */
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
|
Loading…
x
Reference in New Issue
Block a user