base-hw: global IRQ pool as Main member

Let the global kernel IRQ-pool be a member of the one Kernel::Main object
instead of having it as global static variable.

Ref #4217
This commit is contained in:
Martin Stein 2021-07-13 16:37:00 +02:00 committed by Norman Feske
parent c49db16762
commit 5dd8ee5840
17 changed files with 85 additions and 73 deletions

View File

@ -46,22 +46,22 @@ void Cpu_job::_yield()
}
void Cpu_job::_interrupt(unsigned const /* cpu_id */)
void Cpu_job::_interrupt(Irq::Pool &user_irq_pool, unsigned const /* cpu_id */)
{
/* determine handling for specific interrupt */
/* let the IRQ controller take a pending IRQ for handling, if any */
unsigned irq_id;
if (_cpu->pic().take_request(irq_id))
/* is the interrupt a cpu-local one */
if (!_cpu->interrupt(irq_id)) {
/* let the CPU of this job handle the IRQ if it is a CPU-local one */
if (!_cpu->handle_if_cpu_local_interrupt(irq_id)) {
/* it needs to be a user interrupt */
User_irq * irq = User_irq::object(irq_id);
/* it isn't a CPU-local IRQ, so, it must be a user IRQ */
User_irq * irq = User_irq::object(user_irq_pool, irq_id);
if (irq) irq->occurred();
else Genode::raw("Unknown interrupt ", irq_id);
}
/* end interrupt request at controller */
/* let the IRQ controller finish the currently taken IRQ */
_cpu->pic().finish_request();
}
@ -104,10 +104,11 @@ Cpu_job::~Cpu_job()
extern "C" void idle_thread_main(void);
Cpu::Idle_thread::Idle_thread(Cpu_pool &cpu_pool,
Cpu &cpu)
Cpu::Idle_thread::Idle_thread(Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool,
Cpu &cpu)
:
Thread { cpu_pool, "idle" }
Thread { user_irq_pool, cpu_pool, "idle" }
{
regs->ip = (addr_t)&idle_thread_main;
@ -129,7 +130,7 @@ void Cpu::schedule(Job * const job)
}
bool Cpu::interrupt(unsigned const irq_id)
bool Cpu::handle_if_cpu_local_interrupt(unsigned const irq_id)
{
Irq * const irq = object(irq_id);
@ -173,12 +174,13 @@ addr_t Cpu::stack_start()
Cpu::Cpu(unsigned const id,
Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool)
:
_id { id },
_timer { *this },
_scheduler { _idle, _quota(), _fill() },
_idle { cpu_pool, *this },
_idle { user_irq_pool, cpu_pool, *this },
_ipi_irq { *this },
_global_work_list { cpu_pool.work_list() }
{
@ -190,10 +192,10 @@ Cpu::Cpu(unsigned const id,
** Cpu_pool **
**************/
void Cpu_pool::initialize_executing_cpu()
void Cpu_pool::initialize_executing_cpu(Irq::Pool &user_irq_pool)
{
unsigned id = Cpu::executing_id();
_cpus[id].construct(id, *this);
_cpus[id].construct(id, user_irq_pool, *this);
}

View File

@ -102,8 +102,9 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
/**
* Construct idle context for CPU 'cpu'
*/
Idle_thread(Cpu_pool &cpu_pool,
Cpu &cpu);
Idle_thread(Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool,
Cpu &cpu);
};
@ -129,6 +130,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
* Construct object for CPU 'id'
*/
Cpu(unsigned const id,
Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool);
static inline unsigned primary_id() { return 0; }
@ -144,7 +146,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
* \param irq_id id of the interrupt that occured
* \returns true if the interrupt belongs to this CPU, otherwise false
*/
bool interrupt(unsigned const irq_id);
bool handle_if_cpu_local_interrupt(unsigned const irq_id);
/**
* Schedule 'job' at this CPU
@ -200,7 +202,7 @@ class Kernel::Cpu_pool
Cpu_pool(unsigned nr_of_cpus);
void initialize_executing_cpu();
void initialize_executing_cpu(Irq::Pool &user_irq_pool);
/**
* Return object of CPU 'id'

View File

@ -51,7 +51,7 @@ class Kernel::Cpu_job : private Cpu_share
/**
* Handle interrupt exception that occured during execution on CPU 'id'
*/
void _interrupt(unsigned const id);
void _interrupt(Irq::Pool &user_irq_pool, unsigned const id);
/**
* Activate our own CPU-share

View File

@ -29,20 +29,14 @@ void Kernel::Irq::enable() const
}
Kernel::Irq::Pool &Kernel::User_irq::_pool()
{
static Irq::Pool p;
return p;
}
Kernel::User_irq::User_irq(unsigned const irq,
Genode::Irq_session::Trigger trigger,
Genode::Irq_session::Polarity polarity,
Signal_context &context,
Board::Pic &pic)
Board::Pic &pic,
Irq::Pool &user_irq_pool)
:
Irq { irq, _pool(), pic },
Irq { irq, user_irq_pool, pic },
_context { context }
{
disable();

View File

@ -71,7 +71,7 @@ class Kernel::Irq : Genode::Avl_node<Irq>
protected:
unsigned _irq_nr; /* kernel name of the interrupt */
Pool &_pool;
Pool &_irq_pool;
Board::Pic &_pic;
public:
@ -83,17 +83,17 @@ class Kernel::Irq : Genode::Avl_node<Irq>
* \param pool pool this interrupt shall belong to
*/
Irq(unsigned const irq,
Pool &pool,
Pool &irq_pool,
Board::Pic &pic)
:
_irq_nr { irq },
_pool { pool },
_pic { pic }
_irq_nr { irq },
_irq_pool { irq_pool },
_pic { pic }
{
_pool.insert(this);
_irq_pool.insert(this);
}
virtual ~Irq() { _pool.remove(this); }
virtual ~Irq() { _irq_pool.remove(this); }
/**
* Handle occurence of the interrupt
@ -139,11 +139,6 @@ class Kernel::User_irq : public Kernel::Irq
Kernel::Object _kernel_object { *this };
Signal_context &_context;
/**
* Get map that provides all user interrupts by their kernel names
*/
static Irq::Pool &_pool();
public:
/**
@ -153,7 +148,8 @@ class Kernel::User_irq : public Kernel::Irq
Genode::Irq_session::Trigger trigger,
Genode::Irq_session::Polarity polarity,
Signal_context &context,
Board::Pic &pic);
Board::Pic &pic,
Irq::Pool &user_irq_pool);
/**
* Destructor
@ -174,8 +170,8 @@ class Kernel::User_irq : public Kernel::Irq
/**
* Handle occurence of interrupt 'irq'
*/
static User_irq * object(unsigned const irq) {
return dynamic_cast<User_irq*>(_pool().object(irq)); }
static User_irq * object(Irq::Pool &user_irq_pool, unsigned const irq) {
return dynamic_cast<User_irq*>(user_irq_pool.object(irq)); }
/**
* Syscall to create user irq object

View File

@ -42,6 +42,7 @@ class Kernel::Main
Lock _data_lock { };
Cpu_pool _cpu_pool;
Irq::Pool _user_irq_pool { };
Genode::Constructible<Core_main_thread> _core_main_thread { };
void _handle_kernel_entry();
@ -119,7 +120,9 @@ void Kernel::main_initialize_and_handle_kernel_entry()
*/
Lock::Guard guard(Main::_instance->_data_lock);
instance_initialized = true;
Main::_instance->_cpu_pool.initialize_executing_cpu();
Main::_instance->_cpu_pool.initialize_executing_cpu(
Main::_instance->_user_irq_pool);
nr_of_initialized_cpus++;
};
@ -144,6 +147,7 @@ void Kernel::main_initialize_and_handle_kernel_entry()
boot_info.kernel_irqs.add((unsigned)Board::Pic::IPI);
Main::_instance->_core_main_thread.construct(
Main::_instance->_user_irq_pool,
Main::_instance->_cpu_pool);
boot_info.core_main_thread_utcb =

View File

@ -660,7 +660,7 @@ void Thread::_call_new_irq()
_call_new<User_irq>(
(unsigned)user_arg_2(), trigger, polarity, *c,
_cpu_pool.executing_cpu().pic());
_cpu_pool.executing_cpu().pic(), _user_irq_pool);
}
@ -774,12 +774,13 @@ void Thread::_call()
/* switch over kernel calls that are restricted to core */
switch (call_id) {
case call_id_new_thread():
_call_new<Thread>(_cpu_pool, (unsigned) user_arg_2(),
_call_new<Thread>(_user_irq_pool, _cpu_pool, (unsigned) user_arg_2(),
(unsigned) _core_to_kernel_quota(user_arg_3()),
(char const *) user_arg_4());
return;
case call_id_new_core_thread():
_call_new<Thread>(_cpu_pool, (char const *) user_arg_2());
_call_new<Thread>(_user_irq_pool, _cpu_pool,
(char const *) user_arg_2());
return;
case call_id_thread_quota(): _call_thread_quota(); return;
case call_id_delete_thread(): _call_delete_thread(); return;
@ -836,7 +837,8 @@ void Thread::_mmu_exception()
}
Thread::Thread(Cpu_pool &cpu_pool,
Thread::Thread(Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool,
unsigned const priority,
unsigned const quota,
char const *const label,
@ -844,6 +846,7 @@ Thread::Thread(Cpu_pool &cpu_pool,
:
Kernel::Object { *this },
Cpu_job { priority, quota },
_user_irq_pool { user_irq_pool },
_cpu_pool { cpu_pool },
_ipc_node { *this },
_state { AWAITS_START },
@ -871,9 +874,9 @@ Genode::uint8_t __initial_stack_base[DEFAULT_STACK_SIZE];
** Core_main_thread **
**********************/
Core_main_thread::Core_main_thread(Cpu_pool &cpu_pool)
Core_main_thread::Core_main_thread(Irq::Pool &user_irq_pool, Cpu_pool &cpu_pool)
:
Core_object<Thread>(cpu_pool, "core")
Core_object<Thread>(user_irq_pool, cpu_pool, "core")
{
using namespace Genode;

View File

@ -131,6 +131,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
enum { MAX_RCV_CAPS = Genode::Msgbuf_base::MAX_CAPS_PER_MSG };
Irq::Pool &_user_irq_pool;
Cpu_pool &_cpu_pool;
void *_obj_id_ref_ptr[MAX_RCV_CAPS] { nullptr };
Ipc_node _ipc_node;
@ -292,7 +293,8 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
* \param label debugging label
* \param core whether it is a core thread or not
*/
Thread(Cpu_pool &cpu_pool,
Thread(Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool,
unsigned const priority,
unsigned const quota,
char const *const label,
@ -303,10 +305,11 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
*
* \param label debugging label
*/
Thread(Cpu_pool &cpu_pool,
Thread(Irq::Pool &user_irq_pool,
Cpu_pool &cpu_pool,
char const *const label)
:
Thread(cpu_pool, Cpu_priority::min(), 0, label, true)
Thread(user_irq_pool, cpu_pool, Cpu_priority::min(), 0, label, true)
{ }
~Thread();
@ -440,7 +443,7 @@ class Kernel::Core_main_thread : public Core_object<Kernel::Thread>
{
public:
Core_main_thread(Cpu_pool &cpu_pool);
Core_main_thread(Irq::Pool &user_irq_pool, Cpu_pool &cpu_pool);
};
#endif /* _CORE__KERNEL__THREAD_H_ */

View File

@ -55,6 +55,7 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job
enum Scheduler_state { ACTIVE, INACTIVE };
Irq::Pool & _user_irq_pool;
Object _kernel_object { *this };
State & _state;
Signal_context & _context;
@ -71,10 +72,11 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job
* \param state initial CPU state
* \param context signal for VM exceptions other than interrupts
*/
Vm(Cpu & cpu,
State & state,
Signal_context & context,
Identity & id);
Vm(Irq::Pool & user_irq_pool,
Cpu & cpu,
Genode::Vm_state & state,
Kernel::Signal_context & context,
Identity & id);
/**
* Inject an interrupt to this VM

View File

@ -25,7 +25,7 @@ void Kernel::Thread::_call_new_vm()
return;
}
_call_new<Vm>(_cpu_pool.cpu((unsigned)user_arg_2()),
_call_new<Vm>(_user_irq_pool, _cpu_pool.cpu((unsigned)user_arg_2()),
*(Board::Vm_state*)user_arg_3(),
*context, *(Vm::Identity*)user_arg_4());
}

View File

@ -37,7 +37,7 @@ void Thread::exception(Cpu & cpu)
return;
case Cpu::Context::INTERRUPT_REQUEST:
case Cpu::Context::FAST_INTERRUPT_REQUEST:
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
return;
case Cpu::Context::UNDEFINED_INSTRUCTION:
Genode::raw(*this, ": undefined instruction at ip=",

View File

@ -20,13 +20,15 @@
using namespace Kernel;
Kernel::Vm::Vm(Cpu & cpu,
Genode::Vm_state & state,
Kernel::Signal_context & context,
Identity & id)
Vm::Vm(Irq::Pool & user_irq_pool,
Cpu & cpu,
Genode::Vm_state & state,
Kernel::Signal_context & context,
Identity & id)
:
Kernel::Object { *this },
Cpu_job(Cpu_priority::min(), 0),
_user_irq_pool(user_irq_pool),
_state(state),
_context(context),
_id(id),
@ -41,7 +43,7 @@ void Vm::exception(Cpu & cpu)
switch(_state.cpu_exception) {
case Genode::Cpu_state::INTERRUPT_REQUEST: [[fallthrough]];
case Genode::Cpu_state::FAST_INTERRUPT_REQUEST:
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
return;
case Genode::Cpu_state::DATA_ABORT:
_state.dfar = Cpu::Dfar::read();

View File

@ -134,13 +134,15 @@ void Board::Vcpu_context::Virtual_timer_irq::disable()
}
Kernel::Vm::Vm(Cpu & cpu,
Kernel::Vm::Vm(Irq::Pool & user_irq_pool,
Cpu & cpu,
Genode::Vm_state & state,
Kernel::Signal_context & context,
Identity & id)
:
Kernel::Object { *this },
Cpu_job(Cpu_priority::min(), 0),
_user_irq_pool(user_irq_pool),
_state(state),
_context(context),
_id(id),
@ -155,7 +157,7 @@ void Kernel::Vm::exception(Cpu & cpu)
switch(_state.cpu_exception) {
case Genode::Cpu_state::INTERRUPT_REQUEST:
case Genode::Cpu_state::FAST_INTERRUPT_REQUEST:
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
break;
default:
pause();

View File

@ -33,7 +33,7 @@ void Thread::exception(Cpu & cpu)
case Cpu::IRQ_LEVEL_EL1: [[fallthrough]];
case Cpu::FIQ_LEVEL_EL0: [[fallthrough]];
case Cpu::FIQ_LEVEL_EL1:
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
return;
case Cpu::SYNC_LEVEL_EL0: [[fallthrough]];
case Cpu::SYNC_LEVEL_EL1:

View File

@ -109,13 +109,15 @@ void Board::Vcpu_context::Virtual_timer_irq::disable()
}
Vm::Vm(Cpu & cpu,
Vm::Vm(Irq::Pool & user_irq_pool,
Cpu & cpu,
Genode::Vm_state & state,
Kernel::Signal_context & context,
Identity & id)
:
Kernel::Object { *this },
Cpu_job(Cpu_priority::min(), 0),
_user_irq_pool(user_irq_pool),
_state(state),
_context(context),
_id(id),
@ -159,7 +161,7 @@ void Vm::exception(Cpu & cpu)
case Cpu::IRQ_LEVEL_EL1: [[fallthrough]];
case Cpu::FIQ_LEVEL_EL0: [[fallthrough]];
case Cpu::FIQ_LEVEL_EL1:
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
break;
case Cpu::SYNC_LEVEL_EL0: [[fallthrough]];
case Cpu::SYNC_LEVEL_EL1: [[fallthrough]];

View File

@ -30,10 +30,10 @@ void Thread::exception(Cpu & cpu)
if (regs->is_irq()) {
/* cpu-local timer interrupt */
if (regs->irq() == cpu.timer().interrupt_id()) {
cpu.interrupt(cpu.timer().interrupt_id());
cpu.handle_if_cpu_local_interrupt(cpu.timer().interrupt_id());
} else {
/* interrupt controller */
_interrupt(0);
_interrupt(_user_irq_pool, 0);
}
return;
}

View File

@ -42,7 +42,7 @@ void Thread::exception(Cpu & cpu)
if (regs->trapno >= Cpu_state::INTERRUPTS_START &&
regs->trapno <= Cpu_state::INTERRUPTS_END) {
_interrupt(cpu.id());
_interrupt(_user_irq_pool, cpu.id());
return;
}