mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 23:42:32 +00:00
parent
84331ac0f7
commit
0635d5fffb
@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm
|
||||
# add C++ sources
|
||||
SRC_CC += spec/32bit/memory_map.cc
|
||||
SRC_CC += spec/arm/kernel/thread.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_idle.cc
|
||||
SRC_CC += spec/arm/kernel/pd.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
|
||||
|
@ -16,7 +16,6 @@ SRC_S += spec/x86_64/exception_vector.s
|
||||
SRC_CC += kernel/vm_thread_off.cc
|
||||
SRC_CC += spec/x86_64/pic.cc
|
||||
SRC_CC += spec/x86_64/timer.cc
|
||||
SRC_CC += spec/x86_64/kernel/cpu_exception.cc
|
||||
SRC_CC += spec/x86_64/kernel/thread_exception.cc
|
||||
SRC_CC += spec/x86_64/platform_support.cc
|
||||
SRC_CC += spec/x86/platform_services.cc
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <util/list.h>
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
#include <kernel/irq.h>
|
||||
|
||||
namespace Genode {
|
||||
class Irq_session_component;
|
||||
}
|
||||
|
@ -120,17 +120,23 @@ Cpu_job::~Cpu_job()
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
** Cpu_idle **
|
||||
**************/
|
||||
|
||||
void Cpu_idle::_main() { while (1) { Genode::Cpu::wait_for_interrupt(); } }
|
||||
|
||||
|
||||
/*********
|
||||
** Cpu **
|
||||
*********/
|
||||
|
||||
extern "C" void idle_thread_main(void);
|
||||
|
||||
Cpu::Idle_thread::Idle_thread(Cpu * const cpu)
|
||||
: Thread("idle")
|
||||
{
|
||||
regs->ip = (addr_t)&idle_thread_main;
|
||||
|
||||
affinity(cpu);
|
||||
Thread::_pd = core_pd();
|
||||
Thread::_pd->admit(*regs);
|
||||
}
|
||||
|
||||
|
||||
void Cpu::set_timeout(Timeout * const timeout, time_t const duration_us) {
|
||||
_timer.set_timeout(timeout, _timer.us_to_ticks(duration_us)); }
|
||||
|
||||
@ -185,8 +191,8 @@ Cpu_job & Cpu::schedule()
|
||||
|
||||
Cpu::Cpu(unsigned const id)
|
||||
:
|
||||
_id(id), _timer(_id), _idle(this),
|
||||
_scheduler(&_idle, _quota(), _fill()),
|
||||
_id(id), _timer(_id),
|
||||
_scheduler(&_idle, _quota(), _fill()), _idle(this),
|
||||
_ipi_irq(*this), _timer_irq(_timer.interrupt_id(), *this)
|
||||
{ }
|
||||
|
||||
|
@ -16,30 +16,12 @@
|
||||
#define _CORE__KERNEL__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/timer.h>
|
||||
#include <cpu.h>
|
||||
#include <kernel/cpu_scheduler.h>
|
||||
#include <kernel/cpu_context.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
namespace Hw { class Page_table; }
|
||||
#include <kernel/thread.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Context of a job (thread, VM, idle) that shall be executed by a CPU
|
||||
*/
|
||||
class Cpu_job;
|
||||
|
||||
/**
|
||||
* Ability to do a domain update on all CPUs
|
||||
*/
|
||||
class Cpu_domain_update;
|
||||
|
||||
/**
|
||||
* Execution context that is scheduled on CPU idle
|
||||
*/
|
||||
class Cpu_idle;
|
||||
|
||||
/**
|
||||
* Class for kernel data that is needed to manage a specific CPU
|
||||
*/
|
||||
@ -56,158 +38,6 @@ namespace Kernel
|
||||
Cpu_pool * cpu_pool();
|
||||
}
|
||||
|
||||
class Kernel::Cpu_domain_update : public Double_list_item
|
||||
{
|
||||
friend class Cpu_domain_update_list;
|
||||
|
||||
private:
|
||||
|
||||
bool _pending[NR_OF_CPUS];
|
||||
unsigned _domain_id;
|
||||
|
||||
/**
|
||||
* Domain-update back-end
|
||||
*/
|
||||
void _domain_update();
|
||||
|
||||
/**
|
||||
* Perform the domain update on the executing CPU
|
||||
*/
|
||||
void _do();
|
||||
|
||||
protected:
|
||||
|
||||
Cpu_domain_update();
|
||||
|
||||
/**
|
||||
* Do an update of domain 'id' on all CPUs and return if this blocks
|
||||
*/
|
||||
bool _do_global(unsigned const id);
|
||||
|
||||
/**
|
||||
* Notice that the update isn't pending on any CPU anymore
|
||||
*/
|
||||
virtual void _cpu_domain_update_unblocks() = 0;
|
||||
};
|
||||
|
||||
class Kernel::Cpu_job : public Genode::Cpu::User_context, public Cpu_share
|
||||
{
|
||||
protected:
|
||||
|
||||
Cpu * _cpu;
|
||||
|
||||
/**
|
||||
* Handle interrupt exception that occured during execution on CPU 'id'
|
||||
*/
|
||||
void _interrupt(unsigned const id);
|
||||
|
||||
/**
|
||||
* Activate our own CPU-share
|
||||
*/
|
||||
void _activate_own_share();
|
||||
|
||||
/**
|
||||
* Deactivate our own CPU-share
|
||||
*/
|
||||
void _deactivate_own_share();
|
||||
|
||||
/**
|
||||
* Yield the currently scheduled CPU share of this context
|
||||
*/
|
||||
void _yield();
|
||||
|
||||
/**
|
||||
* Return wether we are allowed to help job 'j' with our CPU-share
|
||||
*/
|
||||
bool _helping_possible(Cpu_job * const j) { return j->_cpu == _cpu; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Handle exception that occured during execution on CPU 'id'
|
||||
*/
|
||||
virtual void exception(unsigned const id) = 0;
|
||||
|
||||
/**
|
||||
* Continue execution on CPU 'id'
|
||||
*/
|
||||
virtual void proceed(unsigned const id) = 0;
|
||||
|
||||
/**
|
||||
* Return which job currently uses our CPU-share
|
||||
*/
|
||||
virtual Cpu_job * helping_sink() = 0;
|
||||
|
||||
/**
|
||||
* Construct a job with scheduling priority 'p' and time quota 'q'
|
||||
*/
|
||||
Cpu_job(Cpu_priority const p, unsigned const q);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_job();
|
||||
|
||||
/**
|
||||
* Link job to CPU 'cpu'
|
||||
*/
|
||||
void affinity(Cpu * const cpu);
|
||||
|
||||
/**
|
||||
* Set CPU quota of the job to 'q'
|
||||
*/
|
||||
void quota(unsigned const q);
|
||||
|
||||
/**
|
||||
* Return wether our CPU-share is currently active
|
||||
*/
|
||||
bool own_share_active() { return Cpu_share::ready(); }
|
||||
|
||||
void timeout(Timeout * const timeout, time_t const duration_us);
|
||||
|
||||
time_t timeout_age_us(Timeout const * const timeout) const;
|
||||
|
||||
time_t timeout_max_us() const;
|
||||
|
||||
time_t time() const;
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
void cpu(Cpu * const cpu) { _cpu = cpu; }
|
||||
};
|
||||
|
||||
class Kernel::Cpu_idle : public Cpu_job
|
||||
{
|
||||
private:
|
||||
|
||||
static constexpr size_t stack_size = sizeof(addr_t) * 32;
|
||||
|
||||
char _stack[stack_size] __attribute__((aligned(16)));
|
||||
|
||||
/**
|
||||
* Main function of all idle threads
|
||||
*/
|
||||
static void _main();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct idle context for CPU 'cpu'
|
||||
*/
|
||||
Cpu_idle(Cpu * const cpu);
|
||||
|
||||
|
||||
/*
|
||||
* Cpu_job interface
|
||||
*/
|
||||
|
||||
void exception(unsigned const cpu);
|
||||
void proceed(unsigned const cpu_id);
|
||||
Cpu_job * helping_sink() { return this; }
|
||||
};
|
||||
|
||||
class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout
|
||||
{
|
||||
private:
|
||||
@ -243,10 +73,20 @@ class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout
|
||||
void trigger(unsigned const cpu_id);
|
||||
};
|
||||
|
||||
|
||||
struct Idle_thread : Kernel::Thread
|
||||
{
|
||||
/**
|
||||
* Construct idle context for CPU 'cpu'
|
||||
*/
|
||||
Idle_thread(Cpu * const cpu);
|
||||
};
|
||||
|
||||
|
||||
unsigned const _id;
|
||||
Timer _timer;
|
||||
Cpu_idle _idle;
|
||||
Cpu_scheduler _scheduler;
|
||||
Idle_thread _idle;
|
||||
Ipi _ipi_irq;
|
||||
Irq _timer_irq; /* timer IRQ implemented as empty event */
|
||||
|
||||
|
160
repos/base-hw/src/core/kernel/cpu_context.h
Normal file
160
repos/base-hw/src/core/kernel/cpu_context.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* \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-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.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__KERNEL__CPU_CONTEXT_H_
|
||||
#define _CORE__KERNEL__CPU_CONTEXT_H_
|
||||
|
||||
/* core includes */
|
||||
#include <cpu.h>
|
||||
#include <kernel/cpu_scheduler.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
class Cpu;
|
||||
|
||||
/**
|
||||
* Context of a job (thread, VM, idle) that shall be executed by a CPU
|
||||
*/
|
||||
class Cpu_job;
|
||||
|
||||
/**
|
||||
* Ability to do a domain update on all CPUs
|
||||
*/
|
||||
class Cpu_domain_update;
|
||||
}
|
||||
|
||||
class Kernel::Cpu_domain_update : public Double_list_item
|
||||
{
|
||||
friend class Cpu_domain_update_list;
|
||||
|
||||
private:
|
||||
|
||||
bool _pending[NR_OF_CPUS];
|
||||
unsigned _domain_id;
|
||||
|
||||
/**
|
||||
* Domain-update back-end
|
||||
*/
|
||||
void _domain_update();
|
||||
|
||||
/**
|
||||
* Perform the domain update on the executing CPU
|
||||
*/
|
||||
void _do();
|
||||
|
||||
protected:
|
||||
|
||||
Cpu_domain_update();
|
||||
|
||||
/**
|
||||
* Do an update of domain 'id' on all CPUs and return if this blocks
|
||||
*/
|
||||
bool _do_global(unsigned const id);
|
||||
|
||||
/**
|
||||
* Notice that the update isn't pending on any CPU anymore
|
||||
*/
|
||||
virtual void _cpu_domain_update_unblocks() = 0;
|
||||
};
|
||||
|
||||
class Kernel::Cpu_job : public Genode::Cpu::User_context, public Cpu_share
|
||||
{
|
||||
protected:
|
||||
|
||||
Cpu * _cpu;
|
||||
|
||||
/**
|
||||
* Handle interrupt exception that occured during execution on CPU 'id'
|
||||
*/
|
||||
void _interrupt(unsigned const id);
|
||||
|
||||
/**
|
||||
* Activate our own CPU-share
|
||||
*/
|
||||
void _activate_own_share();
|
||||
|
||||
/**
|
||||
* Deactivate our own CPU-share
|
||||
*/
|
||||
void _deactivate_own_share();
|
||||
|
||||
/**
|
||||
* Yield the currently scheduled CPU share of this context
|
||||
*/
|
||||
void _yield();
|
||||
|
||||
/**
|
||||
* Return wether we are allowed to help job 'j' with our CPU-share
|
||||
*/
|
||||
bool _helping_possible(Cpu_job * const j) { return j->_cpu == _cpu; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Handle exception that occured during execution on CPU 'id'
|
||||
*/
|
||||
virtual void exception(unsigned const id) = 0;
|
||||
|
||||
/**
|
||||
* Continue execution on CPU 'id'
|
||||
*/
|
||||
virtual void proceed(unsigned const id) = 0;
|
||||
|
||||
/**
|
||||
* Return which job currently uses our CPU-share
|
||||
*/
|
||||
virtual Cpu_job * helping_sink() = 0;
|
||||
|
||||
/**
|
||||
* Construct a job with scheduling priority 'p' and time quota 'q'
|
||||
*/
|
||||
Cpu_job(Cpu_priority const p, unsigned const q);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Cpu_job();
|
||||
|
||||
/**
|
||||
* Link job to CPU 'cpu'
|
||||
*/
|
||||
void affinity(Cpu * const cpu);
|
||||
|
||||
/**
|
||||
* Set CPU quota of the job to 'q'
|
||||
*/
|
||||
void quota(unsigned const q);
|
||||
|
||||
/**
|
||||
* Return wether our CPU-share is currently active
|
||||
*/
|
||||
bool own_share_active() { return Cpu_share::ready(); }
|
||||
|
||||
void timeout(Timeout * const timeout, time_t const duration_us);
|
||||
|
||||
time_t timeout_age_us(Timeout const * const timeout) const;
|
||||
|
||||
time_t timeout_max_us() const;
|
||||
|
||||
time_t time() const;
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
void cpu(Cpu * const cpu) { _cpu = cpu; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__KERNEL__CPU_CONTEXT_H_ */
|
@ -160,6 +160,7 @@ bool Cpu_scheduler::ready_check(Share * const s1)
|
||||
void Cpu_scheduler::ready(Share * const s)
|
||||
{
|
||||
assert(!s->_ready && s != _idle);
|
||||
|
||||
s->_ready = 1;
|
||||
s->_fill = _fill;
|
||||
_fills.insert_tail(s);
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <platform_pd.h>
|
||||
#include <pic.h>
|
||||
|
@ -16,7 +16,8 @@
|
||||
#define _CORE__KERNEL__PD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <cpu.h>
|
||||
#include <kernel/core_interface.h>
|
||||
#include <kernel/object.h>
|
||||
#include <translation_table.h>
|
||||
|
||||
@ -33,7 +34,7 @@ namespace Kernel
|
||||
}
|
||||
|
||||
|
||||
class Kernel::Pd : public Cpu::Pd,
|
||||
class Kernel::Pd : public Genode::Cpu::Pd,
|
||||
public Kernel::Object
|
||||
{
|
||||
public:
|
||||
@ -65,7 +66,7 @@ class Kernel::Pd : public Cpu::Pd,
|
||||
/**
|
||||
* Let the CPU context 'c' join the PD
|
||||
*/
|
||||
void admit(Cpu::Context & c);
|
||||
void admit(Genode::Cpu::Context & c);
|
||||
|
||||
|
||||
static capid_t syscall_create(void * const dst,
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <hw/assert.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/irq.h>
|
||||
|
@ -17,7 +17,7 @@
|
||||
/* core includes */
|
||||
#include <kernel/signal_receiver.h>
|
||||
#include <kernel/ipc_node.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/cpu_context.h>
|
||||
#include <kernel/object.h>
|
||||
#include <base/signal.h>
|
||||
|
||||
@ -36,8 +36,6 @@ class Kernel::Thread
|
||||
public Ipc_node, public Signal_context_killer, public Signal_handler,
|
||||
private Timeout
|
||||
{
|
||||
friend class Core_thread;
|
||||
|
||||
private:
|
||||
|
||||
enum { START_VERBOSE = 0 };
|
||||
@ -85,11 +83,15 @@ class Kernel::Thread
|
||||
int _route_event(unsigned const event_id,
|
||||
Signal_context * const signal_context_id);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Switch from an inactive state to the active state
|
||||
*/
|
||||
void _become_active();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Switch from the active state to the inactive state 's'
|
||||
*/
|
||||
@ -241,7 +243,7 @@ class Kernel::Thread
|
||||
* \param label debugging label
|
||||
*/
|
||||
Thread(char const * const label)
|
||||
: Thread(Cpu_priority::MAX, 0, label, true) { }
|
||||
: Thread(Cpu_priority::MIN, 0, label, true) { }
|
||||
|
||||
/**
|
||||
* Syscall to create a thread
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <vm_state.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu_context.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/signal_receiver.h>
|
||||
|
@ -22,4 +22,5 @@ void Genode::Arm_cpu::User_context::init(bool privileged)
|
||||
Psr::F::set(v, 1);
|
||||
Psr::A::set(v, 1);
|
||||
regs->cpsr = v;
|
||||
regs->cpu_exception = Genode::Arm_cpu::Context::RESET;
|
||||
}
|
||||
|
@ -123,18 +123,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
|
||||
Kernel::Call_arg user_arg_3() const { return regs->r3; }
|
||||
Kernel::Call_arg user_arg_4() const { return regs->r4; }
|
||||
|
||||
/**
|
||||
* Initialize thread context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param pd_id kernel name of appropriate protection domain
|
||||
*/
|
||||
void init_thread(addr_t const table, unsigned const pd_id)
|
||||
{
|
||||
regs->protection_domain(pd_id);
|
||||
regs->translation_table(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the context is in a page fault due to translation miss
|
||||
*
|
||||
@ -245,8 +233,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
|
||||
for (; base < top; base += line_size) { Icimvau::write(base); }
|
||||
}
|
||||
|
||||
static void wait_for_interrupt();
|
||||
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
|
@ -22,4 +22,5 @@ void Genode::Arm_cpu::User_context::init(bool privileged)
|
||||
Psr::I::set(v, 1);
|
||||
Psr::A::set(v, 1);
|
||||
regs->cpsr = v;
|
||||
regs->cpu_exception = Cpu::Context::RESET;
|
||||
}
|
||||
|
@ -121,3 +121,15 @@
|
||||
|
||||
_kernel_entry:
|
||||
.long kernel
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*******************************
|
||||
** idle loop for idle thread **
|
||||
*******************************/
|
||||
|
||||
.global idle_thread_main
|
||||
idle_thread_main:
|
||||
wfi
|
||||
b idle_thread_main
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* \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-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 <base/log.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);
|
||||
regs->cpu_exception = Cpu::Context::RESET;
|
||||
regs->ip = (addr_t)&_main;
|
||||
regs->sp = (addr_t)&_stack[stack_size];
|
||||
init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid);
|
||||
init(true);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
switch (regs->cpu_exception) {
|
||||
case Cpu::Context::INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case Cpu::Context::FAST_INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case Cpu::Context::RESET: return;
|
||||
default: Genode::raw("Unknown exception in idle thread"); }
|
||||
}
|
||||
|
||||
|
||||
extern void * kernel_stack;
|
||||
|
||||
void Cpu_idle::proceed(unsigned const cpu)
|
||||
{
|
||||
regs->cpu_exception = (addr_t)&kernel_stack + Cpu::KERNEL_STACK_SIZE * (cpu+1);
|
||||
|
||||
asm volatile("mov sp, %0 \n"
|
||||
"msr spsr_cxsf, %1 \n"
|
||||
"mov lr, %2 \n"
|
||||
"ldm sp, {r0-r14}^ \n"
|
||||
"subs pc, lr, #0 \n"
|
||||
:: "r" (static_cast<Cpu::Context*>(&*regs)),
|
||||
"r" (regs->cpsr), "r" (regs->ip));
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <hw/assert.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||
|
@ -12,16 +12,16 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
void Kernel::Thread::_init()
|
||||
{
|
||||
init(_core);
|
||||
regs->cpu_exception = Cpu::Context::RESET;
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
/* core includes */
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
void Kernel::Thread::_call_update_pd()
|
||||
|
@ -17,6 +17,3 @@
|
||||
|
||||
void Genode::Arm_cpu::clean_invalidate_data_cache() {
|
||||
asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); }
|
||||
|
||||
|
||||
void Genode::Arm_cpu::wait_for_interrupt() { /* FIXME */ }
|
||||
|
@ -22,11 +22,6 @@ namespace Genode { struct Arm_v7_cpu; }
|
||||
|
||||
struct Genode::Arm_v7_cpu : Arm_cpu
|
||||
{
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
static void wait_for_interrupt() { asm volatile ("wfi"); }
|
||||
|
||||
/**
|
||||
* Write back dirty lines of inner data cache and invalidate all
|
||||
*/
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <hw/assert.h>
|
||||
|
||||
#include <platform_pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
namespace Kernel
|
||||
|
@ -163,6 +163,7 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
Psr::F::set(v, 1);
|
||||
Psr::A::set(v, 1);
|
||||
regs->cpsr = v;
|
||||
regs->cpu_exception = Cpu::Context::RESET;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,18 +180,6 @@ class Genode::Cpu : public Arm_v7_cpu
|
||||
Kernel::Call_arg user_arg_3() const { return regs->r3; }
|
||||
Kernel::Call_arg user_arg_4() const { return regs->r4; }
|
||||
|
||||
/**
|
||||
* Initialize thread context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param pd_id kernel name of appropriate protection domain
|
||||
*/
|
||||
void init_thread(addr_t const table, unsigned const pd_id)
|
||||
{
|
||||
regs->protection_domain(pd_id);
|
||||
regs->translation_table(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the context is in a page fault due to translation miss
|
||||
*
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <pic.h>
|
||||
@ -29,7 +30,7 @@ extern "C" void * _start_secondary_cpus;
|
||||
static volatile bool primary_cpu = true;
|
||||
|
||||
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic/*, Kernel::Pd & core_pd, Genode::Board & board*/)
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic)
|
||||
{
|
||||
{
|
||||
Lock::Guard guard(data_lock());
|
||||
|
@ -14,6 +14,7 @@
|
||||
/* core includes */
|
||||
#include <kernel/perf_counter.h>
|
||||
#include <kernel/lock.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <pic.h>
|
||||
#include <platform_pd.h>
|
||||
|
@ -80,10 +80,14 @@ class Genode::Cpu : public Hw::Riscv_cpu
|
||||
{
|
||||
Align_at<Context, 8> regs;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
User_context();
|
||||
User_context()
|
||||
{
|
||||
/*
|
||||
* initialize cpu_exception with something that gets ignored in
|
||||
* Thread::exception
|
||||
*/
|
||||
regs->cpu_exception = IRQ_FLAG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support for kernel calls
|
||||
@ -98,22 +102,8 @@ class Genode::Cpu : public Hw::Riscv_cpu
|
||||
Kernel::Call_arg user_arg_2() const { return regs->a2; }
|
||||
Kernel::Call_arg user_arg_3() const { return regs->a3; }
|
||||
Kernel::Call_arg user_arg_4() const { return regs->a4; }
|
||||
|
||||
/**
|
||||
* Initialize thread context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param pd_id kernel name of appropriate protection domain
|
||||
*/
|
||||
void init_thread(addr_t const table, unsigned const pd_id)
|
||||
{
|
||||
regs->protection_domain(pd_id);
|
||||
regs->translation_table(table);
|
||||
}
|
||||
};
|
||||
|
||||
static void wait_for_interrupt() { asm volatile ("wfi"); };
|
||||
|
||||
/**
|
||||
* From the manual
|
||||
*
|
||||
|
@ -52,3 +52,15 @@ _kernel_entry:
|
||||
la x30, kernel
|
||||
|
||||
jalr x30
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*******************************
|
||||
** idle loop for idle thread **
|
||||
*******************************/
|
||||
|
||||
.global idle_thread_main
|
||||
idle_thread_main:
|
||||
wfi
|
||||
j idle_thread_main
|
||||
|
@ -12,50 +12,8 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assertion.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
#include <hw/memory_map.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
void Kernel::Cpu::init(Kernel::Pic &pic) {
|
||||
Stvec::write(Hw::Mm::supervisor_exception_vector().base); }
|
||||
|
||||
|
||||
Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0)
|
||||
{
|
||||
Cpu_job::cpu(cpu);
|
||||
regs->cpu_exception = Cpu::Context::RESET;
|
||||
regs->ip = (addr_t)&_main;
|
||||
regs->sp = (addr_t)&_stack[stack_size];
|
||||
init_thread((addr_t)core_pd()->translation_table(), core_pd()->asid);
|
||||
}
|
||||
|
||||
|
||||
void Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
if (regs->is_irq()) {
|
||||
_interrupt(cpu);
|
||||
return;
|
||||
} else if (regs->cpu_exception == Cpu::Context::RESET) return;
|
||||
|
||||
ASSERT_NEVER_CALLED;
|
||||
}
|
||||
|
||||
|
||||
void Cpu_idle::proceed(unsigned const)
|
||||
{
|
||||
asm volatile("csrw sscratch, %1 \n"
|
||||
"mv x31, %0 \n"
|
||||
"ld x30, (x31) \n"
|
||||
"csrw sepc, x30 \n"
|
||||
".irp reg,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,"
|
||||
"18,19,20,21,22,23,24,25,26,27,28,29,30 \n"
|
||||
" ld x\\reg, 8 * (\\reg + 1)(x31) \n"
|
||||
".endr \n"
|
||||
"csrrw x31, sscratch, x31 \n"
|
||||
"sret \n"
|
||||
:: "r" (&*regs), "r" (regs->t6) : "x30", "x31");
|
||||
}
|
||||
|
@ -11,9 +11,11 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <hw/assert.h>
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
#include <hw/assert.h>
|
||||
#include <platform_pd.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||
|
@ -21,24 +21,26 @@ void Kernel::Thread::_init() { }
|
||||
|
||||
void Thread::exception(unsigned const cpu)
|
||||
{
|
||||
using Context = Genode::Cpu::Context;
|
||||
|
||||
if (regs->is_irq())
|
||||
return;
|
||||
|
||||
switch(regs->cpu_exception) {
|
||||
case Cpu::Context::ECALL_FROM_USER:
|
||||
case Cpu::Context::ECALL_FROM_SUPERVISOR:
|
||||
case Context::ECALL_FROM_USER:
|
||||
case Context::ECALL_FROM_SUPERVISOR:
|
||||
_call();
|
||||
regs->ip += 4; /* set to next instruction */
|
||||
break;
|
||||
case Cpu::Context::INSTRUCTION_PAGE_FAULT:
|
||||
case Cpu::Context::STORE_PAGE_FAULT:
|
||||
case Cpu::Context::LOAD_PAGE_FAULT:
|
||||
case Context::INSTRUCTION_PAGE_FAULT:
|
||||
case Context::STORE_PAGE_FAULT:
|
||||
case Context::LOAD_PAGE_FAULT:
|
||||
_mmu_exception();
|
||||
break;
|
||||
default:
|
||||
Genode::error(*this, ": unhandled exception ", regs->cpu_exception,
|
||||
" at ip=", (void*)regs->ip,
|
||||
" addr=", Genode::Hex(Cpu::Sbadaddr::read()));
|
||||
" addr=", Genode::Hex(Genode::Cpu::Sbadaddr::read()));
|
||||
_die();
|
||||
}
|
||||
}
|
||||
@ -48,7 +50,7 @@ void Thread::_mmu_exception()
|
||||
{
|
||||
_become_inactive(AWAITS_RESTART);
|
||||
_fault_pd = (addr_t)_pd->platform_pd();
|
||||
_fault_addr = Cpu::Sbadaddr::read();
|
||||
_fault_addr = Genode::Cpu::Sbadaddr::read();
|
||||
|
||||
if (_pager) _pager->submit(1);
|
||||
}
|
||||
@ -56,13 +58,13 @@ void Thread::_mmu_exception()
|
||||
|
||||
void Thread::_call_update_pd()
|
||||
{
|
||||
Cpu::sfence();
|
||||
Genode::Cpu::sfence();
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_update_data_region()
|
||||
{
|
||||
Cpu::sfence();
|
||||
Genode::Cpu::sfence();
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,8 +21,6 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Cpu::User_context::User_context() { }
|
||||
|
||||
void Platform::_init_io_port_alloc() { }
|
||||
|
||||
void Platform::_init_additional() { }
|
||||
|
@ -128,11 +128,6 @@ class Genode::Cpu
|
||||
|
||||
Fpu & fpu() { return _fpu; }
|
||||
|
||||
/**
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
static void wait_for_interrupt() { asm volatile ("pause"); }
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
|
@ -167,3 +167,15 @@
|
||||
.space 64
|
||||
|
||||
_define_gdt TSS
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*******************************
|
||||
** idle loop for idle thread **
|
||||
*******************************/
|
||||
|
||||
.global idle_thread_main
|
||||
idle_thread_main:
|
||||
pause
|
||||
jmp idle_thread_main
|
||||
|
@ -12,59 +12,15 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
|
||||
/* core includes */
|
||||
#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::Gdt::init();
|
||||
Cpu_job::cpu(cpu);
|
||||
regs->ip = (addr_t)&_main;
|
||||
regs->sp = (addr_t)&_stack[stack_size];
|
||||
regs->cs = 0x8;
|
||||
regs->ss = 0x10;
|
||||
regs->init((addr_t)core_pd()->translation_table(), true);
|
||||
}
|
||||
|
||||
extern void * __tss_client_context_ptr;
|
||||
|
||||
void Cpu_idle::proceed(unsigned const)
|
||||
{
|
||||
void * * tss_stack_ptr = (&__tss_client_context_ptr);
|
||||
*tss_stack_ptr = ®s->cr3;
|
||||
|
||||
asm volatile("mov %0, %%rsp \n"
|
||||
"popq %%r8 \n"
|
||||
"popq %%r9 \n"
|
||||
"popq %%r10 \n"
|
||||
"popq %%r11 \n"
|
||||
"popq %%r12 \n"
|
||||
"popq %%r13 \n"
|
||||
"popq %%r14 \n"
|
||||
"popq %%r15 \n"
|
||||
"popq %%rax \n"
|
||||
"popq %%rbx \n"
|
||||
"popq %%rcx \n"
|
||||
"popq %%rdx \n"
|
||||
"popq %%rdi \n"
|
||||
"popq %%rsi \n"
|
||||
"popq %%rbp \n"
|
||||
"add $16, %%rsp \n"
|
||||
"iretq \n"
|
||||
:: "r" (®s->r8));
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Cpu::init(Pic &pic)
|
||||
{
|
||||
Cpu::Gdt::init();
|
||||
Idt::init();
|
||||
Tss::init();
|
||||
|
||||
@ -78,4 +34,4 @@ void Kernel::Cpu::init(Pic &pic)
|
||||
}
|
||||
|
||||
|
||||
void Cpu_domain_update::_domain_update() { }
|
||||
void Kernel::Cpu_domain_update::_domain_update() { }
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* \brief Kernel backend for protection domains
|
||||
* \author Reto Buerki
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2016-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-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.
|
||||
*/
|
||||
|
||||
#include <assertion.h>
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
void Kernel::Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
if (regs->trapno == Cpu::Context::RESET) return;
|
||||
|
||||
if (regs->trapno >= Cpu::Context::INTERRUPTS_START &&
|
||||
regs->trapno <= Cpu::Context::INTERRUPTS_END) {
|
||||
_interrupt(cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::warning("Unknown exception ", regs->trapno, " with error code ",
|
||||
regs->errcode, " at ip=", (void *)regs->ip);
|
||||
|
||||
ASSERT_NEVER_CALLED;
|
||||
}
|
@ -32,5 +32,5 @@ Kernel::Pd::~Pd()
|
||||
}
|
||||
|
||||
|
||||
void Kernel::Pd::admit(Kernel::Cpu::Context & c) {
|
||||
void Kernel::Pd::admit(Genode::Cpu::Context & c) {
|
||||
c.init((addr_t)translation_table(), this == Kernel::core_pd()); }
|
||||
|
@ -41,7 +41,7 @@ void Kernel::Thread::_mmu_exception()
|
||||
{
|
||||
_become_inactive(AWAITS_RESTART);
|
||||
_fault_pd = (addr_t)_pd->platform_pd();
|
||||
_fault_addr = Cpu::Cr2::read();
|
||||
_fault_addr = Genode::Cpu::Cr2::read();
|
||||
_fault_writes = (regs->errcode & ERR_P) && (regs->errcode & ERR_W);
|
||||
_fault_exec = (regs->errcode & ERR_P) && (regs->errcode & ERR_I);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/thread.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* \brief Kernel backend for protection domains
|
||||
* \author Reto Buerki
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2016-01-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-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.
|
||||
*/
|
||||
|
||||
#include <assertion.h>
|
||||
#include <kernel/cpu.h>
|
||||
|
||||
void Kernel::Cpu_idle::exception(unsigned const cpu)
|
||||
{
|
||||
if (regs->trapno == Cpu::Context::RESET) return;
|
||||
|
||||
if (regs->trapno >= Cpu::Context::INTERRUPTS_START &&
|
||||
regs->trapno <= Cpu::Context::INTERRUPTS_END) {
|
||||
pic()->irq_occurred(regs->trapno);
|
||||
_interrupt(cpu);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::warning("Unknown exception ", regs->trapno, " with error code ",
|
||||
regs->errcode, " at ip=", (void *)regs->ip);
|
||||
|
||||
ASSERT_NEVER_CALLED;
|
||||
}
|
Loading…
Reference in New Issue
Block a user