base-foc: enable CPU state modification

With this patch, the register contents of a paused thread (which is not
currently executing a syscall) can get modified by the
'Cpu_session::state()' function.

Fixes #896.
This commit is contained in:
Christian Prochaska 2013-09-26 11:49:00 +02:00 committed by Norman Feske
parent f17727b70b
commit 9090311a06
7 changed files with 116 additions and 28 deletions

View File

@ -156,6 +156,11 @@ namespace Genode {
*/
void acknowledge_wakeup();
/**
* Reply to an exception IPC
*/
void acknowledge_exception();
/**
* Return thread ID of last faulter
*/
@ -183,9 +188,15 @@ namespace Genode {
/**
* Copy the exception registers from the last exception
* to the given thread_state object.
* to the given Thread_state object.
*/
void copy_regs(Thread_state *state);
void get_regs(Thread_state *state);
/*
* Copy the exception reply registers from the given
* Thread_state object
*/
void set_regs(Thread_state state);
};
}

View File

@ -17,23 +17,46 @@
#include <base/ipc_pager.h>
void Genode::Ipc_pager::copy_regs(Thread_state *state)
void Genode::Ipc_pager::get_regs(Thread_state *state)
{
state->ip = _regs.pc;
state->sp = _regs.sp;
state->r0 = _regs.r[0];
state->r1 = _regs.r[1];
state->r2 = _regs.r[2];
state->r3 = _regs.r[3];
state->r4 = _regs.r[4];
state->r5 = _regs.r[5];
state->r6 = _regs.r[6];
state->r7 = _regs.r[7];
state->r8 = _regs.r[8];
state->r9 = _regs.r[9];
state->r10 = _regs.r[10];
state->r11 = _regs.r[11];
state->r12 = _regs.r[12];
state->lr = _regs.ulr;
state->ip = _regs.pc;
state->sp = _regs.sp;
state->r0 = _regs.r[0];
state->r1 = _regs.r[1];
state->r2 = _regs.r[2];
state->r3 = _regs.r[3];
state->r4 = _regs.r[4];
state->r5 = _regs.r[5];
state->r6 = _regs.r[6];
state->r7 = _regs.r[7];
state->r8 = _regs.r[8];
state->r9 = _regs.r[9];
state->r10 = _regs.r[10];
state->r11 = _regs.r[11];
state->r12 = _regs.r[12];
state->lr = _regs.ulr;
state->cpsr = _regs.cpsr;
}
void Genode::Ipc_pager::set_regs(Thread_state state)
{
_regs.pc = state.ip;
_regs.sp = state.sp;
_regs.r[0] = state.r0;
_regs.r[1] = state.r1;
_regs.r[2] = state.r2;
_regs.r[3] = state.r3;
_regs.r[4] = state.r4;
_regs.r[5] = state.r5;
_regs.r[6] = state.r6;
_regs.r[7] = state.r7;
_regs.r[8] = state.r8;
_regs.r[9] = state.r9;
_regs.r[10] = state.r10;
_regs.r[11] = state.r11;
_regs.r[12] = state.r12;
_regs.ulr = state.lr;
_regs.cpsr = state.cpsr;
}

View File

@ -112,6 +112,14 @@ void Ipc_pager::acknowledge_wakeup()
}
void Ipc_pager::acknowledge_exception()
{
memcpy(l4_utcb_exc(), &_regs, sizeof(l4_exc_regs_t));
l4_cap_idx_t dst = Fiasco::Capability::valid(_last) ? _last : L4_SYSF_REPLY;
l4_ipc_send(dst, l4_utcb(), l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0), L4_IPC_SEND_TIMEOUT_0);
}
Ipc_pager::Ipc_pager()
: Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
_badge(0) { }

View File

@ -17,7 +17,7 @@
#include <base/ipc_pager.h>
void Genode::Ipc_pager::copy_regs(Thread_state *state)
void Genode::Ipc_pager::get_regs(Genode::Thread_state *state)
{
state->ip = _regs.ip;
state->sp = _regs.sp;
@ -33,3 +33,22 @@ void Genode::Ipc_pager::copy_regs(Thread_state *state)
state->eflags = _regs.flags;
state->trapno = _regs.trapno;
}
void Genode::Ipc_pager::set_regs(Genode::Thread_state state)
{
_regs.ip = state.ip;
_regs.sp = state.sp;
_regs.edi = state.edi;
_regs.esi = state.esi;
_regs.ebp = state.ebp;
_regs.ebx = state.ebx;
_regs.edx = state.edx;
_regs.ecx = state.ecx;
_regs.eax = state.eax;
_regs.gs = state.gs;
_regs.fs = state.fs;
_regs.flags = state.eflags;
_regs.trapno = state.trapno;
}

View File

@ -17,7 +17,7 @@
#include <base/ipc_pager.h>
void Genode::Ipc_pager::copy_regs(Thread_state *state)
void Genode::Ipc_pager::get_regs(Thread_state *state)
{
state->ip = _regs.ip;
state->sp = _regs.sp;
@ -40,3 +40,29 @@ void Genode::Ipc_pager::copy_regs(Thread_state *state)
state->eflags = _regs.flags;
state->trapno = _regs.trapno;
}
void Genode::Ipc_pager::set_regs(Thread_state state)
{
_regs.ip = state.ip;
_regs.sp = state.sp;
_regs.r8 = state.r8;
_regs.r9 = state.r9;
_regs.r10 = state.r10;
_regs.r11 = state.r11;
_regs.r12 = state.r12;
_regs.r13 = state.r13;
_regs.r14 = state.r14;
_regs.r15 = state.r15;
_regs.rax = state.rax;
_regs.rbx = state.rbx;
_regs.rcx = state.rcx;
_regs.rdx = state.rdx;
_regs.rdi = state.rdi;
_regs.rsi = state.rsi;
_regs.rbp = state.rbp;
_regs.ss = state.ss;
_regs.flags = state.eflags;
_regs.trapno = state.trapno;
}

View File

@ -71,7 +71,7 @@ void Pager_activation_base::entry()
{
if (pager.is_exception()) {
Lock::Guard guard(obj->state.lock);
pager.copy_regs(&obj->state);
pager.get_regs(&obj->state);
obj->state.exceptions++;
obj->state.in_exception = true;
obj->submit_exception_signal();
@ -105,15 +105,17 @@ void Pager_activation_base::entry()
pager.set_reply_dst(Native_thread());
pager.acknowledge_wakeup();
/* revert exception flag */
{
Lock::Guard guard(obj->state.lock);
/* revert exception flag */
obj->state.in_exception = false;
/* set new register contents */
pager.set_regs(obj->state);
}
/* send wake up message to requested thread */
pager.set_reply_dst(obj->badge());
pager.acknowledge_wakeup();
pager.acknowledge_exception();
break;
}
@ -124,8 +126,7 @@ void Pager_activation_base::entry()
case Ipc_pager::PAUSE:
{
Lock::Guard guard(obj->state.lock);
pager.copy_regs(&obj->state);
pager.get_regs(&obj->state);
obj->state.exceptions++;
obj->state.in_exception = true;

View File

@ -174,8 +174,8 @@ void Platform_thread::pager(Pager_object *pager_obj)
void Platform_thread::state(Thread_state s)
{
PDBG("Not implemented");
throw Cpu_session::State_access_failed();
if (_pager_obj)
_pager_obj->state = s;
}