From 9090311a0657228c5d0d888bbf3d43accdb9a0c1 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 26 Sep 2013 11:49:00 +0200 Subject: [PATCH] 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. --- base-foc/include/base/ipc_pager.h | 15 ++++++- base-foc/src/base/ipc/arm/pager.cc | 57 +++++++++++++++++++-------- base-foc/src/base/ipc/pager.cc | 8 ++++ base-foc/src/base/ipc/x86_32/pager.cc | 21 +++++++++- base-foc/src/base/ipc/x86_64/pager.cc | 28 ++++++++++++- base-foc/src/base/pager/pager.cc | 11 +++--- base-foc/src/core/platform_thread.cc | 4 +- 7 files changed, 116 insertions(+), 28 deletions(-) diff --git a/base-foc/include/base/ipc_pager.h b/base-foc/include/base/ipc_pager.h index 12280b63e..0a4ddd20a 100644 --- a/base-foc/include/base/ipc_pager.h +++ b/base-foc/include/base/ipc_pager.h @@ -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); }; } diff --git a/base-foc/src/base/ipc/arm/pager.cc b/base-foc/src/base/ipc/arm/pager.cc index ccea4a3c9..fde164d32 100644 --- a/base-foc/src/base/ipc/arm/pager.cc +++ b/base-foc/src/base/ipc/arm/pager.cc @@ -17,23 +17,46 @@ #include -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; +} + diff --git a/base-foc/src/base/ipc/pager.cc b/base-foc/src/base/ipc/pager.cc index 99116ef6d..fc1ad7c45 100644 --- a/base-foc/src/base/ipc/pager.cc +++ b/base-foc/src/base/ipc/pager.cc @@ -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) { } diff --git a/base-foc/src/base/ipc/x86_32/pager.cc b/base-foc/src/base/ipc/x86_32/pager.cc index 3e99a5ca9..7ce713c76 100644 --- a/base-foc/src/base/ipc/x86_32/pager.cc +++ b/base-foc/src/base/ipc/x86_32/pager.cc @@ -17,7 +17,7 @@ #include -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; +} + diff --git a/base-foc/src/base/ipc/x86_64/pager.cc b/base-foc/src/base/ipc/x86_64/pager.cc index e2ad87a5e..c49638c16 100644 --- a/base-foc/src/base/ipc/x86_64/pager.cc +++ b/base-foc/src/base/ipc/x86_64/pager.cc @@ -17,7 +17,7 @@ #include -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; +} + diff --git a/base-foc/src/base/pager/pager.cc b/base-foc/src/base/pager/pager.cc index d8ac77b45..5121f2738 100644 --- a/base-foc/src/base/pager/pager.cc +++ b/base-foc/src/base/pager/pager.cc @@ -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; diff --git a/base-foc/src/core/platform_thread.cc b/base-foc/src/core/platform_thread.cc index ab64cc9e6..151104122 100644 --- a/base-foc/src/core/platform_thread.cc +++ b/base-foc/src/core/platform_thread.cc @@ -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; }