mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
hw: make 'smp' property an aspect (Ref #1312)
This commit separates certain SMP aspects into 'spec/smp' subdirectories. Thereby it simplifies non-SMP implementations again, where no locking and several platform specific maintainance operations are not needed. Moreover, it moves several platform specifics to appropriated places, removes dead code from x86, and starts to turn global static pointers into references that are handed over.
This commit is contained in:
parent
8899d9cb6d
commit
e05d26567d
@ -47,7 +47,7 @@ SRC_CC += pager.cc
|
||||
SRC_CC += _main.cc
|
||||
SRC_CC += kernel/cpu_scheduler.cc
|
||||
SRC_CC += kernel/double_list.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
SRC_CC += kernel/init.cc
|
||||
SRC_CC += kernel/thread.cc
|
||||
SRC_CC += kernel/signal_receiver.cc
|
||||
SRC_CC += kernel/ipc_node.cc
|
||||
|
@ -9,7 +9,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/kernel/thread.cc
|
||||
SRC_CC += spec/arm/kernel/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_idle.cc
|
||||
SRC_CC += spec/arm/kernel/pd.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
|
||||
|
@ -12,6 +12,8 @@ SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm_v6/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm_v6/mode_transition.s
|
||||
|
@ -7,9 +7,15 @@
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/smp
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/cortex_a15/cpu.cc
|
||||
SRC_CC += spec/arm_v7/smp/kernel/cpu.cc
|
||||
SRC_CC += spec/smp/kernel/kernel.cc
|
||||
|
||||
# add assembler sources
|
||||
SRC_S += spec/arm/smp/kernel/crt0.s
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc
|
||||
|
@ -10,6 +10,8 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
SRC_CC += spec/arm/kernel/cpu.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc
|
||||
|
@ -13,6 +13,8 @@ SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm/kernel/cpu.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc
|
||||
|
@ -9,11 +9,12 @@
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/x86
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/kernel.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/x86/platform_support.cc
|
||||
SRC_CC += spec/x86/kernel/pd.cc
|
||||
SRC_CC += spec/x86/cpu.cc
|
||||
SRC_CC += spec/x86/bios_data_area.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/x86/io_port_session_component.cc
|
||||
SRC_CC += spec/x86/platform_services.cc
|
||||
|
||||
|
@ -269,7 +269,7 @@ class Kernel::Cpu : public Genode::Cpu,
|
||||
Cpu_idle _idle;
|
||||
Timer * const _timer;
|
||||
Cpu_scheduler _scheduler;
|
||||
Ipi _ipi_irq;
|
||||
Ipi _ipi_irq;
|
||||
Irq _timer_irq; /* timer irq implemented as empty event */
|
||||
|
||||
unsigned _quota() const { return _timer->ms_to_tics(cpu_quota_ms); }
|
||||
@ -282,6 +282,14 @@ class Kernel::Cpu : public Genode::Cpu,
|
||||
*/
|
||||
Cpu(unsigned const id, Timer * const timer);
|
||||
|
||||
/**
|
||||
* Initialize primary cpu object
|
||||
*
|
||||
* \param pic interrupt controller object
|
||||
* \param core_pd core's pd object
|
||||
*/
|
||||
void init(Pic &pic, Kernel::Pd &core_pd);
|
||||
|
||||
/**
|
||||
* Raise the IPI of the CPU
|
||||
*/
|
||||
@ -301,9 +309,9 @@ class Kernel::Cpu : public Genode::Cpu,
|
||||
void schedule(Job * const job);
|
||||
|
||||
/**
|
||||
* Handle recent exception of the CPU and proceed its user execution
|
||||
* Return the job that should be executed at next
|
||||
*/
|
||||
void exception();
|
||||
Cpu_job& schedule();
|
||||
|
||||
|
||||
/***************
|
||||
@ -313,8 +321,8 @@ class Kernel::Cpu : public Genode::Cpu,
|
||||
/**
|
||||
* Returns the currently active job
|
||||
*/
|
||||
Job * scheduled_job() const {
|
||||
return static_cast<Job *>(_scheduler.head())->helping_sink(); }
|
||||
Job & scheduled_job() const {
|
||||
return *static_cast<Job *>(_scheduler.head())->helping_sink(); }
|
||||
|
||||
unsigned id() const { return _id; }
|
||||
Cpu_scheduler * scheduler() { return &_scheduler; }
|
||||
|
@ -11,6 +11,20 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get base of the first kernel-stack and the common kernel-stack size
|
||||
*
|
||||
* \param base_dst_reg register that shall receive the stack-area base
|
||||
* \param size_dst_reg register that shall receive the size of a kernel stack
|
||||
*/
|
||||
.macro _get_constraints_of_kernel_stacks base_dst_reg, size_dst_reg
|
||||
|
||||
ldr \base_dst_reg, =kernel_stack
|
||||
ldr \size_dst_reg, =kernel_stack_size
|
||||
ldr \size_dst_reg, [\size_dst_reg]
|
||||
.endm
|
||||
|
||||
|
||||
/**
|
||||
* Calculate and apply kernel SP for a given kernel-stacks area
|
||||
*
|
||||
|
@ -125,15 +125,13 @@ class Genode::Cpu : public Arm
|
||||
*
|
||||
* \param pd kernel's pd object
|
||||
*/
|
||||
static void init_virt_kernel(Kernel::Pd* pd);
|
||||
static void init_virt_kernel(Kernel::Pd& pd);
|
||||
|
||||
/**
|
||||
* Ensure that TLB insertions get applied
|
||||
*/
|
||||
static void tlb_insertions() { flush_tlb(); }
|
||||
|
||||
static void start_secondary_cpus(void *) { assert(!Board::is_smp()); }
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
|
@ -155,7 +155,7 @@ class Genode::Arm_v7 : public Arm
|
||||
*
|
||||
* \param pd kernel's pd object
|
||||
*/
|
||||
static void init_virt_kernel(Kernel::Pd* pd);
|
||||
static void init_virt_kernel(Kernel::Pd& pd);
|
||||
|
||||
inline static void finish_init_phys_kernel();
|
||||
|
||||
@ -176,17 +176,6 @@ class Genode::Arm_v7 : public Arm
|
||||
*/
|
||||
static void data_synchronization_barrier() { asm volatile ("dsb"); }
|
||||
|
||||
/**
|
||||
* Enable secondary CPUs with instr. pointer 'ip'
|
||||
*/
|
||||
static void start_secondary_cpus(void * const ip)
|
||||
{
|
||||
if (!(NR_OF_CPUS > 1)) { return; }
|
||||
Board::secondary_cpus_ip(ip);
|
||||
data_synchronization_barrier();
|
||||
asm volatile ("sev\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
|
@ -427,7 +427,7 @@ class Genode::Cpu : public Arm_v7
|
||||
*
|
||||
* \param pd kernel pd object pointer
|
||||
*/
|
||||
static void init_virt_kernel(Kernel::Pd * pd);
|
||||
static void init_virt_kernel(Kernel::Pd & pd);
|
||||
|
||||
|
||||
/*************
|
||||
|
@ -144,7 +144,7 @@ class Genode::Cpu
|
||||
{
|
||||
friend class Cpu_lazy_state;
|
||||
|
||||
private:
|
||||
protected:
|
||||
|
||||
Idt *_idt;
|
||||
Tss *_tss;
|
||||
@ -311,96 +311,6 @@ class Genode::Cpu
|
||||
Kernel::Call_arg user_arg_7() const { return r11; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if current execution context is running in user mode
|
||||
*/
|
||||
static bool is_user()
|
||||
{
|
||||
PDBG("not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all entries of all instruction caches
|
||||
*/
|
||||
__attribute__((always_inline)) static void invalidate_instr_caches() { }
|
||||
|
||||
/**
|
||||
* Flush all entries of all data caches
|
||||
*/
|
||||
inline static void flush_data_caches() { }
|
||||
|
||||
/**
|
||||
* Invalidate all entries of all data caches
|
||||
*/
|
||||
inline static void invalidate_data_caches() { }
|
||||
|
||||
/**
|
||||
* Flush all caches
|
||||
*/
|
||||
static void flush_caches()
|
||||
{
|
||||
flush_data_caches();
|
||||
invalidate_instr_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all TLB entries of the address space named 'pid'
|
||||
*/
|
||||
static void flush_tlb_by_pid(unsigned const pid)
|
||||
{
|
||||
flush_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all TLB entries
|
||||
*/
|
||||
static void flush_tlb()
|
||||
{
|
||||
flush_caches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush data-cache entries for virtual region ['base', 'base + size')
|
||||
*/
|
||||
static void
|
||||
flush_data_caches_by_virt_region(addr_t base, size_t const size) { }
|
||||
|
||||
/**
|
||||
* Bin instr.-cache entries for virtual region ['base', 'base + size')
|
||||
*/
|
||||
static void
|
||||
invalidate_instr_caches_by_virt_region(addr_t base, size_t const size)
|
||||
{ }
|
||||
|
||||
static void inval_branch_predicts() { };
|
||||
|
||||
/**
|
||||
* Switch to the virtual mode in kernel
|
||||
*
|
||||
* \param pd kernel's pd object
|
||||
*/
|
||||
static void init_virt_kernel(Kernel::Pd * pd);
|
||||
|
||||
/**
|
||||
* Configure this module appropriately for the first kernel run
|
||||
*/
|
||||
static void init_phys_kernel()
|
||||
{
|
||||
Timer::disable_pit();
|
||||
_init_fpu();
|
||||
};
|
||||
|
||||
/**
|
||||
* Finish all previous data transfers
|
||||
*/
|
||||
static void data_synchronization_barrier() { }
|
||||
|
||||
/**
|
||||
* Enable secondary CPUs with instr. pointer 'ip'
|
||||
*/
|
||||
static void start_secondary_cpus(void * const ip) { }
|
||||
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
@ -455,12 +365,22 @@ class Genode::Cpu
|
||||
_disable_fpu();
|
||||
}
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
*************/
|
||||
|
||||
static void tlb_insertions() { inval_branch_predicts(); }
|
||||
/*********************************************
|
||||
** Dummy implementations not needed on x86 **
|
||||
*********************************************/
|
||||
|
||||
static void tlb_insertions() { }
|
||||
static void translation_added(addr_t, size_t) { }
|
||||
static void flush_data_caches() { }
|
||||
static void flush_caches() { }
|
||||
static void flush_tlb_by_pid(unsigned const pid) { }
|
||||
static void flush_data_caches_by_virt_region(addr_t base,
|
||||
size_t const size) { }
|
||||
static void invalidate_instr_caches() { }
|
||||
static void invalidate_data_caches() { }
|
||||
static void invalidate_instr_caches_by_virt_region(addr_t base,
|
||||
size_t const size) {}
|
||||
};
|
||||
|
||||
struct Genode::Cpu::Cr0 : Register<64>
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* \brief CPU context of a virtual machine
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL__VM_STATE_H_
|
||||
#define _KERNEL__VM_STATE_H_
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Dummy
|
||||
*/
|
||||
struct Vm_state { };
|
||||
}
|
||||
|
||||
#endif /* _KERNEL__VM_STATE_H_ */
|
@ -274,7 +274,6 @@ class Genode::Pic : public Mmio
|
||||
*/
|
||||
|
||||
void mask() { }
|
||||
void init_cpu_local() { }
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
void trigger_ip_interrupt(unsigned) { }
|
||||
};
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <pic.h>
|
||||
|
||||
namespace Kernel {
|
||||
void init_trustzone(Pic * pic);
|
||||
void init_trustzone(Pic & pic);
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__TRUSTZONE_H_ */
|
||||
|
@ -177,12 +177,10 @@ bool Cpu::interrupt(unsigned const irq_id)
|
||||
}
|
||||
|
||||
|
||||
void Cpu::exception()
|
||||
Cpu_job & Cpu::schedule()
|
||||
{
|
||||
/* update old job */
|
||||
Job * const old_job = scheduled_job();
|
||||
|
||||
old_job->exception(_id);
|
||||
/* get new job */
|
||||
Job & old_job = scheduled_job();
|
||||
|
||||
/* update scheduler */
|
||||
unsigned const old_time = _scheduler.head_quota();
|
||||
@ -191,18 +189,18 @@ void Cpu::exception()
|
||||
_scheduler.update(quota);
|
||||
|
||||
/* get new job */
|
||||
Job * const new_job = scheduled_job();
|
||||
Job & new_job = scheduled_job();
|
||||
quota = _scheduler.head_quota();
|
||||
assert(quota);
|
||||
_timer->start_one_shot(quota, _id);
|
||||
|
||||
/* switch between lazy state of old and new job */
|
||||
Cpu_lazy_state * const old_state = old_job->lazy_state();
|
||||
Cpu_lazy_state * const new_state = new_job->lazy_state();
|
||||
Cpu_lazy_state * const old_state = old_job.lazy_state();
|
||||
Cpu_lazy_state * const new_state = new_job.lazy_state();
|
||||
prepare_proceeding(old_state, new_state);
|
||||
|
||||
/* resume new job */
|
||||
new_job->proceed(_id);
|
||||
/* return new job */
|
||||
return new_job;
|
||||
}
|
||||
|
||||
|
||||
|
69
repos/base-hw/src/core/kernel/init.cc
Normal file
69
repos/base-hw/src/core/kernel/init.cc
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* \brief Common kernel initialization
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-10-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/test.h>
|
||||
#include <platform_pd.h>
|
||||
#include <pic.h>
|
||||
#include <platform_thread.h>
|
||||
|
||||
/* base includes */
|
||||
#include <unmanaged_singleton.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t),
|
||||
"Bad result type for size_t arithmetics.");
|
||||
|
||||
Pd * Kernel::core_pd() {
|
||||
return unmanaged_singleton<Genode::Core_platform_pd>()->kernel_pd(); }
|
||||
|
||||
|
||||
Pic * Kernel::pic() { return unmanaged_singleton<Pic>(); }
|
||||
|
||||
|
||||
/**
|
||||
* Setup kernel environment
|
||||
*/
|
||||
extern "C" void init_kernel()
|
||||
{
|
||||
/*
|
||||
* As atomic operations are broken in physical mode on some platforms
|
||||
* we must avoid the use of 'cmpxchg' by now (includes not using any
|
||||
* local static objects.
|
||||
*/
|
||||
|
||||
/* calculate in advance as needed later when data writes aren't allowed */
|
||||
core_pd();
|
||||
|
||||
/* initialize cpu pool */
|
||||
cpu_pool();
|
||||
|
||||
/* initialize PIC */
|
||||
pic();
|
||||
|
||||
/* initialize current cpu */
|
||||
cpu_pool()->cpu(Cpu::executing_id())->init(*pic(), *core_pd());
|
||||
|
||||
Core_thread::singleton();
|
||||
|
||||
Genode::printf("kernel initialized\n");
|
||||
|
||||
test();
|
||||
|
||||
kernel();
|
||||
}
|
@ -1,19 +1,8 @@
|
||||
/*
|
||||
* \brief Singlethreaded minimalistic kernel
|
||||
* \brief Kernel entrypoint
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-10-20
|
||||
*
|
||||
* This kernel is the only code except the mode transition PIC, that runs in
|
||||
* privileged CPU mode. It has two tasks. First it initializes the process
|
||||
* 'core', enriches it with the whole identically mapped address range,
|
||||
* joins and applies it, assigns one thread to it with a userdefined
|
||||
* entrypoint (the core main thread) and starts this thread in userland.
|
||||
* Afterwards it is called each time an exception occurs in userland to do
|
||||
* a minimum of appropriate exception handling. Thus it holds a CPU context
|
||||
* for itself as for any other thread. But due to the fact that it never
|
||||
* relies on prior kernel runs this context only holds some constant pointers
|
||||
* such as SP and IP.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -24,137 +13,14 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/test.h>
|
||||
#include <platform_pd.h>
|
||||
#include <trustzone.h>
|
||||
#include <timer.h>
|
||||
#include <pic.h>
|
||||
#include <platform_thread.h>
|
||||
|
||||
/* base includes */
|
||||
#include <unmanaged_singleton.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
extern void * _start_secondary_cpus;
|
||||
|
||||
static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t),
|
||||
"Bad result type for size_t arithmetics.");
|
||||
|
||||
Lock & Kernel::data_lock() { return *unmanaged_singleton<Kernel::Lock>(); }
|
||||
|
||||
|
||||
Pd * Kernel::core_pd() {
|
||||
return unmanaged_singleton<Genode::Core_platform_pd>()->kernel_pd(); }
|
||||
|
||||
|
||||
Pic * Kernel::pic() { return unmanaged_singleton<Pic>(); }
|
||||
|
||||
|
||||
/**
|
||||
* Setup kernel environment before activating secondary CPUs
|
||||
*/
|
||||
extern "C" void init_kernel_up()
|
||||
{
|
||||
/*
|
||||
* As atomic operations are broken in physical mode on some platforms
|
||||
* we must avoid the use of 'cmpxchg' by now (includes not using any
|
||||
* local static objects.
|
||||
*/
|
||||
|
||||
/* calculate in advance as needed later when data writes aren't allowed */
|
||||
core_pd();
|
||||
|
||||
/* initialize all CPU objects */
|
||||
cpu_pool();
|
||||
|
||||
/* initialize PIC */
|
||||
pic();
|
||||
|
||||
/* go multiprocessor mode */
|
||||
Cpu::start_secondary_cpus(&_start_secondary_cpus);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup kernel enviroment after activating secondary CPUs as primary CPU
|
||||
*/
|
||||
void init_kernel_mp_primary()
|
||||
{
|
||||
Core_thread::singleton();
|
||||
Genode::printf("kernel initialized\n");
|
||||
test();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup kernel enviroment after activating secondary CPUs
|
||||
*/
|
||||
extern "C" void init_kernel_mp()
|
||||
{
|
||||
/*
|
||||
* As updates on a cached kernel lock might not be visible to CPUs that
|
||||
* have not enabled caches, we can't synchronize the activation of MMU and
|
||||
* caches. Hence we must avoid write access to kernel data by now.
|
||||
*/
|
||||
|
||||
/* synchronize data view of all CPUs */
|
||||
Cpu::invalidate_data_caches();
|
||||
Cpu::invalidate_instr_caches();
|
||||
Cpu::data_synchronization_barrier();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
pic()->init_cpu_local();
|
||||
|
||||
/* initialize CPU in physical mode */
|
||||
Cpu::init_phys_kernel();
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(core_pd());
|
||||
|
||||
/*
|
||||
* Now it's safe to use 'cmpxchg'
|
||||
*/
|
||||
|
||||
Lock::Guard guard(data_lock());
|
||||
|
||||
/*
|
||||
* Now it's save to write to kernel data
|
||||
*/
|
||||
|
||||
/*
|
||||
* TrustZone initialization code
|
||||
*
|
||||
* FIXME This is a plattform specific feature
|
||||
*/
|
||||
init_trustzone(pic());
|
||||
|
||||
/*
|
||||
* Enable performance counter
|
||||
*
|
||||
* FIXME This is an optional CPU specific feature
|
||||
*/
|
||||
perf_counter()->enable();
|
||||
|
||||
/* enable timer interrupt */
|
||||
unsigned const cpu = Cpu::executing_id();
|
||||
pic()->unmask(Timer::interrupt_id(cpu), cpu);
|
||||
|
||||
/* do further initialization only as primary CPU */
|
||||
if (Cpu::primary_id() != cpu) { return; }
|
||||
init_kernel_mp_primary();
|
||||
}
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
|
||||
extern "C" void kernel()
|
||||
{
|
||||
data_lock().lock();
|
||||
cpu_pool()->cpu(Cpu::executing_id())->exception();
|
||||
using namespace Kernel;
|
||||
|
||||
Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id());
|
||||
cpu->scheduled_job().exception(cpu->id());
|
||||
cpu->schedule().proceed(cpu->id());
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
/* Genode includes */
|
||||
@ -69,9 +68,6 @@ void Mode_transition_control::switch_to(Cpu::Context * const context,
|
||||
addr_t const entry_raw,
|
||||
addr_t const context_ptr_base)
|
||||
{
|
||||
/* unlock kernel data */
|
||||
data_lock().unlock();
|
||||
|
||||
/* override client-context pointer of the executing CPU */
|
||||
size_t const context_ptr_offset = cpu * sizeof(context);
|
||||
addr_t const context_ptr = context_ptr_base + context_ptr_offset;
|
||||
|
@ -34,7 +34,7 @@ using namespace Genode;
|
||||
extern int _prog_img_beg;
|
||||
extern int _prog_img_end;
|
||||
|
||||
void __attribute__((weak)) Kernel::init_trustzone(Pic * pic) { }
|
||||
void __attribute__((weak)) Kernel::init_trustzone(Pic & pic) { }
|
||||
|
||||
/**
|
||||
* Format of a boot-module header
|
||||
|
@ -13,29 +13,39 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/perf_counter.h>
|
||||
#include <pic.h>
|
||||
#include <trustzone.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd)
|
||||
{
|
||||
Cpu_job::cpu(cpu);
|
||||
cpu_exception = RESET;
|
||||
ip = (addr_t)&_main;
|
||||
sp = (addr_t)&_stack[stack_size];
|
||||
init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid);
|
||||
/* locally initialize interrupt controller */
|
||||
pic.init_cpu_local();
|
||||
|
||||
/* initialize CPU in physical mode */
|
||||
Cpu::init_phys_kernel();
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(core_pd);
|
||||
|
||||
/*
|
||||
* TrustZone initialization code
|
||||
*
|
||||
* FIXME This is a plattform specific feature
|
||||
*/
|
||||
init_trustzone(pic);
|
||||
|
||||
/*
|
||||
* Enable performance counter
|
||||
*
|
||||
* FIXME This is an optional CPU specific feature
|
||||
*/
|
||||
perf_counter()->enable();
|
||||
|
||||
/* enable timer interrupt */
|
||||
unsigned const cpu = Cpu::executing_id();
|
||||
pic.unmask(Timer::interrupt_id(cpu), cpu);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
switch (cpu_exception) {
|
||||
case INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case RESET: return;
|
||||
default: assert(0); }
|
||||
}
|
||||
|
41
repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc
Normal file
41
repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* \brief Class for kernel data that is needed to manage a specific CPU
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-01-14
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
|
||||
{
|
||||
Cpu_job::cpu(cpu);
|
||||
cpu_exception = RESET;
|
||||
ip = (addr_t)&_main;
|
||||
sp = (addr_t)&_stack[stack_size];
|
||||
init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
switch (cpu_exception) {
|
||||
case INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case RESET: return;
|
||||
default: assert(0); }
|
||||
}
|
@ -20,20 +20,6 @@
|
||||
.include "macros.s"
|
||||
|
||||
|
||||
/**
|
||||
* Get base of the first kernel-stack and the common kernel-stack size
|
||||
*
|
||||
* \param base_dst_reg register that shall receive the stack-area base
|
||||
* \param size_dst_reg register that shall receive the size of a kernel stack
|
||||
*/
|
||||
.macro _get_constraints_of_kernel_stacks base_dst_reg, size_dst_reg
|
||||
|
||||
ldr \base_dst_reg, =kernel_stack
|
||||
ldr \size_dst_reg, =kernel_stack_size
|
||||
ldr \size_dst_reg, [\size_dst_reg]
|
||||
.endm
|
||||
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/**********************************
|
||||
@ -65,29 +51,12 @@
|
||||
b 1b
|
||||
2:
|
||||
|
||||
/* setup temporary stack pointer for uniprocessor mode */
|
||||
/* setup temporary stack pointer */
|
||||
_get_constraints_of_kernel_stacks r0, r1
|
||||
add sp, r0, r1
|
||||
|
||||
/* uniprocessor kernel-initialization which activates multiprocessor */
|
||||
bl init_kernel_up
|
||||
/* kernel-initialization */
|
||||
bl init_kernel
|
||||
|
||||
/*********************************************
|
||||
** Startup code that is common to all CPUs **
|
||||
*********************************************/
|
||||
|
||||
.global _start_secondary_cpus
|
||||
_start_secondary_cpus:
|
||||
|
||||
/* setup multiprocessor-aware kernel stack-pointer */
|
||||
_get_constraints_of_kernel_stacks r0, r1
|
||||
_init_kernel_sp r0, r1
|
||||
|
||||
/* do multiprocessor kernel-initialization */
|
||||
bl init_kernel_mp
|
||||
|
||||
/* call the kernel main-routine */
|
||||
bl kernel
|
||||
|
||||
/* catch erroneous return of the kernel main-routine */
|
||||
/* catch erroneous return of the kernel initialization routine */
|
||||
1: b 1b
|
||||
|
42
repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s
Normal file
42
repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* \brief Startup code for SMP kernel
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-12-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/************
|
||||
** Macros **
|
||||
************/
|
||||
|
||||
/* core includes */
|
||||
.include "macros.s"
|
||||
|
||||
.section ".text.crt0"
|
||||
|
||||
/*********************************************
|
||||
** Startup code that is common to all CPUs **
|
||||
*********************************************/
|
||||
|
||||
.global _start_secondary_cpus
|
||||
_start_secondary_cpus:
|
||||
|
||||
/* setup multiprocessor-aware kernel stack-pointer */
|
||||
_get_constraints_of_kernel_stacks r0, r1
|
||||
_init_kernel_sp r0, r1
|
||||
|
||||
/* do multiprocessor kernel-initialization */
|
||||
bl init_kernel_mp
|
||||
|
||||
/* call the kernel main-routine */
|
||||
bl kernel
|
||||
|
||||
/* catch erroneous return of the kernel main-routine */
|
||||
1: b 1b
|
@ -23,11 +23,11 @@ void Genode::Arm::invalidate_data_caches() {
|
||||
asm volatile ("mcr p15, 0, %[rd], c7, c6, 0" :: [rd]"r"(0) : ); }
|
||||
|
||||
|
||||
void Genode::Cpu::init_virt_kernel(Kernel::Pd* pd)
|
||||
void Genode::Cpu::init_virt_kernel(Kernel::Pd& pd)
|
||||
{
|
||||
Cidr::write(pd->asid);
|
||||
Cidr::write(pd.asid);
|
||||
Dacr::write(Dacr::init_virt_kernel());
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table()));
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table()));
|
||||
Ttbcr::write(0);
|
||||
Sctlr::write(Sctlr::init_virt_kernel());
|
||||
}
|
||||
|
@ -159,11 +159,11 @@ Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone()
|
||||
}
|
||||
|
||||
|
||||
void Genode::Arm_v7::init_virt_kernel(Kernel::Pd * pd)
|
||||
void Genode::Arm_v7::init_virt_kernel(Kernel::Pd & pd)
|
||||
{
|
||||
Cidr::write(pd->asid);
|
||||
Cidr::write(pd.asid);
|
||||
Dacr::write(Dacr::init_virt_kernel());
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table()));
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table()));
|
||||
Ttbcr::write(0);
|
||||
Sctlr::write(Sctlr::init_virt_kernel());
|
||||
inval_branch_predicts();
|
||||
|
99
repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc
Normal file
99
repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* \brief Cpu class implementation specific to Armv7 SMP
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-12-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/test.h>
|
||||
#include <platform_pd.h>
|
||||
#include <trustzone.h>
|
||||
#include <timer.h>
|
||||
#include <pic.h>
|
||||
#include <board.h>
|
||||
#include <platform_thread.h>
|
||||
|
||||
/* base includes */
|
||||
#include <unmanaged_singleton.h>
|
||||
#include <base/native_types.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
extern "C" void * _start_secondary_cpus;
|
||||
|
||||
Lock & Kernel::data_lock() { return *unmanaged_singleton<Kernel::Lock>(); }
|
||||
|
||||
|
||||
/**
|
||||
* Setup kernel enviroment after activating secondary CPUs
|
||||
*/
|
||||
extern "C" void init_kernel_mp()
|
||||
{
|
||||
/*
|
||||
* As updates on a cached kernel lock might not be visible to CPUs that
|
||||
* have not enabled caches, we can't synchronize the activation of MMU and
|
||||
* caches. Hence we must avoid write access to kernel data by now.
|
||||
*/
|
||||
|
||||
/* synchronize data view of all CPUs */
|
||||
Cpu::invalidate_data_caches();
|
||||
Cpu::invalidate_instr_caches();
|
||||
Cpu::data_synchronization_barrier();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
pic()->init_cpu_local();
|
||||
|
||||
/* initialize CPU in physical mode */
|
||||
Cpu::init_phys_kernel();
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::init_virt_kernel(*core_pd());
|
||||
|
||||
/*
|
||||
* Now it's safe to use 'cmpxchg'
|
||||
*/
|
||||
{
|
||||
Lock::Guard guard(data_lock());
|
||||
|
||||
/*
|
||||
* Now it's save to write to kernel data
|
||||
*/
|
||||
|
||||
/* TrustZone initialization code */
|
||||
init_trustzone(*pic());
|
||||
|
||||
/* enable performance counter */
|
||||
perf_counter()->enable();
|
||||
|
||||
/* enable timer interrupt */
|
||||
unsigned const cpu = Cpu::executing_id();
|
||||
pic()->unmask(Timer::interrupt_id(cpu), cpu);
|
||||
PINF("ok CPU awake");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd)
|
||||
{
|
||||
if (NR_OF_CPUS > 1) {
|
||||
Genode::Board::secondary_cpus_ip(&_start_secondary_cpus);
|
||||
data_synchronization_barrier();
|
||||
asm volatile ("sev\n");
|
||||
}
|
||||
|
||||
init_kernel_mp();
|
||||
}
|
@ -56,8 +56,8 @@ struct Kernel::Vm_irq : Kernel::Irq
|
||||
*/
|
||||
void occurred()
|
||||
{
|
||||
Cpu_job * job = cpu_pool()->executing_cpu()->scheduled_job();
|
||||
Vm *vm = dynamic_cast<Vm*>(job);
|
||||
Cpu_job & job = cpu_pool()->executing_cpu()->scheduled_job();
|
||||
Vm *vm = dynamic_cast<Vm*>(&job);
|
||||
if (!vm)
|
||||
PERR("VM timer interrupt while VM is not runnning!");
|
||||
else
|
||||
|
@ -15,12 +15,12 @@
|
||||
#include <kernel/pd.h>
|
||||
#include <cpu.h>
|
||||
|
||||
void Genode::Cpu::init_virt_kernel(Kernel::Pd * pd)
|
||||
void Genode::Cpu::init_virt_kernel(Kernel::Pd & pd)
|
||||
{
|
||||
Mair0::write(Mair0::init_virt_kernel());
|
||||
Dacr::write(Dacr::init_virt_kernel());
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd->translation_table(),
|
||||
pd->asid));
|
||||
Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table(),
|
||||
pd.asid));
|
||||
Ttbcr::write(Ttbcr::init_virt_kernel());
|
||||
Sctlr::write(Sctlr::init_virt_kernel());
|
||||
inval_branch_predicts();
|
||||
|
37
repos/base-hw/src/core/spec/smp/kernel/kernel.cc
Normal file
37
repos/base-hw/src/core/spec/smp/kernel/kernel.cc
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* \brief Kernel entrypoint
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-10-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
|
||||
|
||||
extern "C" void kernel()
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
Cpu_job * new_job;
|
||||
unsigned cpu_id;
|
||||
|
||||
{
|
||||
Lock::Guard guard(data_lock());
|
||||
|
||||
cpu_id = Cpu::executing_id();
|
||||
Cpu * const cpu = cpu_pool()->cpu(cpu_id);
|
||||
cpu->scheduled_job().exception(cpu_id);
|
||||
new_job = &cpu->schedule();
|
||||
}
|
||||
|
||||
new_job->proceed(cpu_id);
|
||||
}
|
@ -15,20 +15,6 @@
|
||||
#include <cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
void Genode::Cpu::init_virt_kernel(Kernel::Pd * pd)
|
||||
{
|
||||
/*
|
||||
* Please do not remove the PINF(), because the serial constructor requires
|
||||
* access to the Bios Data Area, which is available in the initial
|
||||
* translation table set, but not in the final tables used after
|
||||
* Cr3::write().
|
||||
*/
|
||||
PINF("Switch to core's final translation table");
|
||||
|
||||
Cr3::write(Cr3::init((addr_t)pd->translation_table()));
|
||||
}
|
||||
|
||||
|
||||
void Genode::Cpu::_init_fpu()
|
||||
{
|
||||
Cr0::access_t cr0_value = Cr0::read();
|
||||
|
@ -40,3 +40,25 @@ void Cpu_idle::exception(unsigned const cpu)
|
||||
errcode, (void *)ip);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd)
|
||||
{
|
||||
Timer::disable_pit();
|
||||
|
||||
_init_fpu();
|
||||
|
||||
/*
|
||||
* Please do not remove the PINF(), because the serial constructor requires
|
||||
* access to the Bios Data Area, which is available in the initial
|
||||
* translation table set, but not in the final tables used after
|
||||
* Cr3::write().
|
||||
*/
|
||||
PINF("Switch to core's final translation table");
|
||||
|
||||
Cr3::write(Cr3::init((addr_t)core_pd.translation_table()));
|
||||
|
||||
/* enable timer interrupt */
|
||||
unsigned const cpu = Cpu::executing_id();
|
||||
pic.unmask(Timer::interrupt_id(cpu), cpu);
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* \brief Kernel backend for virtual machines
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/vm.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
void Vm::exception(unsigned const cpu) {
|
||||
PDBG("not implemented"); }
|
||||
|
@ -94,23 +94,10 @@
|
||||
movq __initial_bx@GOTPCREL(%rip),%rax
|
||||
movq %rbx, (%rax)
|
||||
|
||||
/* uniprocessor kernel-initialization which activates multiprocessor */
|
||||
call init_kernel_up
|
||||
/* kernel-initialization */
|
||||
call init_kernel
|
||||
|
||||
/*********************************************
|
||||
** Startup code that is common to all CPUs **
|
||||
*********************************************/
|
||||
|
||||
.global _start_secondary_cpus
|
||||
_start_secondary_cpus:
|
||||
|
||||
/* do multiprocessor kernel-initialization */
|
||||
call init_kernel_mp
|
||||
|
||||
/* call the kernel main-routine */
|
||||
call kernel
|
||||
|
||||
/* catch erroneous return of the kernel main-routine */
|
||||
/* catch erroneous return of the kernel initialization */
|
||||
1: jmp 1b
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user