parent
b32af4e0a4
commit
0188b08f6a
|
@ -31,10 +31,10 @@ namespace Genode
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
unsigned _irq_number;
|
|
||||||
Range_allocator * const _irq_alloc;
|
Range_allocator * const _irq_alloc;
|
||||||
Irq_session_capability _cap;
|
Irq_session_capability _cap;
|
||||||
Irq_signal _signal;
|
Irq_signal _signal;
|
||||||
|
Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace Kernel
|
||||||
class Signal_receiver;
|
class Signal_receiver;
|
||||||
class Signal_context;
|
class Signal_context;
|
||||||
class Vm;
|
class Vm;
|
||||||
|
class User_irq;
|
||||||
|
|
||||||
addr_t mode_transition_base();
|
addr_t mode_transition_base();
|
||||||
size_t mode_transition_size();
|
size_t mode_transition_size();
|
||||||
|
@ -54,6 +55,8 @@ namespace Kernel
|
||||||
constexpr Call_arg call_id_pause_vm() { return 29; }
|
constexpr Call_arg call_id_pause_vm() { return 29; }
|
||||||
constexpr Call_arg call_id_pause_thread() { return 30; }
|
constexpr Call_arg call_id_pause_thread() { return 30; }
|
||||||
constexpr Call_arg call_id_delete_vm() { return 31; }
|
constexpr Call_arg call_id_delete_vm() { return 31; }
|
||||||
|
constexpr Call_arg call_id_new_irq() { return 32; }
|
||||||
|
constexpr Call_arg call_id_delete_irq() { return 33; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a domain
|
* Create a domain
|
||||||
|
@ -346,6 +349,27 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
return call(call_id_pause_vm(), (Call_arg) vm);
|
return call(call_id_pause_vm(), (Call_arg) vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an interrupt object
|
||||||
|
*
|
||||||
|
* \param p memory donation for the irq object
|
||||||
|
* \param irq_nr interrupt number
|
||||||
|
*/
|
||||||
|
inline void new_irq(addr_t const p, unsigned irq_nr)
|
||||||
|
{
|
||||||
|
call(call_id_new_irq(), (Call_arg) p, irq_nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destruct an interrupt object
|
||||||
|
*
|
||||||
|
* \param irq pointer to interrupt kernel object
|
||||||
|
*/
|
||||||
|
inline void delete_irq(User_irq * const irq)
|
||||||
|
{
|
||||||
|
call(call_id_delete_irq(), (Call_arg) irq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _KERNEL__CORE_INTERFACE_H_ */
|
#endif /* _KERNEL__CORE_INTERFACE_H_ */
|
||||||
|
|
|
@ -113,16 +113,6 @@ class Kernel::User_irq
|
||||||
*/
|
*/
|
||||||
static Irq::Pool * _pool();
|
static Irq::Pool * _pool();
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(); }
|
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** Signal_ack_handler **
|
** Signal_ack_handler **
|
||||||
|
@ -145,6 +135,16 @@ class Kernel::User_irq
|
||||||
Signal_context::ack_handler(this);
|
Signal_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(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle occurence of the interrupt
|
* Handle occurence of the interrupt
|
||||||
*/
|
*/
|
||||||
|
@ -154,24 +154,6 @@ class Kernel::User_irq
|
||||||
disable();
|
disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information that enables a user to handle an interrupt
|
|
||||||
*
|
|
||||||
* \param irq_id kernel name of targeted interrupt
|
|
||||||
*/
|
|
||||||
static Genode::Irq_signal signal(unsigned const irq_id)
|
|
||||||
{
|
|
||||||
typedef Genode::Irq_signal Irq_signal;
|
|
||||||
static Irq_signal const invalid = { 0, 0 };
|
|
||||||
User_irq * const irq =
|
|
||||||
dynamic_cast<User_irq*>(_pool()->object(irq_id));
|
|
||||||
if (irq) {
|
|
||||||
Irq_signal s = { irq->_receiver_id(), irq->_context_id() };
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
return invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle occurence of an interrupt
|
* Handle occurence of an interrupt
|
||||||
*
|
*
|
||||||
|
|
|
@ -237,6 +237,8 @@ class Kernel::Thread
|
||||||
void _call_pause_vm();
|
void _call_pause_vm();
|
||||||
void _call_access_thread_regs();
|
void _call_access_thread_regs();
|
||||||
void _call_route_thread_event();
|
void _call_route_thread_event();
|
||||||
|
void _call_new_irq();
|
||||||
|
void _call_delete_irq();
|
||||||
|
|
||||||
|
|
||||||
/***************************
|
/***************************
|
||||||
|
|
|
@ -42,22 +42,28 @@ Irq_signal Irq_session_component::signal() { return _signal; }
|
||||||
|
|
||||||
Irq_session_component::~Irq_session_component()
|
Irq_session_component::~Irq_session_component()
|
||||||
{
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
irq_session_ep()->dissolve(this);
|
irq_session_ep()->dissolve(this);
|
||||||
_irq_alloc->free((void *)(addr_t)_irq_number);
|
User_irq * kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||||
|
_irq_alloc->free((void *)(addr_t)static_cast<Kernel::Irq*>(kirq)->id());
|
||||||
|
Kernel::delete_irq(kirq);
|
||||||
}
|
}
|
||||||
|
|
||||||
Irq_session_component::Irq_session_component(Cap_session * const cap_session,
|
Irq_session_component::Irq_session_component(Cap_session * const cap_session,
|
||||||
Range_allocator * const irq_alloc,
|
Range_allocator * const irq_alloc,
|
||||||
const char * const args)
|
const char * const args)
|
||||||
:
|
: _irq_alloc(irq_alloc)
|
||||||
_irq_alloc(irq_alloc)
|
|
||||||
{
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
/* check arguments */
|
/* check arguments */
|
||||||
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
bool shared = Arg_string::find_arg(args, "irq_shared").bool_value(false);
|
||||||
if (shared) {
|
if (shared) {
|
||||||
PERR("shared interrupts not supported");
|
PERR("shared interrupts not supported");
|
||||||
throw Root::Invalid_args();
|
throw Root::Invalid_args();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate interrupt */
|
/* allocate interrupt */
|
||||||
long irq_nr = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
long irq_nr = Arg_string::find_arg(args, "irq_number").long_value(-1);
|
||||||
bool error = irq_nr < 0 || !_irq_alloc;
|
bool error = irq_nr < 0 || !_irq_alloc;
|
||||||
|
@ -70,8 +76,10 @@ Irq_session_component::Irq_session_component(Cap_session * const cap_session
|
||||||
PERR("unavailable interrupt requested");
|
PERR("unavailable interrupt requested");
|
||||||
throw Root::Invalid_args();
|
throw Root::Invalid_args();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make interrupt accessible */
|
/* make interrupt accessible */
|
||||||
_irq_number = (unsigned)plat_irq_nr;
|
new_irq((addr_t)&_kernel_object, plat_irq_nr);
|
||||||
_signal = Kernel::User_irq::signal(plat_irq_nr);
|
User_irq * kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||||
|
_signal = { kirq->receiver_id(), kirq->context_id() };
|
||||||
_cap = Irq_session_capability(irq_session_ep()->manage(this));
|
_cap = Irq_session_capability(irq_session_ep()->manage(this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,18 +141,6 @@ namespace Kernel
|
||||||
return unmanaged_singleton<Core_pd>(table, slab);
|
return unmanaged_singleton<Core_pd>(table, slab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return wether interrupt 'irq' is private to the kernel
|
|
||||||
*/
|
|
||||||
bool private_interrupt(unsigned const irq)
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < NR_OF_CPUS; i++)
|
|
||||||
if (irq == Timer::interrupt_id(i)) return true;
|
|
||||||
if (irq == Pic::IPI) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get attributes of the mode transition region in every PD
|
* Get attributes of the mode transition region in every PD
|
||||||
*/
|
*/
|
||||||
|
@ -260,12 +248,6 @@ void init_kernel_mp_primary()
|
||||||
t.init(cpu_pool()->primary_cpu(), core_pd(),
|
t.init(cpu_pool()->primary_cpu(), core_pd(),
|
||||||
(Native_utcb*)Genode::UTCB_MAIN_THREAD, 1);
|
(Native_utcb*)Genode::UTCB_MAIN_THREAD, 1);
|
||||||
|
|
||||||
/* initialize user interrupt objects */
|
|
||||||
static Genode::uint8_t _irqs[Kernel::Pic::NR_OF_IRQ * sizeof(User_irq)];
|
|
||||||
for (unsigned i = 0; i < Kernel::Pic::NR_OF_IRQ; i++) {
|
|
||||||
if (private_interrupt(i)) { continue; }
|
|
||||||
new (&_irqs[i * sizeof(User_irq)]) User_irq(i);
|
|
||||||
}
|
|
||||||
/* kernel initialization finished */
|
/* kernel initialization finished */
|
||||||
Genode::printf("kernel initialized\n");
|
Genode::printf("kernel initialized\n");
|
||||||
test();
|
test();
|
||||||
|
|
|
@ -688,6 +688,14 @@ void Thread::_call_delete_signal_receiver() {
|
||||||
reinterpret_cast<Signal_receiver*>(user_arg_1())->~Signal_receiver(); }
|
reinterpret_cast<Signal_receiver*>(user_arg_1())->~Signal_receiver(); }
|
||||||
|
|
||||||
|
|
||||||
|
void Thread::_call_new_irq() {
|
||||||
|
new ((void *)user_arg_1()) User_irq(user_arg_2()); }
|
||||||
|
|
||||||
|
|
||||||
|
void Thread::_call_delete_irq() {
|
||||||
|
reinterpret_cast<User_irq*>(user_arg_1())->~User_irq(); }
|
||||||
|
|
||||||
|
|
||||||
int Thread::_read_reg(addr_t const id, addr_t & value) const
|
int Thread::_read_reg(addr_t const id, addr_t & value) const
|
||||||
{
|
{
|
||||||
addr_t Thread::* const reg = _reg(id);
|
addr_t Thread::* const reg = _reg(id);
|
||||||
|
@ -762,6 +770,8 @@ void Thread::_call()
|
||||||
case call_id_run_vm(): _call_run_vm(); return;
|
case call_id_run_vm(): _call_run_vm(); return;
|
||||||
case call_id_pause_vm(): _call_pause_vm(); return;
|
case call_id_pause_vm(): _call_pause_vm(); return;
|
||||||
case call_id_pause_thread(): _call_pause_thread(); return;
|
case call_id_pause_thread(): _call_pause_thread(); return;
|
||||||
|
case call_id_new_irq(): _call_new_irq(); return;
|
||||||
|
case call_id_delete_irq(): _call_delete_irq(); return;
|
||||||
default:
|
default:
|
||||||
PWRN("%s -> %s: unknown kernel call", pd_label(), label());
|
PWRN("%s -> %s: unknown kernel call", pd_label(), label());
|
||||||
_stop();
|
_stop();
|
||||||
|
|
|
@ -150,9 +150,12 @@ Platform::Platform()
|
||||||
|
|
||||||
_init_io_port_alloc();
|
_init_io_port_alloc();
|
||||||
|
|
||||||
/* make interrupts available to the interrupt allocator */
|
/* make all non-kernel interrupts available to the interrupt allocator */
|
||||||
for (unsigned i = 0; i < Kernel::Pic::NR_OF_IRQ; i++)
|
for (unsigned i = 0; i < Kernel::Pic::NR_OF_IRQ; i++) {
|
||||||
|
if (i == Timer::interrupt_id(i) || i == Pic::IPI)
|
||||||
|
continue;
|
||||||
_irq_alloc.add_range(i, 1);
|
_irq_alloc.add_range(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use byte granuarity for MMIO regions because on some platforms, devices
|
* Use byte granuarity for MMIO regions because on some platforms, devices
|
||||||
|
|
|
@ -25,6 +25,7 @@ void Pic::_init()
|
||||||
for (unsigned i = min_spi; i <= _max_irq; i++) {
|
for (unsigned i = min_spi; i <= _max_irq; i++) {
|
||||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||||
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
||||||
|
_distr.write<Distr::Icenabler::Clear_enable>(1, i);
|
||||||
}
|
}
|
||||||
/* enable device */
|
/* enable device */
|
||||||
_distr.write<Distr::Ctlr::Enable>(1);
|
_distr.write<Distr::Ctlr::Enable>(1);
|
||||||
|
|
|
@ -27,6 +27,7 @@ void Pic::_init()
|
||||||
_distr.write<Distr::Igroupr::Group_status>(1, i);
|
_distr.write<Distr::Igroupr::Group_status>(1, i);
|
||||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||||
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
||||||
|
_distr.write<Distr::Icenabler::Clear_enable>(1, i);
|
||||||
}
|
}
|
||||||
/* enable device */
|
/* enable device */
|
||||||
Distr::Ctlr::access_t v = 0;
|
Distr::Ctlr::access_t v = 0;
|
||||||
|
|
Loading…
Reference in New Issue