base-hw: don't use boot_info() outside main.cc

It's sufficient to access the boot info only on kernel initialization time.
Therfore, it can remain completely hidden to the rest of the kernel inside
kernel/main.cc in the initialization function.

Ref #4217
This commit is contained in:
Martin Stein 2021-07-12 17:26:32 +02:00 committed by Norman Feske
parent b247def09a
commit c49db16762
3 changed files with 57 additions and 33 deletions

View File

@ -190,17 +190,16 @@ Cpu::Cpu(unsigned const id,
** Cpu_pool **
**************/
bool Cpu_pool::initialize()
void Cpu_pool::initialize_executing_cpu()
{
unsigned id = Cpu::executing_id();
_cpus[id].construct(id, *this);
return --_initialized == 0;
}
Cpu & Cpu_pool::cpu(unsigned const id)
{
assert(id < _count && _cpus[id].constructed());
assert(id < _nr_of_cpus && _cpus[id].constructed());
return *_cpus[id];
}
@ -208,7 +207,7 @@ Cpu & Cpu_pool::cpu(unsigned const id)
using Boot_info = Hw::Boot_info<Board::Boot_info>;
Cpu_pool::Cpu_pool()
Cpu_pool::Cpu_pool(unsigned nr_of_cpus)
:
_count(reinterpret_cast<Boot_info*>(Hw::Mm::boot_info().base)->cpus)
_nr_of_cpus(nr_of_cpus)
{ }

View File

@ -193,15 +193,14 @@ class Kernel::Cpu_pool
private:
Inter_processor_work_list _global_work_list {};
unsigned _count;
unsigned _initialized { _count };
unsigned _nr_of_cpus;
Genode::Constructible<Cpu> _cpus[NR_OF_CPUS];
public:
Cpu_pool();
Cpu_pool(unsigned nr_of_cpus);
bool initialize();
void initialize_executing_cpu();
/**
* Return object of CPU 'id'
@ -221,11 +220,13 @@ class Kernel::Cpu_pool
template <typename FUNC>
void for_each_cpu(FUNC const &func)
{
for (unsigned i = 0; i < _count; i++) func(cpu(i));
for (unsigned i = 0; i < _nr_of_cpus; i++) func(cpu(i));
}
Inter_processor_work_list & work_list() {
return _global_work_list; }
unsigned nr_of_cpus() { return _nr_of_cpus; }
};
#endif /* _CORE__KERNEL__CPU_H_ */

View File

@ -41,16 +41,24 @@ class Kernel::Main
static Main *_instance;
Lock _data_lock { };
Cpu_pool _cpu_pool { };
Cpu_pool _cpu_pool;
Genode::Constructible<Core_main_thread> _core_main_thread { };
void _handle_kernel_entry();
Main(unsigned nr_of_cpus);
};
Kernel::Main *Kernel::Main::_instance;
Kernel::Main::Main(unsigned nr_of_cpus)
:
_cpu_pool { nr_of_cpus }
{ }
void Kernel::Main::_handle_kernel_entry()
{
Cpu &cpu = _cpu_pool.cpu(Cpu::executing_id());
@ -74,11 +82,17 @@ void Kernel::main_handle_kernel_entry()
void Kernel::main_initialize_and_handle_kernel_entry()
{
static volatile bool instance_initialized = false;
static volatile bool pool_ready = false;
static volatile bool kernel_ready = false;
using Boot_info = Hw::Boot_info<Board::Boot_info>;
bool const primary_cpu { Cpu::executing_id() == Cpu::primary_id() };
static volatile bool instance_initialized { false };
static volatile unsigned nr_of_initialized_cpus { 0 };
static volatile bool kernel_initialized { false };
Boot_info &boot_info {
*reinterpret_cast<Boot_info*>(Hw::Mm::boot_info().base) };
unsigned const nr_of_cpus { boot_info.cpus };
bool const primary_cpu { Cpu::executing_id() == Cpu::primary_id() };
if (primary_cpu) {
@ -86,7 +100,7 @@ void Kernel::main_initialize_and_handle_kernel_entry()
* Let the primary CPU create a Main object and initialize the static
* reference to it.
*/
static Main instance { };
static Main instance { nr_of_cpus };
Main::_instance = &instance;
} else {
@ -99,43 +113,53 @@ void Kernel::main_initialize_and_handle_kernel_entry()
}
{
/**
* Let each CPU initialize its corresponding CPU object in the
* CPU pool.
*/
Lock::Guard guard(Main::_instance->_data_lock);
instance_initialized = true;
/* initialize current cpu */
pool_ready = Main::_instance->_cpu_pool.initialize();
Main::_instance->_cpu_pool.initialize_executing_cpu();
nr_of_initialized_cpus++;
};
/* wait until all cpus have initialized their corresponding cpu object */
while (!pool_ready) { ; }
/**
* Let all CPUs block until each CPU object in the CPU pool has been
* initialized by the corresponding CPU.
*/
while (nr_of_initialized_cpus < nr_of_cpus) { }
/* the boot-cpu initializes the rest of the kernel */
if (primary_cpu) {
Lock::Guard guard(Main::_instance->_data_lock);
using Boot_info = Hw::Boot_info<Board::Boot_info>;
Boot_info &boot_info {
*reinterpret_cast<Boot_info*>(Hw::Mm::boot_info().base) };
/**
* Let the primary CPU initialize the core main thread and finish
* initialization of the boot info.
*/
Lock::Guard guard(Main::_instance->_data_lock);
Main::_instance->_cpu_pool.for_each_cpu([&] (Kernel::Cpu &cpu) {
boot_info.kernel_irqs.add(cpu.timer().interrupt_id());
});
boot_info.kernel_irqs.add((unsigned)Board::Pic::IPI);
Genode::log("");
Genode::log("kernel initialized");
Main::_instance->_core_main_thread.construct(
Main::_instance->_cpu_pool);
boot_info.core_main_thread_utcb =
(addr_t)Main::_instance->_core_main_thread->utcb();
kernel_ready = true;
Genode::log("");
Genode::log("kernel initialized");
kernel_initialized = true;
} else {
/* secondary cpus spin until the kernel is initialized */
while (!kernel_ready) {;}
/**
* Let secondary CPUs block until the primary CPU has initialized the
* core main thread and finished initialization of the boot info.
*/
while (!kernel_initialized) {;}
}
Main::_instance->_handle_kernel_entry();