hw: turn Cpu_idle into a Thread

Fix #2539
This commit is contained in:
Stefan Kalkowski 2017-10-05 16:11:24 +02:00 committed by Christian Helmuth
parent 84331ac0f7
commit 0635d5fffb
40 changed files with 279 additions and 477 deletions

View File

@ -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

View File

@ -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

View File

@ -19,6 +19,8 @@
#include <util/list.h>
#include <irq_session/capability.h>
#include <kernel/irq.h>
namespace Genode {
class Irq_session_component;
}

View File

@ -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)
{ }

View File

@ -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 */

View 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_ */

View File

@ -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);

View File

@ -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>

View File

@ -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,

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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 **

View File

@ -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;
}

View File

@ -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

View File

@ -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));
}

View File

@ -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>;

View File

@ -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;
}

View File

@ -12,6 +12,7 @@
*/
/* core includes */
#include <kernel/pd.h>
#include <kernel/cpu.h>
#include <kernel/thread.h>
void Kernel::Thread::_call_update_pd()

View File

@ -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 */ }

View File

@ -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
*/

View File

@ -15,6 +15,7 @@
#include <hw/assert.h>
#include <platform_pd.h>
#include <kernel/cpu.h>
#include <kernel/vm.h>
namespace Kernel

View File

@ -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
*

View File

@ -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());

View File

@ -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>

View File

@ -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
*

View File

@ -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

View File

@ -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");
}

View File

@ -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>;

View File

@ -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();
}

View File

@ -21,8 +21,6 @@
using namespace Genode;
Cpu::User_context::User_context() { }
void Platform::_init_io_port_alloc() { }
void Platform::_init_additional() { }

View File

@ -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
*/

View File

@ -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

View File

@ -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 = &regs->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" (&regs->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() { }

View File

@ -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;
}

View File

@ -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()); }

View File

@ -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);

View File

@ -14,6 +14,7 @@
*/
/* core includes */
#include <kernel/cpu.h>
#include <kernel/thread.h>
using namespace Kernel;

View File

@ -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;
}