base-hw: introduce Kernel::Main class

This commit introduces the Kernel::Main class that replaces the former way of
initializing the kernel (former 'kernel_init' function) and calling the C++
kernel entry handler (former 'kernel' function). These two are now
'Main::initialize_and_handle_kernel_entry' and 'Main::handle_kernel_entry'.
Also reading the execution time of the idle threads was already moved to
'Main'. The one static Main instance is meant to successivly replace all the
global static objects of the base-hw kernel with data members of the Main
instance making the data model of the kernel much more comprehensible. The
instance and most of its interface are hidden in kernel/main.cc. There are only
rare cases where parts of the Main interface must be accessible from the
outside. This should be done in the most specific way possible (see main.h)
and, if possible, without handing out references to Main data members or the
Main instance itself.

Ref #4217
This commit is contained in:
Martin Stein 2021-07-05 15:47:24 +02:00 committed by Norman Feske
parent 9de43a48b6
commit 82cf31ac27
18 changed files with 179 additions and 138 deletions

View File

@ -54,7 +54,7 @@ SRC_CC += kernel/cpu_scheduler.cc
SRC_CC += kernel/init.cc
SRC_CC += kernel/ipc_node.cc
SRC_CC += kernel/irq.cc
SRC_CC += kernel/kernel.cc
SRC_CC += kernel/main.cc
SRC_CC += kernel/object.cc
SRC_CC += kernel/signal_receiver.cc
SRC_CC += kernel/thread.cc

View File

@ -14,13 +14,7 @@
/* core includes */
#include <kernel/pd.h>
#include <kernel/cpu.h>
#include <kernel/kernel.h>
#include <kernel/lock.h>
#include <platform_pd.h>
#include <board.h>
#include <platform_thread.h>
#include <hw/boot_info.h>
/* base includes */
#include <base/internal/unmanaged_singleton.h>
@ -34,62 +28,3 @@ static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t),
Pd &Kernel::core_pd() {
return unmanaged_singleton<Genode::Core_platform_pd>()->kernel_pd(); }
extern "C" void kernel_init();
/**
* Setup kernel environment
*/
extern "C" void kernel_init()
{
static volatile bool lock_ready = false;
static volatile bool pool_ready = false;
static volatile bool kernel_ready = false;
/**
* It is essential to guard the initialization of the data_lock object
* in the SMP case, because otherwise the __cxa_guard_aquire of the cxx
* library contention path might get called, which ends up in
* calling a Semaphore, which will call Kernel::stop_thread() or
* Kernel::yield() system-calls in this code
*/
while (Cpu::executing_id() != Cpu::primary_id() && !lock_ready) { ; }
{
Lock::Guard guard(data_lock());
lock_ready = true;
/* initialize current cpu */
pool_ready = cpu_pool().initialize();
};
/* wait until all cpus have initialized their corresponding cpu object */
while (!pool_ready) { ; }
/* the boot-cpu initializes the rest of the kernel */
if (Cpu::executing_id() == Cpu::primary_id()) {
Lock::Guard guard(data_lock());
using Boot_info = Hw::Boot_info<Board::Boot_info>;
Boot_info &boot_info {
*reinterpret_cast<Boot_info*>(Hw::Mm::boot_info().base) };
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");
Core_main_thread::singleton();
kernel_ready = true;
} else {
/* secondary cpus spin until the kernel is initialized */
while (!kernel_ready) {;}
}
kernel();
}

View File

@ -1,46 +0,0 @@
/*
* \brief Kernel entrypoint
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2011-10-20
*/
/*
* Copyright (C) 2011-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* core includes */
#include <kernel/cpu.h>
#include <kernel/lock.h>
#include <kernel/kernel.h>
namespace Kernel {
time_t read_idle_thread_execution_time(unsigned cpu_idx);
}
Kernel::time_t Kernel::read_idle_thread_execution_time(unsigned cpu_idx)
{
return cpu_pool().cpu(cpu_idx).idle_thread().execution_time();
}
extern "C" void kernel()
{
using namespace Kernel;
Cpu &cpu = cpu_pool().cpu(Cpu::executing_id());
Cpu_job * new_job;
{
Lock::Guard guard(data_lock());
new_job = &cpu.schedule();
}
new_job->proceed(cpu);
}

View File

