hw: add IPI type to flush and stop CPUs

as preparation before powering off the CPU

Issue #4669
This commit is contained in:
Alexander Boettcher 2023-02-10 14:14:51 +01:00 committed by Christian Helmuth
parent 80453236c4
commit a20a26b41b
12 changed files with 83 additions and 18 deletions

View File

@ -19,12 +19,12 @@ using namespace Kernel;
void Cpu::Ipi::occurred()
{
/* lambda to iterate over a work-list and execute all work items */
auto iterate = [] (Genode::List<Genode::List_element<Inter_processor_work>> & li) {
auto iterate = [&] (Genode::List<Genode::List_element<Inter_processor_work>> & li) {
Genode::List_element<Inter_processor_work> const *e = li.first();
Genode::List_element<Inter_processor_work> const *next = nullptr;
for ( ; e; e = next) {
next = e->next();
e->object()->execute();
e->object()->execute(cpu);
}
};

View File

@ -32,7 +32,7 @@ class Kernel::Inter_processor_work : Genode::Interface
{
public:
virtual void execute() = 0;
virtual void execute(Cpu &) = 0;
protected:

View File

@ -169,7 +169,7 @@ Thread::Destroy::Destroy(Thread & caller, Genode::Kernel_object<Thread> & to_del
void
Thread::Destroy::execute()
Thread::Destroy::execute(Cpu &)
{
thread_to_destroy->_cpu->work_list().remove(&_le);
thread_to_destroy.destruct();

View File

@ -92,7 +92,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
** Inter_processor_work interface **
************************************/
void execute() override;
void execute(Cpu &) override;
};
/**
@ -112,11 +112,40 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
** Inter_processor_work interface **
************************************/
void execute() override;
void execute(Cpu &) override;
};
friend void Tlb_invalidation::execute();
friend void Destroy::execute();
/**
* Flush and stop CPU, e.g. before suspending or powering off the CPU
*/
struct Flush_and_stop_cpu : Inter_processor_work
{
Inter_processor_work_list &global_work_list;
unsigned cpus_left;
Hw::Suspend_type suspend;
Flush_and_stop_cpu(Inter_processor_work_list &global_work_list,
unsigned cpus, Hw::Suspend_type suspend)
:
global_work_list(global_work_list),
cpus_left(cpus),
suspend(suspend)
{
global_work_list.insert(&_le);
}
~Flush_and_stop_cpu() { global_work_list.remove(&_le); }
/************************************
** Inter_processor_work interface **
************************************/
void execute(Cpu &) override;
};
friend void Tlb_invalidation::execute(Cpu &);
friend void Destroy::execute(Cpu &);
friend void Flush_and_stop_cpu::execute(Cpu &);
protected:
@ -157,6 +186,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
Genode::Constructible<Tlb_invalidation> _tlb_invalidation {};
Genode::Constructible<Destroy> _destroy {};
Genode::Constructible<Flush_and_stop_cpu> _stop_cpu {};
/**
* Notice that another thread yielded the CPU to this thread

View File

@ -62,7 +62,10 @@ void Thread::exception(Cpu & cpu)
* coprocessor registers (there might be ARM SoCs where this is not valid,
* with several shareability domains, but until now we do not support them)
*/
void Kernel::Thread::Tlb_invalidation::execute() { };
void Kernel::Thread::Tlb_invalidation::execute(Cpu &) { }
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
void Thread::proceed(Cpu & cpu)

View File

@ -82,7 +82,10 @@ void Thread::exception(Cpu & cpu)
* coprocessor registers (there might be ARM SoCs where this is not valid,
* with several shareability domains, but until now we do not support them)
*/
void Kernel::Thread::Tlb_invalidation::execute() { };
void Kernel::Thread::Tlb_invalidation::execute(Cpu &) { }
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
bool Kernel::Pd::invalidate_tlb(Cpu & cpu, addr_t addr, size_t size)

View File

@ -19,7 +19,10 @@
using namespace Kernel;
void Thread::Tlb_invalidation::execute() {}
void Thread::Tlb_invalidation::execute(Cpu &) { }
void Thread::Flush_and_stop_cpu::execute(Cpu &) { }
void Thread::exception(Cpu & cpu)

View File

@ -19,7 +19,7 @@
#include <kernel/pd.h>
void Kernel::Thread::Tlb_invalidation::execute()
void Kernel::Thread::Tlb_invalidation::execute(Cpu &)
{
/* invalidate cpu-local TLB */
Cpu::invalidate_tlb();
@ -32,6 +32,9 @@ void Kernel::Thread::Tlb_invalidation::execute()
};
void Kernel::Thread::Flush_and_stop_cpu::execute(Cpu &) { }
void Kernel::Thread::_call_cache_coherent_region() { }

View File

@ -16,7 +16,10 @@
#include <hw/spec/arm/register_macros.h>
namespace Hw { struct Arm_cpu; }
namespace Hw { struct Arm_cpu; struct Suspend_type; }
struct Hw::Suspend_type { };
struct Hw::Arm_cpu

View File

@ -31,7 +31,10 @@
};
namespace Hw { struct Arm_64_cpu; }
namespace Hw { struct Arm_64_cpu; struct Suspend_type; }
struct Hw::Suspend_type { };
struct Hw::Arm_64_cpu

View File

@ -16,7 +16,10 @@
#include <hw/spec/riscv/register_macros.h>
namespace Hw { struct Riscv_cpu; }
namespace Hw { struct Riscv_cpu; struct Suspend_type; }
struct Hw::Suspend_type { };
struct Hw::Riscv_cpu

View File

@ -16,7 +16,19 @@
#include <hw/spec/x86_64/register_macros.h>
namespace Hw { struct X86_64_cpu; }
namespace Hw { struct X86_64_cpu; struct Suspend_type; }
/*
* The intended sleep state S0 ... S5. The values are read out by an
* ACPI AML component and are of type TYP_SLPx as described in the
* ACPI specification, e.g. TYP_SLPa and TYP_SLPb. The values differ
* between different PC systems/boards.
*/
struct Hw::Suspend_type {
Genode::uint8_t typ_a;
Genode::uint8_t typ_b;
};
struct Hw::X86_64_cpu
@ -95,6 +107,8 @@ struct Hw::X86_64_cpu
X86_64_CPUID_REGISTER(Cpuid_1_edx, 1, edx,
struct Pat : Bitfield<16, 1> { };
);
Suspend_type suspend;
};
#endif /* _SRC__LIB__HW__SPEC__X86_64__CPU_H_ */