mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-12 13:33:21 +00:00
parent
84331ac0f7
commit
0635d5fffb
@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm
|
|||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += spec/32bit/memory_map.cc
|
SRC_CC += spec/32bit/memory_map.cc
|
||||||
SRC_CC += spec/arm/kernel/thread.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/kernel/pd.cc
|
||||||
SRC_CC += spec/arm/platform_support.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 += kernel/vm_thread_off.cc
|
||||||
SRC_CC += spec/x86_64/pic.cc
|
SRC_CC += spec/x86_64/pic.cc
|
||||||
SRC_CC += spec/x86_64/timer.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/kernel/thread_exception.cc
|
||||||
SRC_CC += spec/x86_64/platform_support.cc
|
SRC_CC += spec/x86_64/platform_support.cc
|
||||||
SRC_CC += spec/x86/platform_services.cc
|
SRC_CC += spec/x86/platform_services.cc
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
#include <irq_session/capability.h>
|
#include <irq_session/capability.h>
|
||||||
|
|
||||||
|
#include <kernel/irq.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
class Irq_session_component;
|
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 **
|
** 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) {
|
void Cpu::set_timeout(Timeout * const timeout, time_t const duration_us) {
|
||||||
_timer.set_timeout(timeout, _timer.us_to_ticks(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)
|
Cpu::Cpu(unsigned const id)
|
||||||
:
|
:
|
||||||
_id(id), _timer(_id), _idle(this),
|
_id(id), _timer(_id),
|
||||||
_scheduler(&_idle, _quota(), _fill()),
|
_scheduler(&_idle, _quota(), _fill()), _idle(this),
|
||||||
_ipi_irq(*this), _timer_irq(_timer.interrupt_id(), *this)
|
_ipi_irq(*this), _timer_irq(_timer.interrupt_id(), *this)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -16,30 +16,12 @@
|
|||||||
#define _CORE__KERNEL__CPU_H_
|
#define _CORE__KERNEL__CPU_H_
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/timer.h>
|
#include <kernel/cpu_context.h>
|
||||||
#include <cpu.h>
|
|
||||||
#include <kernel/cpu_scheduler.h>
|
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
|
#include <kernel/thread.h>
|
||||||
namespace Hw { class Page_table; }
|
|
||||||
|
|
||||||
namespace Kernel
|
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
|
* Class for kernel data that is needed to manage a specific CPU
|
||||||
*/
|
*/
|
||||||
@ -56,158 +38,6 @@ namespace Kernel
|
|||||||
Cpu_pool * cpu_pool();
|
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
|
class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -243,10 +73,20 @@ class Kernel::Cpu : public Genode::Cpu, public Irq::Pool, private Timeout
|
|||||||
void trigger(unsigned const cpu_id);
|
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;
|
unsigned const _id;
|
||||||
Timer _timer;
|
Timer _timer;
|
||||||
Cpu_idle _idle;
|
|
||||||
Cpu_scheduler _scheduler;
|
Cpu_scheduler _scheduler;
|
||||||
|
Idle_thread _idle;
|
||||||
Ipi _ipi_irq;
|
Ipi _ipi_irq;
|
||||||
Irq _timer_irq; /* timer IRQ implemented as empty event */
|
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)
|
void Cpu_scheduler::ready(Share * const s)
|
||||||
{
|
{
|
||||||
assert(!s->_ready && s != _idle);
|
assert(!s->_ready && s != _idle);
|
||||||
|
|
||||||
s->_ready = 1;
|
s->_ready = 1;
|
||||||
s->_fill = _fill;
|
s->_fill = _fill;
|
||||||
_fills.insert_tail(s);
|
_fills.insert_tail(s);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
|
@ -16,7 +16,8 @@
|
|||||||
#define _CORE__KERNEL__PD_H_
|
#define _CORE__KERNEL__PD_H_
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/cpu.h>
|
#include <cpu.h>
|
||||||
|
#include <kernel/core_interface.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
#include <translation_table.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 Kernel::Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -65,7 +66,7 @@ class Kernel::Pd : public Cpu::Pd,
|
|||||||
/**
|
/**
|
||||||
* Let the CPU context 'c' join the 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,
|
static capid_t syscall_create(void * const dst,
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <hw/assert.h>
|
#include <hw/assert.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/signal_receiver.h>
|
#include <kernel/signal_receiver.h>
|
||||||
#include <kernel/ipc_node.h>
|
#include <kernel/ipc_node.h>
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu_context.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
|
|
||||||
@ -36,8 +36,6 @@ class Kernel::Thread
|
|||||||
public Ipc_node, public Signal_context_killer, public Signal_handler,
|
public Ipc_node, public Signal_context_killer, public Signal_handler,
|
||||||
private Timeout
|
private Timeout
|
||||||
{
|
{
|
||||||
friend class Core_thread;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum { START_VERBOSE = 0 };
|
enum { START_VERBOSE = 0 };
|
||||||
@ -85,11 +83,15 @@ class Kernel::Thread
|
|||||||
int _route_event(unsigned const event_id,
|
int _route_event(unsigned const event_id,
|
||||||
Signal_context * const signal_context_id);
|
Signal_context * const signal_context_id);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch from an inactive state to the active state
|
* Switch from an inactive state to the active state
|
||||||
*/
|
*/
|
||||||
void _become_active();
|
void _become_active();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch from the active state to the inactive state 's'
|
* Switch from the active state to the inactive state 's'
|
||||||
*/
|
*/
|
||||||
@ -241,7 +243,7 @@ class Kernel::Thread
|
|||||||
* \param label debugging label
|
* \param label debugging label
|
||||||
*/
|
*/
|
||||||
Thread(char const * const 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
|
* Syscall to create a thread
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <vm_state.h>
|
#include <vm_state.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <kernel/cpu_context.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
#include <kernel/signal_receiver.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::F::set(v, 1);
|
||||||
Psr::A::set(v, 1);
|
Psr::A::set(v, 1);
|
||||||
regs->cpsr = v;
|
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_3() const { return regs->r3; }
|
||||||
Kernel::Call_arg user_arg_4() const { return regs->r4; }
|
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
|
* 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); }
|
for (; base < top; base += line_size) { Icimvau::write(base); }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wait_for_interrupt();
|
|
||||||
|
|
||||||
|
|
||||||
/*************
|
/*************
|
||||||
** Dummies **
|
** Dummies **
|
||||||
|
@ -22,4 +22,5 @@ void Genode::Arm_cpu::User_context::init(bool privileged)
|
|||||||
Psr::I::set(v, 1);
|
Psr::I::set(v, 1);
|
||||||
Psr::A::set(v, 1);
|
Psr::A::set(v, 1);
|
||||||
regs->cpsr = v;
|
regs->cpsr = v;
|
||||||
|
regs->cpu_exception = Cpu::Context::RESET;
|
||||||
}
|
}
|
||||||
|
@ -121,3 +121,15 @@
|
|||||||
|
|
||||||
_kernel_entry:
|
_kernel_entry:
|
||||||
.long kernel
|
.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 */
|
/* core includes */
|
||||||
#include <hw/assert.h>
|
#include <hw/assert.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||||
|
@ -12,16 +12,16 @@
|
|||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <kernel/thread.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/pd.h>
|
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
|
#include <kernel/pd.h>
|
||||||
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
void Kernel::Thread::_init()
|
void Kernel::Thread::_init()
|
||||||
{
|
{
|
||||||
init(_core);
|
init(_core);
|
||||||
regs->cpu_exception = Cpu::Context::RESET;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
void Kernel::Thread::_call_update_pd()
|
void Kernel::Thread::_call_update_pd()
|
||||||
|
@ -17,6 +17,3 @@
|
|||||||
|
|
||||||
void Genode::Arm_cpu::clean_invalidate_data_cache() {
|
void Genode::Arm_cpu::clean_invalidate_data_cache() {
|
||||||
asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); }
|
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
|
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
|
* Write back dirty lines of inner data cache and invalidate all
|
||||||
*/
|
*/
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <hw/assert.h>
|
#include <hw/assert.h>
|
||||||
|
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/vm.h>
|
#include <kernel/vm.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -163,6 +163,7 @@ class Genode::Cpu : public Arm_v7_cpu
|
|||||||
Psr::F::set(v, 1);
|
Psr::F::set(v, 1);
|
||||||
Psr::A::set(v, 1);
|
Psr::A::set(v, 1);
|
||||||
regs->cpsr = v;
|
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_3() const { return regs->r3; }
|
||||||
Kernel::Call_arg user_arg_4() const { return regs->r4; }
|
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
|
* Return if the context is in a page fault due to translation miss
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/lock.h>
|
#include <kernel/lock.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
@ -29,7 +30,7 @@ extern "C" void * _start_secondary_cpus;
|
|||||||
static volatile bool primary_cpu = true;
|
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());
|
Lock::Guard guard(data_lock());
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/perf_counter.h>
|
#include <kernel/perf_counter.h>
|
||||||
#include <kernel/lock.h>
|
#include <kernel/lock.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
@ -80,10 +80,14 @@ class Genode::Cpu : public Hw::Riscv_cpu
|
|||||||
{
|
{
|
||||||
Align_at<Context, 8> regs;
|
Align_at<Context, 8> regs;
|
||||||
|
|
||||||
/**
|
User_context()
|
||||||
* Constructor
|
{
|
||||||
|
/*
|
||||||
|
* initialize cpu_exception with something that gets ignored in
|
||||||
|
* Thread::exception
|
||||||
*/
|
*/
|
||||||
User_context();
|
regs->cpu_exception = IRQ_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support for kernel calls
|
* 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_2() const { return regs->a2; }
|
||||||
Kernel::Call_arg user_arg_3() const { return regs->a3; }
|
Kernel::Call_arg user_arg_3() const { return regs->a3; }
|
||||||
Kernel::Call_arg user_arg_4() const { return regs->a4; }
|
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
|
* From the manual
|
||||||
*
|
*
|
||||||
|
@ -52,3 +52,15 @@ _kernel_entry:
|
|||||||
la x30, kernel
|
la x30, kernel
|
||||||
|
|
||||||
jalr x30
|
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 */
|
/* core includes */
|
||||||
#include <assertion.h>
|
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/pd.h>
|
|
||||||
|
|
||||||
#include <hw/memory_map.h>
|
#include <hw/memory_map.h>
|
||||||
|
|
||||||
using namespace Kernel;
|
|
||||||
|
|
||||||
void Kernel::Cpu::init(Kernel::Pic &pic) {
|
void Kernel::Cpu::init(Kernel::Pic &pic) {
|
||||||
Stvec::write(Hw::Mm::supervisor_exception_vector().base); }
|
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.
|
* 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 <platform_pd.h>
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||||
|
@ -21,24 +21,26 @@ void Kernel::Thread::_init() { }
|
|||||||
|
|
||||||
void Thread::exception(unsigned const cpu)
|
void Thread::exception(unsigned const cpu)
|
||||||
{
|
{
|
||||||
|
using Context = Genode::Cpu::Context;
|
||||||
|
|
||||||
if (regs->is_irq())
|
if (regs->is_irq())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(regs->cpu_exception) {
|
switch(regs->cpu_exception) {
|
||||||
case Cpu::Context::ECALL_FROM_USER:
|
case Context::ECALL_FROM_USER:
|
||||||
case Cpu::Context::ECALL_FROM_SUPERVISOR:
|
case Context::ECALL_FROM_SUPERVISOR:
|
||||||
_call();
|
_call();
|
||||||
regs->ip += 4; /* set to next instruction */
|
regs->ip += 4; /* set to next instruction */
|
||||||
break;
|
break;
|
||||||
case Cpu::Context::INSTRUCTION_PAGE_FAULT:
|
case Context::INSTRUCTION_PAGE_FAULT:
|
||||||
case Cpu::Context::STORE_PAGE_FAULT:
|
case Context::STORE_PAGE_FAULT:
|
||||||
case Cpu::Context::LOAD_PAGE_FAULT:
|
case Context::LOAD_PAGE_FAULT:
|
||||||
_mmu_exception();
|
_mmu_exception();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Genode::error(*this, ": unhandled exception ", regs->cpu_exception,
|
Genode::error(*this, ": unhandled exception ", regs->cpu_exception,
|
||||||
" at ip=", (void*)regs->ip,
|
" at ip=", (void*)regs->ip,
|
||||||
" addr=", Genode::Hex(Cpu::Sbadaddr::read()));
|
" addr=", Genode::Hex(Genode::Cpu::Sbadaddr::read()));
|
||||||
_die();
|
_die();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,7 +50,7 @@ void Thread::_mmu_exception()
|
|||||||
{
|
{
|
||||||
_become_inactive(AWAITS_RESTART);
|
_become_inactive(AWAITS_RESTART);
|
||||||
_fault_pd = (addr_t)_pd->platform_pd();
|
_fault_pd = (addr_t)_pd->platform_pd();
|
||||||
_fault_addr = Cpu::Sbadaddr::read();
|
_fault_addr = Genode::Cpu::Sbadaddr::read();
|
||||||
|
|
||||||
if (_pager) _pager->submit(1);
|
if (_pager) _pager->submit(1);
|
||||||
}
|
}
|
||||||
@ -56,13 +58,13 @@ void Thread::_mmu_exception()
|
|||||||
|
|
||||||
void Thread::_call_update_pd()
|
void Thread::_call_update_pd()
|
||||||
{
|
{
|
||||||
Cpu::sfence();
|
Genode::Cpu::sfence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread::_call_update_data_region()
|
void Thread::_call_update_data_region()
|
||||||
{
|
{
|
||||||
Cpu::sfence();
|
Genode::Cpu::sfence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
Cpu::User_context::User_context() { }
|
|
||||||
|
|
||||||
void Platform::_init_io_port_alloc() { }
|
void Platform::_init_io_port_alloc() { }
|
||||||
|
|
||||||
void Platform::_init_additional() { }
|
void Platform::_init_additional() { }
|
||||||
|
@ -128,11 +128,6 @@ class Genode::Cpu
|
|||||||
|
|
||||||
Fpu & fpu() { return _fpu; }
|
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
|
* Return wether to retry an undefined user instruction after this call
|
||||||
*/
|
*/
|
||||||
|
@ -167,3 +167,15 @@
|
|||||||
.space 64
|
.space 64
|
||||||
|
|
||||||
_define_gdt TSS
|
_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.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <base/log.h>
|
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/pd.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)
|
void Kernel::Cpu::init(Pic &pic)
|
||||||
{
|
{
|
||||||
|
Cpu::Gdt::init();
|
||||||
Idt::init();
|
Idt::init();
|
||||||
Tss::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()); }
|
c.init((addr_t)translation_table(), this == Kernel::core_pd()); }
|
||||||
|
@ -41,7 +41,7 @@ void Kernel::Thread::_mmu_exception()
|
|||||||
{
|
{
|
||||||
_become_inactive(AWAITS_RESTART);
|
_become_inactive(AWAITS_RESTART);
|
||||||
_fault_pd = (addr_t)_pd->platform_pd();
|
_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_writes = (regs->errcode & ERR_P) && (regs->errcode & ERR_W);
|
||||||
_fault_exec = (regs->errcode & ERR_P) && (regs->errcode & ERR_I);
|
_fault_exec = (regs->errcode & ERR_P) && (regs->errcode & ERR_I);
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
|
|
||||||
using namespace Kernel;
|
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…
x
Reference in New Issue
Block a user