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;
}