base-hw: Read and write whole thread states.

By now there is no use case for read/write a single register
of a thread state. Thus the new syscalls 'read_thread_state' and
'write_thread_state' replace the old ones 'read_register' and
'write_register'.
This commit is contained in:
Martin Stein 2012-11-12 16:52:12 +01:00 committed by Norman Feske
parent 6cb89f79e3
commit 4dadd6a437
3 changed files with 71 additions and 104 deletions

View File

@ -43,8 +43,8 @@ namespace Kernel
GET_THREAD = 5,
CURRENT_THREAD_ID = 6,
YIELD_THREAD = 7,
READ_REGISTER = 18,
WRITE_REGISTER = 19,
READ_THREAD_STATE = 18,
WRITE_THREAD_STATE = 19,
/* interprocess communication */
REQUEST_AND_WAIT = 8,
@ -380,41 +380,31 @@ namespace Kernel
/**
* Get the current value of a register of a specific CPU context
* Copy the current state of a thread to the callers UTCB
*
* \param thread_id ID of the thread that owns the targeted context
* \param reg_id platform-specific ID of the targeted register
* \param thread_id ID of the targeted thread
*
* 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 context
* 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.
*/
inline unsigned long read_register(unsigned long const thread_id,
unsigned long const reg_id)
{
return syscall(READ_REGISTER, (Syscall_arg)thread_id,
(Syscall_arg)reg_id);
}
inline void read_thread_state(unsigned const thread_id) {
syscall(READ_THREAD_STATE, (Syscall_arg)thread_id); }
/**
* Write a value to a register of a specific CPU context
* Override the state of a thread with the callers UTCB content
*
* \param thread_id ID of the thread that owns the targeted context
* \param reg_id platform-specific ID of the targeted register
* \param value value that shall be written to the register
* \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_register(unsigned long const thread_id,
unsigned long const reg_id,
unsigned long const value)
{
syscall(WRITE_REGISTER, (Syscall_arg)thread_id, (Syscall_arg)reg_id,
(Syscall_arg)value);
}
inline void write_thread_state(unsigned const thread_id) {
syscall(WRITE_THREAD_STATE, (Syscall_arg)thread_id); }
/**

View File

@ -480,6 +480,52 @@ namespace Arm
addr_t tlb() const { return section_table; }
void protection_domain(unsigned const id) { cidr = id; }
/**
* 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;
}
};
/**
@ -513,66 +559,6 @@ namespace Arm
unsigned user_arg_6() const { return r6; }
unsigned user_arg_7() const { return r7; }
/**
* Read a general purpose register
*
* \param id ID of the targeted register
* \param v Holds register value if this returns 1
*/
bool get_gpr(unsigned id, unsigned & v) const
{
switch(id)
{
case 0: v = r0; return 1;
case 1: v = r1; return 1;
case 2: v = r2; return 1;
case 3: v = r3; return 1;
case 4: v = r4; return 1;
case 5: v = r5; return 1;
case 6: v = r6; return 1;
case 7: v = r7; return 1;
case 8: v = r8; return 1;
case 9: v = r9; return 1;
case 10: v = r10; return 1;
case 11: v = r11; return 1;
case 12: v = r12; return 1;
case 13: v = sp; return 1;
case 14: v = lr; return 1;
case 15: v = ip; return 1;
}
return 0;
}
/**
* Override a general purpose register
*
* \param id ID of the targeted register
* \param v Has been written to register if this returns 1
*/
bool set_gpr(unsigned id, unsigned const v)
{
switch(id)
{
case 0: r0 = v; return 1;
case 1: r1 = v; return 1;
case 2: r2 = v; return 1;
case 3: r3 = v; return 1;
case 4: r4 = v; return 1;
case 5: r5 = v; return 1;
case 6: r6 = v; return 1;
case 7: r7 = v; return 1;
case 8: r8 = v; return 1;
case 9: r9 = v; return 1;
case 10: r10 = v; return 1;
case 11: r11 = v; return 1;
case 12: r12 = v; return 1;
case 13: sp = v; return 1;
case 14: lr = v; return 1;
case 15: ip = v; return 1;
}
return 0;
}
/**
* Check if a pagefault has occured due to a translation miss
*

View File

@ -27,6 +27,7 @@
#include <cpu/cpu_state.h>
#include <util/fifo.h>
#include <util/avl_tree.h>
#include <base/thread_state.h>
/* core includes */
#include <kernel_support.h>
@ -54,6 +55,7 @@ extern Genode::addr_t _mt_master_context_end;
namespace Kernel
{
/* import Genode types */
typedef Genode::Thread_state Thread_state;
typedef Genode::size_t size_t;
typedef Genode::addr_t addr_t;
typedef Genode::umword_t umword_t;
@ -1899,37 +1901,26 @@ namespace Kernel
/**
* Do specific syscall for 'user', for details see 'syscall.h'
*/
void do_read_register(Thread * const user)
void do_read_thread_state(Thread * const user)
{
/* check permissions */
assert(user->pd_id() == core_id());
/* get targeted thread */
Thread * const t = Thread::pool()->object(user->user_arg_1());
assert(t);
/* return requested register */
unsigned gpr;
assert(t->get_gpr(user->user_arg_2(), gpr));
user->user_arg_0(gpr);
if (!t) PDBG("Targeted thread unknown");
Thread_state * const ts = (Thread_state *)user->phys_utcb()->base();
t->Cpu::Context::read_cpu_state(ts);
}
/**
* Do specific syscall for 'user', for details see 'syscall.h'
*/
void do_write_register(Thread * const user)
void do_write_thread_state(Thread * const user)
{
/* check permissions */
assert(user->pd_id() == core_id());
/* get targeted thread */
Thread * const t = Thread::pool()->object(user->user_arg_1());
assert(t);
/* write to requested register */
unsigned const gpr = user->user_arg_3();
assert(t->set_gpr(user->user_arg_2(), gpr));
if (!t) PDBG("Targeted thread unknown");
Thread_state * const ts = (Thread_state *)user->phys_utcb()->base();
t->Cpu::Context::write_cpu_state(ts);
}
@ -2090,8 +2081,8 @@ namespace Kernel
/* 15 */ do_await_irq,
/* 16 */ do_free_irq,
/* 17 */ do_print_char,
/* 18 */ do_read_register,
/* 19 */ do_write_register,
/* 18 */ do_read_thread_state,
/* 19 */ do_write_thread_state,
/* 20 */ do_new_signal_receiver,
/* 21 */ do_new_signal_context,
/* 22 */ do_await_signal,