@ -15,12 +15,6 @@
#ifndef _CORE__KERNEL__KERNEL_H_
#define _CORE__KERNEL__KERNEL_H_
/**
* Main routine of every kernel pass
*/
extern "C" void kernel();
namespace Kernel {
class Pd;

View File

@ -0,0 +1,133 @@
/*
* \brief Main object of the kernel
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2021-07-09
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* base-hw Core includes */
#include <kernel/cpu.h>
#include <kernel/lock.h>
#include <kernel/main.h>
/* base-hw-internal includes */
#include <hw/boot_info.h>
namespace Kernel {
class Main;
}
class Kernel::Main
{
private:
friend void main_handle_kernel_entry();
friend void main_initialize_and_handle_kernel_entry();
static Main *_instance;
void _handle_kernel_entry();
};
Kernel::Main *Kernel::Main::_instance;
void Kernel::Main::_handle_kernel_entry()
{
Cpu &cpu = cpu_pool().cpu(Cpu::executing_id());
Cpu_job * new_job;
{
Lock::Guard guard(data_lock());
new_job = &cpu.schedule();
}
new_job->proceed(cpu);
}
void Kernel::main_handle_kernel_entry()
{
Main::_instance->_handle_kernel_entry();
}
void Kernel::main_initialize_and_handle_kernel_entry()
{
static volatile bool lock_ready = false;
static volatile bool pool_ready = false;
static volatile bool kernel_ready = false;
/**
* It is essential to guard the initialization of the data_lock object
* in the SMP case, because otherwise the __cxa_guard_aquire of the cxx
* library contention path might get called, which ends up in
* calling a Semaphore, which will call Kernel::stop_thread() or
* Kernel::yield() system-calls in this code
*/
while (Cpu::executing_id() != Cpu::primary_id() && !lock_ready) { }
/**
* Create a main object and initialize static reference to it
*/
if (Cpu::executing_id() == Cpu::primary_id()) {
static Main instance { };
Main::_instance = &instance;
}
{
Lock::Guard guard(data_lock());
lock_ready = true;
/* initialize current cpu */
pool_ready = cpu_pool().initialize();
};
/* wait until all cpus have initialized their corresponding cpu object */
while (!pool_ready) { ; }
/* the boot-cpu initializes the rest of the kernel */
if (Cpu::executing_id() == Cpu::primary_id()) {
Lock::Guard guard(data_lock());
using Boot_info = Hw::Boot_info<Board::Boot_info>;
Boot_info &boot_info {
*reinterpret_cast<Boot_info*>(Hw::Mm::boot_info().base) };
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");
Core_main_thread::singleton();
kernel_ready = true;
} else {
/* secondary cpus spin until the kernel is initialized */
while (!kernel_ready) {;}
}
Main::_instance->_handle_kernel_entry();
}
Kernel::time_t Kernel::main_read_idle_thread_execution_time(unsigned cpu_idx)
{
return cpu_pool().cpu(cpu_idx).idle_thread().execution_time();
}

View File

@ -0,0 +1,29 @@
/*
* \brief Main object of the kernel
* \author Martin Stein
* \date 2021-07-09
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _KERNEL__MAIN_H_
#define _KERNEL__MAIN_H_
/* base-hw Core includes */
#include <kernel/types.h>
namespace Kernel {
void main_handle_kernel_entry();
void main_initialize_and_handle_kernel_entry();
time_t main_read_idle_thread_execution_time(unsigned cpu_idx);
}
#endif /* _KERNEL__MAIN_H_ */

View File

@ -23,6 +23,7 @@
#include <hw/page_flags.h>
#include <hw/util.h>
#include <translation_table.h>
#include <kernel/main.h>
/* base-internal includes */
#include <base/internal/crt0.h>
@ -35,11 +36,6 @@
using namespace Genode;
namespace Kernel {
time_t read_idle_thread_execution_time(unsigned cpu_idx);
}
/**************
** Platform **
@ -236,7 +232,7 @@ Platform::Platform()
Info trace_source_info() const override
{
Trace::Execution_time execution_time {
Kernel::read_idle_thread_execution_time(
Kernel::main_read_idle_thread_execution_time(
_affinity.xpos()), 0 };
return { Session_label("kernel"), "idle",

View File

@ -31,7 +31,7 @@
add sp, r1, r0
/* jump into init C code */
b kernel_init
b _ZN6Kernel39main_initialize_and_handle_kernel_entryEv
_kernel_stack: .long kernel_stack
_kernel_stack_size: .long kernel_stack_size

View File

@ -134,7 +134,7 @@
bx lr
_kernel_entry:
.long kernel
.long _ZN6Kernel24main_handle_kernel_entryEv
_fpu_save:
.long vfp_save_fpu_context

View File

@ -99,7 +99,7 @@ monitor_mode_exception_vector:
ldr lr, [lr]
subs pc, lr, #0 /* jump back into kernel */
_kernel_entry: .long kernel
_kernel_entry: .long _ZN6Kernel24main_handle_kernel_entryEv
/* jump to this point to switch to TrustZone's normal world */

View File

@ -18,6 +18,7 @@
#include <platform_pd.h>
#include <kernel/cpu.h>
#include <kernel/vm.h>
#include <kernel/main.h>
namespace Kernel {
@ -60,8 +61,7 @@ struct Host_context
} vt_host_context;
extern "C" void kernel();
extern "C" void hypervisor_enter_vm(Genode::Vm_state&, Host_context&);
extern "C" void hypervisor_enter_vm(Genode::Vm_state&, Host_context&);
static Host_context & host_context(Cpu & cpu)
@ -78,7 +78,7 @@ static Host_context & host_context(Cpu & cpu)
c.mair0 = Cpu::Mair0::read();
c.dacr = Cpu::Dacr::read();
c.vmpidr = Cpu::Mpidr::read();
c.ip = (addr_t) &kernel;
c.ip = (addr_t)&Kernel::main_handle_kernel_entry;
c.vttbr = 0;
c.hcr = 0;
c.hstr = 0;

View File

@ -31,7 +31,7 @@
add sp, r1, r0*/
/* jump into init C code */
b kernel_init
b _ZN6Kernel39main_initialize_and_handle_kernel_entryEv
_kernel_stack: .quad kernel_stack
_kernel_stack_size: .quad kernel_stack_size

View File

@ -67,7 +67,7 @@ _kernel_entry:
ldr x0, [sp, #-16]
ldr x1, [sp, #-32]
str x1, [x0]
bl kernel
bl _ZN6Kernel24main_handle_kernel_entryEv
.section .text

View File

@ -21,12 +21,12 @@
#include <platform_pd.h>
#include <kernel/cpu.h>
#include <kernel/vm.h>
#include <kernel/main.h>
using Genode::addr_t;
using Kernel::Cpu;
using Kernel::Vm;
extern "C" void kernel();
extern void * kernel_stack;
extern "C" void hypervisor_enter_vm(addr_t vm, addr_t host,
addr_t pic, addr_t guest_table);
@ -40,7 +40,7 @@ static Genode::Vm_state & host_context(Cpu & cpu)
host_context[cpu.id()].construct();
Genode::Vm_state & c = *host_context[cpu.id()];
c.sp_el1 = cpu.stack_start();
c.ip = (addr_t) &kernel;
c.ip = (addr_t)&Kernel::main_handle_kernel_entry;
c.pstate = 0;
Cpu::Spsr::Sp::set(c.pstate, 1); /* select non-el0 stack pointer */
Cpu::Spsr::El::set(c.pstate, Cpu::Current_el::EL1);

View File

@ -24,7 +24,7 @@
la x30, kernel_stack_size
ld x30, (x30)
add sp, x29, x30
la x30, kernel_init
la x30, _ZN6Kernel39main_initialize_and_handle_kernel_entryEv
jalr x30

View File

@ -49,7 +49,7 @@ _kernel_entry:
la x30, kernel_stack_size
ld x30, (x30)
add sp, x29, x30
la x30, kernel
la x30, _ZN6Kernel24main_handle_kernel_entryEv
jalr x30

View File

@ -38,7 +38,7 @@
movq %rax, %rsp
/* jump to C entry code */
jmp kernel_init
jmp _ZN6Kernel39main_initialize_and_handle_kernel_entryEv
/*********************************

View File

@ -133,7 +133,7 @@
addq $KERNEL_STACK_OFFSET, %rax
movq (%rax), %rsp
_load_address kernel rcx
_load_address _ZN6Kernel24main_handle_kernel_entryEv rcx
jmp *%rcx