mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 15:29:57 +00:00
parent
1c6c90fed5
commit
15a56bd682
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Syscall declarations specific for ARM V7A systems
|
||||
* \brief Syscall declarations specific for ARM systems
|
||||
* \author Martin Stein
|
||||
* \date 2011-11-30
|
||||
*/
|
||||
@ -21,6 +21,19 @@ namespace Kernel
|
||||
{
|
||||
typedef Genode::uint32_t Syscall_arg;
|
||||
typedef Genode::uint32_t Syscall_ret;
|
||||
|
||||
/**
|
||||
* Thread registers that can be accessed via Access_thread_regs
|
||||
*/
|
||||
struct Access_thread_regs_id
|
||||
{
|
||||
enum {
|
||||
R0, R1, R2, R3, R4,
|
||||
R5, R6, R7, R8, R9,
|
||||
R10, R11, R12, SP, LR,
|
||||
IP, CPSR, CPU_EXCEPTION
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__ARM__BASE__SYSCALL_H_ */
|
@ -15,7 +15,7 @@
|
||||
#define _INCLUDE__KERNEL__SYSCALLS_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/syscall_types.h>
|
||||
#include <base/syscall_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -49,8 +49,7 @@ namespace Kernel
|
||||
GET_THREAD = 5,
|
||||
CURRENT_THREAD_ID = 6,
|
||||
YIELD_THREAD = 7,
|
||||
READ_THREAD_STATE = 18,
|
||||
WRITE_THREAD_STATE = 19,
|
||||
ACCESS_THREAD_REGS = 37,
|
||||
|
||||
/* interprocess communication */
|
||||
REQUEST_AND_WAIT = 8,
|
||||
@ -389,31 +388,47 @@ namespace Kernel
|
||||
|
||||
|
||||
/**
|
||||
* Copy the current state of a thread to the callers UTCB
|
||||
* Access plain member variables of a kernel thread-object
|
||||
*
|
||||
* \param thread_id ID of the targeted thread
|
||||
* \param thread_id kernel name of the targeted thread
|
||||
* \param reads amount of read operations
|
||||
* \param writes amount of write operations
|
||||
* \param read_values base of value buffer for read operations
|
||||
* \param write_values base of value buffer for write operations
|
||||
*
|
||||
* Restricted to core threads. One can also read from its own context,
|
||||
* or any thread that is active in the meantime. In these cases
|
||||
* be aware of the fact, that the result reflects the thread
|
||||
* state that were backed at the last kernel entry of the thread.
|
||||
* The copy might be incoherent when this function returns because
|
||||
* the caller might get scheduled away before then.
|
||||
* \retval 0 all operations done
|
||||
* \retval >0 amount of undone operations
|
||||
* \retval -1 failed to start processing operations
|
||||
*
|
||||
* Restricted to core threads. Operations are processed in order of the
|
||||
* appearance of the register names in the callers UTCB. If reads = 0,
|
||||
* read_values is of no relevance. If writes = 0, write_values is of no
|
||||
* relevance.
|
||||
*
|
||||
* Expected structure at the callers UTCB base:
|
||||
*
|
||||
* 0 * sizeof(addr_t): read register name #1
|
||||
* ... ...
|
||||
* (reads - 1) * sizeof(addr_t): read register name #reads
|
||||
* (reads - 0) * sizeof(addr_t): write register name #1
|
||||
* ... ...
|
||||
* (reads + writes - 1) * sizeof(addr_t): write register name #writes
|
||||
*
|
||||
* Expected structure at write_values:
|
||||
*
|
||||
* 0 * sizeof(addr_t): write value #1
|
||||
* ... ...
|
||||
* (writes - 1) * sizeof(addr_t): write value #writes
|
||||
*/
|
||||
inline void read_thread_state(unsigned const thread_id) {
|
||||
syscall(READ_THREAD_STATE, (Syscall_arg)thread_id); }
|
||||
|
||||
|
||||
/**
|
||||
* Override the state of a thread with the callers UTCB content
|
||||
*
|
||||
* \param thread_id ID of the targeted thread
|
||||
*
|
||||
* Restricted to core threads. One can also write to its own context, or
|
||||
* to that of a thread that is active in the meantime.
|
||||
*/
|
||||
inline void write_thread_state(unsigned const thread_id) {
|
||||
syscall(WRITE_THREAD_STATE, (Syscall_arg)thread_id); }
|
||||
inline int access_thread_regs(unsigned const thread_id,
|
||||
unsigned const reads,
|
||||
unsigned const writes,
|
||||
addr_t * const read_values,
|
||||
addr_t * const write_values)
|
||||
{
|
||||
return syscall(ACCESS_THREAD_REGS, thread_id, reads, writes,
|
||||
(Syscall_arg)read_values, (Syscall_arg)write_values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -161,3 +161,22 @@ Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** CPU-state utilities **
|
||||
*************************/
|
||||
|
||||
typedef Access_thread_regs_id Id;
|
||||
|
||||
static addr_t const _cpu_state_regs[] = {
|
||||
Id::R0, Id::R1, Id::R2, Id::R3, Id::R4, Id::R5, Id::R6, Id::R7,
|
||||
Id::R8, Id::R9, Id::R10, Id::R11, Id::R12, Id::SP, Id::LR, Id::IP,
|
||||
Id::CPSR, Id::CPU_EXCEPTION };
|
||||
|
||||
addr_t const * cpu_state_regs() { return _cpu_state_regs; }
|
||||
|
||||
|
||||
size_t cpu_state_regs_length()
|
||||
{
|
||||
return sizeof(_cpu_state_regs)/sizeof(_cpu_state_regs[0]);
|
||||
}
|
||||
|
47
base-hw/src/core/arm/cpu_support.cc
Normal file
47
base-hw/src/core/arm/cpu_support.cc
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief CPU specific implementations of core
|
||||
* \author Martin Stein
|
||||
* \date 2013-11-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/thread.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
|
||||
/********************
|
||||
** Kernel::Thread **
|
||||
********************/
|
||||
|
||||
addr_t * Kernel::Thread::_reg(addr_t const id) const
|
||||
{
|
||||
static addr_t * const _regs[] = {
|
||||
(addr_t *)&r0,
|
||||
(addr_t *)&r1,
|
||||
(addr_t *)&r2,
|
||||
(addr_t *)&r3,
|
||||
(addr_t *)&r4,
|
||||
(addr_t *)&r5,
|
||||
(addr_t *)&r6,
|
||||
(addr_t *)&r7,
|
||||
(addr_t *)&r8,
|
||||
(addr_t *)&r9,
|
||||
(addr_t *)&r10,
|
||||
(addr_t *)&r11,
|
||||
(addr_t *)&r12,
|
||||
(addr_t *)&sp,
|
||||
(addr_t *)&lr,
|
||||
(addr_t *)&ip,
|
||||
(addr_t *)&cpsr,
|
||||
(addr_t *)&cpu_exception
|
||||
};
|
||||
return id < sizeof(_regs)/sizeof(_regs[0]) ? _regs[id] : 0;
|
||||
}
|
@ -13,7 +13,8 @@ INC_DIR += $(REP_DIR)/src/core/arndale
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -24,6 +25,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/arndale
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -469,52 +469,6 @@ namespace Arm
|
||||
uint32_t cidr; /* context ID register backup */
|
||||
uint32_t section_table; /* base address of applied section table */
|
||||
|
||||
/**
|
||||
* Copy CPU state data to 'c'
|
||||
*/
|
||||
void read_cpu_state(Cpu_state * const s)
|
||||
{
|
||||
s->r0 = r0;
|
||||
s->r1 = r1;
|
||||
s->r2 = r2;
|
||||
s->r3 = r3;
|
||||
s->r4 = r4;
|
||||
s->r5 = r5;
|
||||
s->r6 = r6;
|
||||
s->r7 = r7;
|
||||
s->r8 = r8;
|
||||
s->r9 = r9;
|
||||
s->r10 = r10;
|
||||
s->r11 = r11;
|
||||
s->r12 = r12;
|
||||
s->sp = sp;
|
||||
s->lr = lr;
|
||||
s->ip = ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override CPU state with data from 'c'
|
||||
*/
|
||||
void write_cpu_state(Cpu_state * const s)
|
||||
{
|
||||
r0 = s->r0;
|
||||
r1 = s->r1;
|
||||
r2 = s->r2;
|
||||
r3 = s->r3;
|
||||
r4 = s->r4;
|
||||
r5 = s->r5;
|
||||
r6 = s->r6;
|
||||
r7 = s->r7;
|
||||
r8 = s->r8;
|
||||
r9 = s->r9;
|
||||
r10 = s->r10;
|
||||
r11 = s->r11;
|
||||
r12 = s->r12;
|
||||
sp = s->sp;
|
||||
lr = s->lr;
|
||||
ip = s->ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base of assigned translation lookaside buffer
|
||||
*/
|
||||
|
@ -12,7 +12,8 @@ INC_DIR += $(REP_DIR)/src/core/imx31
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -23,6 +24,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/imx31
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v6
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -13,7 +13,8 @@ INC_DIR += $(REP_DIR)/src/core/imx53
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -24,6 +25,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/imx53
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -128,20 +128,12 @@ namespace Genode {
|
||||
/**
|
||||
* Get raw thread state
|
||||
*/
|
||||
Thread_state state()
|
||||
{
|
||||
Kernel::read_thread_state(id());
|
||||
return *(Thread_state *)Thread_base::myself()->utcb()->base();
|
||||
};
|
||||
Thread_state state();
|
||||
|
||||
/**
|
||||
* Override raw thread state
|
||||
*/
|
||||
void state(Thread_state s)
|
||||
{
|
||||
*(Thread_state *)Thread_base::myself()->utcb()->base() = s;
|
||||
Kernel::write_thread_state(id());
|
||||
};
|
||||
void state(Thread_state s);
|
||||
|
||||
/**
|
||||
* Return unique identification of this thread as faulter
|
||||
|
@ -680,32 +680,6 @@ void Thread::_syscall_print_char()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
void Thread::_syscall_read_thread_state()
|
||||
{
|
||||
assert(_core());
|
||||
Thread * const t = Thread::pool()->object(user_arg_1());
|
||||
if (!t) PDBG("Targeted thread unknown");
|
||||
Thread_state * const ts = (Thread_state *)_phys_utcb->base();
|
||||
t->Cpu::Context::read_cpu_state(ts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
void Thread::_syscall_write_thread_state()
|
||||
{
|
||||
assert(_core());
|
||||
Thread * const t = Thread::pool()->object(user_arg_1());
|
||||
if (!t) PDBG("Targeted thread unknown");
|
||||
Thread_state * const ts = (Thread_state *)_phys_utcb->base();
|
||||
t->Cpu::Context::write_cpu_state(ts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for this thread, for details see 'syscall.h'
|
||||
*/
|
||||
@ -976,8 +950,6 @@ void Thread::_syscall()
|
||||
case GET_THREAD: _syscall_get_thread(); return;
|
||||
case CURRENT_THREAD_ID: _syscall_current_thread_id(); return;
|
||||
case YIELD_THREAD: _syscall_yield_thread(); return;
|
||||
case READ_THREAD_STATE: _syscall_read_thread_state(); return;
|
||||
case WRITE_THREAD_STATE: _syscall_write_thread_state(); return;
|
||||
case REQUEST_AND_WAIT: _syscall_request_and_wait(); return;
|
||||
case REPLY: _syscall_reply(); return;
|
||||
case WAIT_FOR_REQUEST: _syscall_wait_for_request(); return;
|
||||
@ -998,6 +970,7 @@ void Thread::_syscall()
|
||||
case RUN_VM: _syscall_run_vm(); return;
|
||||
case PAUSE_VM: _syscall_pause_vm(); return;
|
||||
case KILL_PD: _syscall_kill_pd(); return;
|
||||
case ACCESS_THREAD_REGS: _syscall_access_thread_regs(); return;
|
||||
default:
|
||||
PERR("invalid syscall");
|
||||
_stop();
|
||||
|
@ -135,6 +135,38 @@ class Kernel::Thread
|
||||
*/
|
||||
void _syscall();
|
||||
|
||||
/**
|
||||
* Read a thread register
|
||||
*
|
||||
* \param id kernel name of targeted thread register
|
||||
* \param value read-value buffer
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
int _read_reg(addr_t const id, addr_t & value) const;
|
||||
|
||||
/**
|
||||
* Override a thread register
|
||||
*
|
||||
* \param id kernel name of targeted thread register
|
||||
* \param value write-value buffer
|
||||
*
|
||||
* \retval 0 succeeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
int _write_reg(addr_t const id, addr_t const value);
|
||||
|
||||
/**
|
||||
* Map kernel names of thread registers to the corresponding data
|
||||
*
|
||||
* \param id kernel name of thread register
|
||||
*
|
||||
* \retval 0 failed
|
||||
* \retval >0 pointer to register content
|
||||
*/
|
||||
addr_t * _reg(addr_t const id) const;
|
||||
|
||||
|
||||
/***************************************************
|
||||
** Syscall backends, for details see 'syscall.h' **
|
||||
@ -158,8 +190,6 @@ class Kernel::Thread
|
||||
void _syscall_update_pd();
|
||||
void _syscall_update_region();
|
||||
void _syscall_print_char();
|
||||
void _syscall_read_thread_state();
|
||||
void _syscall_write_thread_state();
|
||||
void _syscall_new_signal_receiver();
|
||||
void _syscall_new_signal_context();
|
||||
void _syscall_await_signal();
|
||||
@ -171,6 +201,7 @@ class Kernel::Thread
|
||||
void _syscall_new_vm();
|
||||
void _syscall_run_vm();
|
||||
void _syscall_pause_vm();
|
||||
void _syscall_access_thread_regs();
|
||||
|
||||
|
||||
/***************************
|
||||
|
@ -13,7 +13,8 @@ INC_DIR += $(REP_DIR)/src/core/panda
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -24,6 +25,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/panda
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -13,7 +13,8 @@ INC_DIR += $(REP_DIR)/src/core/pbxa9
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -24,6 +25,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/pbxa9
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -212,3 +212,38 @@ Genode::Pager_object * Platform_thread::pager()
|
||||
{
|
||||
return _rm_client ? static_cast<Pager_object *>(_rm_client) : 0;
|
||||
}
|
||||
|
||||
|
||||
addr_t const * cpu_state_regs();
|
||||
|
||||
size_t cpu_state_regs_length();
|
||||
|
||||
|
||||
Thread_state Platform_thread::state()
|
||||
{
|
||||
static addr_t const * const src = cpu_state_regs();
|
||||
static size_t const length = cpu_state_regs_length();
|
||||
static size_t const size = length * sizeof(src[0]);
|
||||
void * dst = Thread_base::myself()->utcb()->base();
|
||||
Genode::memcpy(dst, src, size);
|
||||
Thread_state thread_state;
|
||||
Cpu_state * const cpu_state = static_cast<Cpu_state *>(&thread_state);
|
||||
if (Kernel::access_thread_regs(id(), length, 0, (addr_t *)cpu_state, 0)) {
|
||||
throw Cpu_session::State_access_failed();
|
||||
}
|
||||
return thread_state;
|
||||
};
|
||||
|
||||
|
||||
void Platform_thread::state(Thread_state thread_state)
|
||||
{
|
||||
static addr_t const * const src = cpu_state_regs();
|
||||
static size_t const length = cpu_state_regs_length();
|
||||
static size_t const size = length * sizeof(src[0]);
|
||||
void * dst = Thread_base::myself()->utcb()->base();
|
||||
Genode::memcpy(dst, src, size);
|
||||
Cpu_state * const cpu_state = static_cast<Cpu_state *>(&thread_state);
|
||||
if (Kernel::access_thread_regs(id(), 0, length, 0, (addr_t *)cpu_state)) {
|
||||
throw Cpu_session::State_access_failed();
|
||||
}
|
||||
};
|
||||
|
@ -12,7 +12,8 @@ INC_DIR += $(REP_DIR)/src/core/rpi
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += mode_transition.s \
|
||||
@ -23,6 +24,7 @@ SRC_S += mode_transition.s \
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/rpi
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v6
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
|
||||
#
|
||||
|
@ -9,8 +9,9 @@
|
||||
INC_DIR += $(REP_DIR)/src/core/vea9x4
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc
|
||||
SRC_CC += platform_services.cc \
|
||||
platform_support.cc \
|
||||
cpu_support.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += crt0.s \
|
||||
@ -31,6 +32,7 @@ endif
|
||||
# declare source paths
|
||||
vpath mode_transition.s $(REP_DIR)/src/core/arm_v7
|
||||
vpath crt0.s $(REP_DIR)/src/core/arm
|
||||
vpath cpu_support.cc $(REP_DIR)/src/core/arm
|
||||
|
||||
# include less specific target parts
|
||||
include $(REP_DIR)/src/core/target.inc
|
||||
|
Loading…
x
Reference in New Issue
Block a user