mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
b32af4e0a4
commit
0188b08f6a
@ -31,10 +31,10 @@ namespace Genode
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator * const _irq_alloc;
|
||||
Irq_session_capability _cap;
|
||||
Irq_signal _signal;
|
||||
Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
|
||||
|
||||
public:
|
||||
|
||||
|
@ -24,6 +24,7 @@ namespace Kernel
|
||||
class Signal_receiver;
|
||||
class Signal_context;
|
||||
class Vm;
|
||||
class User_irq;
|
||||
|
||||
addr_t mode_transition_base();
|
||||
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_thread() { return 30; }
|
||||
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
|
||||
@ -346,6 +349,27 @@ namespace Kernel
|
||||
{
|
||||
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_ */
|
||||
|
@ -113,16 +113,6 @@ class Kernel::User_irq
|
||||
*/
|
||||
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 **
|
||||
@ -145,6 +135,16 @@ class Kernel::User_irq
|
||||
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
|
||||
*/
|
||||
@ -154,24 +154,6 @@ class Kernel::User_irq
|
||||
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
|
||||
*
|
||||
|
@ -237,6 +237,8 @@ class Kernel::Thread
|
||||
void _call_pause_vm();
|
||||
void _call_access_thread_regs();
|
||||
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()
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
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,
|
||||
Range_allocator * const irq_alloc,
|
||||
const char * const args)
|
||||
:
|
||||
_irq_alloc(irq_alloc)
|
||||
: _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;
|
||||
@ -70,8 +76,10 @@ Irq_session_component::Irq_session_component(Cap_session * const cap_session
|
||||
PERR("unavailable interrupt requested");
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
|
||||
/* make interrupt accessible */
|
||||
_irq_number = (unsigned)plat_irq_nr;
|
||||
_signal = Kernel::User_irq::signal(plat_irq_nr);
|
||||
new_irq((addr_t)&_kernel_object, 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));
|
||||
}
|
||||
|
@ -141,18 +141,6 @@ namespace Kernel
|
||||
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
|
||||
*/
|
||||
@ -260,12 +248,6 @@ void init_kernel_mp_primary()
|
||||
t.init(cpu_pool()->primary_cpu(), core_pd(),
|
||||
(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 */
|
||||
Genode::printf("kernel initialized\n");
|
||||
test();
|
||||
|
@ -688,6 +688,14 @@ void Thread::_call_delete_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
|
||||
{
|
||||
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_pause_vm(): _call_pause_vm(); 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:
|
||||
PWRN("%s -> %s: unknown kernel call", pd_label(), label());
|
||||
_stop();
|
||||
|
@ -150,9 +150,12 @@ Platform::Platform()
|
||||
|
||||
_init_io_port_alloc();
|
||||
|
||||
/* make interrupts available to the interrupt allocator */
|
||||
for (unsigned i = 0; i < Kernel::Pic::NR_OF_IRQ; i++)
|
||||
/* make all non-kernel interrupts available to the interrupt allocator */
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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++) {
|
||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
||||
_distr.write<Distr::Icenabler::Clear_enable>(1, i);
|
||||
}
|
||||
/* enable device */
|
||||
_distr.write<Distr::Ctlr::Enable>(1);
|
||||
|
@ -27,6 +27,7 @@ void Pic::_init()
|
||||
_distr.write<Distr::Igroupr::Group_status>(1, i);
|
||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
||||
_distr.write<Distr::Icenabler::Clear_enable>(1, i);
|
||||
}
|
||||
/* enable device */
|
||||
Distr::Ctlr::access_t v = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user