mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
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:
parent
f17727b70b
commit
9090311a06
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) { }
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user