mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
hw: add CPU re-init/resume support
On resume the CPU state must be re-initialized, since all CPUs have been potentially off (depending on sleep form) and lost state. Handle the halt and suspend state explicitly by an extra Job implementation which can be executed without holding the global kernel lock. Issue #4669
This commit is contained in:
parent
a20a26b41b
commit
1b5bfec8f9
@ -145,6 +145,9 @@ Cpu_job & Cpu::schedule()
|
||||
Job & old_job = scheduled_job();
|
||||
old_job.exception(*this);
|
||||
|
||||
if (_state == SUSPEND || _state == HALT)
|
||||
return _halt_job;
|
||||
|
||||
if (_scheduler.need_to_schedule()) {
|
||||
_timer.process_timeouts();
|
||||
_scheduler.update(_timer.time());
|
||||
|
@ -109,7 +109,20 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
Pd &core_pd);
|
||||
};
|
||||
|
||||
struct Halt_job : Job
|
||||
{
|
||||
Halt_job() : Job (0, 0) { }
|
||||
|
||||
void exception(Kernel::Cpu &) override { }
|
||||
|
||||
void proceed(Kernel::Cpu &) override;
|
||||
|
||||
Kernel::Cpu_job* helping_destination() override { return this; }
|
||||
} _halt_job { };
|
||||
|
||||
enum State { RUN, HALT, SUSPEND };
|
||||
|
||||
State _state { RUN };
|
||||
unsigned const _id;
|
||||
Board::Pic _pic;
|
||||
Timer _timer;
|
||||
@ -126,6 +139,11 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
|
||||
public:
|
||||
|
||||
void next_state_halt() { _state = HALT; };
|
||||
void next_state_suspend() { _state = SUSPEND; };
|
||||
|
||||
State state() { return _state; }
|
||||
|
||||
enum { KERNEL_STACK_SIZE = 16 * 1024 * sizeof(Genode::addr_t) };
|
||||
|
||||
/**
|
||||
@ -186,6 +204,12 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
* Return CPU's idle thread object
|
||||
*/
|
||||
Kernel::Thread &idle_thread() { return _idle; }
|
||||
|
||||
void reinit_cpu()
|
||||
{
|
||||
_arch_init();
|
||||
_state = RUN;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -213,6 +237,12 @@ class Kernel::Cpu_pool
|
||||
Pd &core_pd,
|
||||
Board::Global_interrupt_controller &global_irq_ctrl);
|
||||
|
||||
/**
|
||||
* Return whether CPU object is valid and is constructed.
|
||||
*/
|
||||
bool cpu_valid(unsigned const id) const {
|
||||
return id < _nr_of_cpus && _cpus[id].constructed(); }
|
||||
|
||||
/**
|
||||
* Return object of CPU 'id'
|
||||
*/
|
||||
|
@ -134,6 +134,33 @@ void Kernel::main_initialize_and_handle_kernel_entry()
|
||||
while (!instance_initialized) { }
|
||||
}
|
||||
|
||||
if (Main::_instance->_cpu_pool.cpu_valid(Cpu::executing_id())) {
|
||||
/* the CPU resumed since the cpu object is already valid */
|
||||
{
|
||||
Lock::Guard guard(Main::_instance->_data_lock);
|
||||
|
||||
if (kernel_initialized) {
|
||||
nr_of_initialized_cpus = 0;
|
||||
kernel_initialized = false;
|
||||
}
|
||||
|
||||
nr_of_initialized_cpus ++;
|
||||
|
||||
Main::_instance->_cpu_pool.cpu(Cpu::executing_id()).reinit_cpu();
|
||||
|
||||
if (nr_of_initialized_cpus == nr_of_cpus) {
|
||||
kernel_initialized = true;
|
||||
Genode::raw("kernel resumed");
|
||||
}
|
||||
}
|
||||
|
||||
while (!kernel_initialized) { }
|
||||
|
||||
Main::_instance->_handle_kernel_entry();
|
||||
/* never reached */
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
/**
|
||||
* Let each CPU initialize its corresponding CPU object in the
|
||||
|
@ -68,6 +68,9 @@ void Kernel::Thread::Tlb_invalidation::execute(Cpu &) { }
|
||||
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
|
||||
|
||||
|
||||
void Cpu::Halt_job::proceed(Kernel::Cpu &) { }
|
||||
|
||||
|
||||
void Thread::proceed(Cpu & cpu)
|
||||
{
|
||||
if (!cpu.active(pd().mmu_regs) && type() != CORE)
|
||||
|
@ -88,6 +88,9 @@ void Kernel::Thread::Tlb_invalidation::execute(Cpu &) { }
|
||||
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
|
||||
|
||||
|
||||
void Cpu::Halt_job::proceed(Kernel::Cpu &) { }
|
||||
|
||||
|
||||
bool Kernel::Pd::invalidate_tlb(Cpu & cpu, addr_t addr, size_t size)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
@ -25,6 +25,9 @@ void Thread::Tlb_invalidation::execute(Cpu &) { }
|
||||
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
|
||||
|
||||
|
||||
void Cpu::Halt_job::proceed(Kernel::Cpu &) { }
|
||||
|
||||
|
||||
void Thread::exception(Cpu & cpu)
|
||||
{
|
||||
using Context = Genode::Cpu::Context;
|
||||
|
@ -35,6 +35,9 @@ void Kernel::Thread::Tlb_invalidation::execute(Cpu &)
|
||||
void Kernel::Thread::Flush_and_stop_cpu::execute(Cpu &) { }
|
||||
|
||||
|
||||
void Kernel::Cpu::Halt_job::proceed(Kernel::Cpu &) { }
|
||||
|
||||
|
||||
void Kernel::Thread::_call_cache_coherent_region() { }
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user