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(); void acknowledge_wakeup();
/**
* Reply to an exception IPC
*/
void acknowledge_exception();
/** /**
* Return thread ID of last faulter * Return thread ID of last faulter
*/ */
@ -183,9 +188,15 @@ namespace Genode {
/** /**
* Copy the exception registers from the last exception * 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> #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->ip = _regs.pc;
state->sp = _regs.sp; state->sp = _regs.sp;
state->r0 = _regs.r[0]; state->r0 = _regs.r[0];
state->r1 = _regs.r[1]; state->r1 = _regs.r[1];
state->r2 = _regs.r[2]; state->r2 = _regs.r[2];
state->r3 = _regs.r[3]; state->r3 = _regs.r[3];
state->r4 = _regs.r[4]; state->r4 = _regs.r[4];
state->r5 = _regs.r[5]; state->r5 = _regs.r[5];
state->r6 = _regs.r[6]; state->r6 = _regs.r[6];
state->r7 = _regs.r[7]; state->r7 = _regs.r[7];
state->r8 = _regs.r[8]; state->r8 = _regs.r[8];
state->r9 = _regs.r[9]; state->r9 = _regs.r[9];
state->r10 = _regs.r[10]; state->r10 = _regs.r[10];
state->r11 = _regs.r[11]; state->r11 = _regs.r[11];
state->r12 = _regs.r[12]; state->r12 = _regs.r[12];
state->lr = _regs.ulr; state->lr = _regs.ulr;
state->cpsr = _regs.cpsr; 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() Ipc_pager::Ipc_pager()
: Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]), : Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
_badge(0) { } _badge(0) { }

View File

@ -17,7 +17,7 @@
#include <base/ipc_pager.h> #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->ip = _regs.ip;
state->sp = _regs.sp; state->sp = _regs.sp;
@ -33,3 +33,22 @@ void Genode::Ipc_pager::copy_regs(Thread_state *state)
state->eflags = _regs.flags; state->eflags = _regs.flags;
state->trapno = _regs.trapno; 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> #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->ip = _regs.ip;
state->sp = _regs.sp; state->sp = _regs.sp;
@ -40,3 +40,29 @@ void Genode::Ipc_pager::copy_regs(Thread_state *state)
state->eflags = _regs.flags; state->eflags = _regs.flags;
state->trapno = _regs.trapno; 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()) { if (pager.is_exception()) {
Lock::Guard guard(obj->state.lock); Lock::Guard guard(obj->state.lock);
pager.copy_regs(&obj->state); pager.get_regs(&obj->state);
obj->state.exceptions++; obj->state.exceptions++;
obj->state.in_exception = true; obj->state.in_exception = true;
obj->submit_exception_signal(); obj->submit_exception_signal();
@ -105,15 +105,17 @@ void Pager_activation_base::entry()
pager.set_reply_dst(Native_thread()); pager.set_reply_dst(Native_thread());
pager.acknowledge_wakeup(); pager.acknowledge_wakeup();
/* revert exception flag */
{ {
Lock::Guard guard(obj->state.lock); Lock::Guard guard(obj->state.lock);
/* revert exception flag */
obj->state.in_exception = false; obj->state.in_exception = false;
/* set new register contents */
pager.set_regs(obj->state);
} }
/* send wake up message to requested thread */ /* send wake up message to requested thread */
pager.set_reply_dst(obj->badge()); pager.set_reply_dst(obj->badge());
pager.acknowledge_wakeup(); pager.acknowledge_exception();
break; break;
} }
@ -124,8 +126,7 @@ void Pager_activation_base::entry()
case Ipc_pager::PAUSE: case Ipc_pager::PAUSE:
{ {
Lock::Guard guard(obj->state.lock); Lock::Guard guard(obj->state.lock);
pager.copy_regs(&obj->state); pager.get_regs(&obj->state);
obj->state.exceptions++; obj->state.exceptions++;
obj->state.in_exception = true; 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) void Platform_thread::state(Thread_state s)
{ {
PDBG("Not implemented"); if (_pager_obj)
throw Cpu_session::State_access_failed(); _pager_obj->state = s;
} }