diff --git a/base-nova/include/base/pager.h b/base-nova/include/base/pager.h index c109f39579..154491005b 100644 --- a/base-nova/include/base/pager.h +++ b/base-nova/include/base/pager.h @@ -62,6 +62,7 @@ namespace Genode { addr_t sel_client_ec; bool valid; bool dead; + bool singlestep; } _state; void _copy_state(Nova::Utcb * utcb); @@ -173,6 +174,8 @@ namespace Genode { uint8_t client_recall(); void client_set_ec(addr_t ec) { _state.sel_client_ec = ec; } + + void single_step(bool on) { _state.singlestep = on; } }; diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 3fa9d31e66..fb7dadb402 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -124,8 +124,18 @@ void Pager_object::_recall_handler() obj->_state.valid = false; + bool singlestep_state = obj->_state.thread.eflags & 0x100UL; + if (obj->_state.singlestep && !singlestep_state) { + utcb->flags = obj->_state.thread.eflags | 0x100UL; + utcb->mtd = Nova::Mtd(Mtd::EFL).value(); + } else + if (!obj->_state.singlestep && singlestep_state) { + utcb->flags = obj->_state.thread.eflags & ~0x100UL; + utcb->mtd = Nova::Mtd(Mtd::EFL).value(); + } else + utcb->mtd = 0; utcb->set_msg_word(0); - utcb->mtd = 0; + reply(myself->stack_top()); } @@ -201,6 +211,7 @@ Pager_object::Pager_object(unsigned long badge) _sm_state_notify = cap_selector_allocator()->alloc(); _state.valid = false; _state.dead = false; + _state.singlestep = false; _state.sel_client_ec = Native_thread::INVALID_INDEX; /* Create portal for exception handlers 0x0 - 0xd */ diff --git a/base-nova/src/core/cpu_session_extension.cc b/base-nova/src/core/cpu_session_extension.cc index 7b56c9b95c..7aff4fdc97 100644 --- a/base-nova/src/core/cpu_session_extension.cc +++ b/base-nova/src/core/cpu_session_extension.cc @@ -23,7 +23,7 @@ Native_capability Cpu_session_component::native_cap(Thread_capability thread_cap) { Cpu_thread_component *thread = _lookup_thread(thread_cap); - if (!thread) + if (!thread || !thread->platform_thread()) return Native_capability::invalid_cap(); return thread->platform_thread()->native_cap(); @@ -38,3 +38,15 @@ Cpu_session_component::pause_sync(Thread_capability target_thread_cap) return thread->platform_thread()->pause(); } + +void +Cpu_session_component::single_step(Thread_capability thread_cap, bool enable) +{ + using namespace Genode; + + Cpu_thread_component *thread = _lookup_thread(thread_cap); + if (!thread || !thread->platform_thread()) + return; + + thread->platform_thread()->single_step(enable); +} diff --git a/base-nova/src/core/include/cpu_session_component.h b/base-nova/src/core/include/cpu_session_component.h index 774527daec..9c28cdc765 100644 --- a/base-nova/src/core/include/cpu_session_component.h +++ b/base-nova/src/core/include/cpu_session_component.h @@ -137,6 +137,7 @@ namespace Genode { int start(Thread_capability, addr_t, addr_t); void pause(Thread_capability thread_cap); void resume(Thread_capability thread_cap); + void single_step(Thread_capability thread_cap, bool enable); void cancel_blocking(Thread_capability); int name(Thread_capability, char *, size_t); int state(Thread_capability, Thread_state *); diff --git a/base-nova/src/core/include/platform_thread.h b/base-nova/src/core/include/platform_thread.h index c6c5d34c5f..f47ccacd10 100644 --- a/base-nova/src/core/include/platform_thread.h +++ b/base-nova/src/core/include/platform_thread.h @@ -152,6 +152,8 @@ namespace Genode { _sel_ec(), Obj_crd::RIGHT_EC_RECALL); } + void single_step(bool on); + }; } diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index 279605d6e3..1585dd373b 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -294,6 +294,12 @@ void Platform_thread::cancel_blocking() _pager->client_cancel_blocking(); } +void Platform_thread::single_step(bool on) +{ + if (!_pager) return; + + _pager->single_step(on); +} unsigned long Platform_thread::pager_object_badge() const {