From c49db16762753a39bb6ad950ec1fcd9e393ce8e4 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 12 Jul 2021 17:26:32 +0200 Subject: [PATCH] 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 --- repos/base-hw/src/core/kernel/cpu.cc | 9 ++-- repos/base-hw/src/core/kernel/cpu.h | 11 +++-- repos/base-hw/src/core/kernel/main.cc | 70 ++++++++++++++++++--------- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 20e3833652..8335354b59 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -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; -Cpu_pool::Cpu_pool() +Cpu_pool::Cpu_pool(unsigned nr_of_cpus) : - _count(reinterpret_cast(Hw::Mm::boot_info().base)->cpus) + _nr_of_cpus(nr_of_cpus) { } diff --git a/repos/base-hw/src/core/kernel/cpu.h b/repos/base-hw/src/core/kernel/cpu.h index 2d960479ea..9508663d9e 100644 --- a/repos/base-hw/src/core/kernel/cpu.h +++ b/repos/base-hw/src/core/kernel/cpu.h @@ -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 _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 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_ */ diff --git a/repos/base-hw/src/core/kernel/main.cc b/repos/base-hw/src/core/kernel/main.cc index df1e45f338..25558eb530 100644 --- a/repos/base-hw/src/core/kernel/main.cc +++ b/repos/base-hw/src/core/kernel/main.cc @@ -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 { }; 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; - 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(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; - Boot_info &boot_info { - *reinterpret_cast(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();