Hello Genode community,
in my checkpoint component I intercepted the Cpu session of a child, through which I get all Thread_capabilities created for and by the child. To store the state of a component I need to store the registers of the threads used by the child.
I tried reading the registers through the "Thread_state Cpu_thread::state()" method, but it did not contain any information about (just zeros).
I'm using Genode 16.05, kernel Fiasco.OC (pbax9 build). By inspecting the kernel API of foc, I found out that the function l4_thread_ex_regs_ret can read the sp and ip register. By changing the state method in platform_thread.cc (in base-foc) I could get the registers:
Thread_state Platform_thread::state() { Thread_state s; if (_pager_obj) s = _pager_obj->state;
_pager_obj->state.ip = ~0UL; _pager_obj->state.sp = ~0UL; l4_umword_t flags = 0; l4_thread_ex_regs_ret(_thread.local.dst(), &_pager_obj->state.ip, &_pager_obj->state.sp, &flags);
s.sp = _pager_obj->state.sp; s.ip = _pager_obj->state.ip; s.kcap = _gate.remote; s.id = _gate.local.local_name(); s.utcb = _utcb;
return s; }
But other registers like r0 - r12 are missing.
Is there a simple way in Genode to get them? Can I utilize the utcb memory location to find the missing registers?
Kind regards Denis
Hi Denis,
On 19.08.2016 10:30, Denis Huber wrote:
I tried reading the registers through the "Thread_state Cpu_thread::state()" method, but it did not contain any information about (just zeros).
I'm using Genode 16.05, kernel Fiasco.OC (pbax9 build). By inspecting the kernel API of foc, I found out that the function l4_thread_ex_regs_ret can read the sp and ip register.
On Fiasco.OC, the 'Platform_thread::pause()' function forces the thread into an exception state, which is handled by the pager, who reads the register state (including r0-r12) from the UTCB in 'Ipc_pager::_parse()'. The 'Platform_thread::state()' function then returns this previously saved state. If you called 'Cpu_thread::pause()' before 'Cpu_thread::state()' and did not get the correct register state, perhaps the thread was just executing a syscall. In that case, the exception would only occur after the syscall returned, which might take a long time, so 'Platform_thread::pause()' returns without waiting for the exception when it detects this situation. A possible solution for this problem without having to block until the thread returns from the syscall might be to extend 'l4_thread_ex_regs_ret()' to return the missing registers in the UTCB.
Regards, Christian
Hi Christina,
thank you for your answer, it helped a lot.
Is it possible to aquire the thread's registers through simply reading them in the UTCB which is pointed by Thread_state::utcb? If yes, what is the layout of the UTCB in the memory? Or do I also have to pause the thread to find relevant registers?
Kind regards, Denis
On 19.08.2016 16:28, Christian Prochaska wrote:
Hi Denis,
On 19.08.2016 10:30, Denis Huber wrote:
I tried reading the registers through the "Thread_state Cpu_thread::state()" method, but it did not contain any information about (just zeros).
I'm using Genode 16.05, kernel Fiasco.OC (pbax9 build). By inspecting the kernel API of foc, I found out that the function l4_thread_ex_regs_ret can read the sp and ip register.
On Fiasco.OC, the 'Platform_thread::pause()' function forces the thread into an exception state, which is handled by the pager, who reads the register state (including r0-r12) from the UTCB in 'Ipc_pager::_parse()'. The 'Platform_thread::state()' function then returns this previously saved state. If you called 'Cpu_thread::pause()' before 'Cpu_thread::state()' and did not get the correct register state, perhaps the thread was just executing a syscall. In that case, the exception would only occur after the syscall returned, which might take a long time, so 'Platform_thread::pause()' returns without waiting for the exception when it detects this situation. A possible solution for this problem without having to block until the thread returns from the syscall might be to extend 'l4_thread_ex_regs_ret()' to return the missing registers in the UTCB.
Regards, Christian
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Denis,
On 25.08.2016 15:45, Denis Huber wrote:
Is it possible to aquire the thread's registers through simply reading them in the UTCB which is pointed by Thread_state::utcb? If yes, what is the layout of the UTCB in the memory? Or do I also have to pause the thread to find relevant registers?
the thread's registers can be read from the UTCB in userland if the kernel saved them there. On Fiasco.OC, this currently only happens when an exception occurs ('Thread::exception()' in thread-ipc.cpp links '_utcb_handler' to the trap state, which is then copied into the UTCB in 'Thread::copy_ts_to_utcb()' in thread-arm.cpp). When pausing the thread, an artificial exception is triggered, which causes the kernel to copy the thread state into the UTCB. Therefore, it is necessary to pause the thread before the register values are available in the UTCB.
Regards, Christian
Hallo Christian,
thank you for your answer. It helped me a lot :)
Best regards, Denis
On 30.08.2016 14:34, Christian Prochaska wrote:
Hi Denis,
On 25.08.2016 15:45, Denis Huber wrote:
Is it possible to aquire the thread's registers through simply reading them in the UTCB which is pointed by Thread_state::utcb? If yes, what is the layout of the UTCB in the memory? Or do I also have to pause the thread to find relevant registers?
the thread's registers can be read from the UTCB in userland if the kernel saved them there. On Fiasco.OC, this currently only happens when an exception occurs ('Thread::exception()' in thread-ipc.cpp links '_utcb_handler' to the trap state, which is then copied into the UTCB in 'Thread::copy_ts_to_utcb()' in thread-arm.cpp). When pausing the thread, an artificial exception is triggered, which causes the kernel to copy the thread state into the UTCB. Therefore, it is necessary to pause the thread before the register values are available in the UTCB.
Regards, Christian
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hallo Christian, and hallo Genode community.
Preliminary: I want to read the registers of a thread A from a task from another thread B on another task. I am using Genode 16.08 on Fiasco.OC. I am also using the Genode mechanism of Cpu_thread::pause() before Cpu_thread::state(), but do not receive the any register values beside zeros. Christina told me that this problem comes from thread A being in a syscall during the pausing. His suggestion was to extend l4_thread_ex_regs_ret() to return the missing registers from the UTCB in a non-blocking fashion.
I am trying to do this, but I do not understand the syscall mechanism fully. Am I correct with the following understanding:
* Thread A is in a syscall: It is waiting for the answer of its IPC call. * The answer will be stored in the UTCB. * While the thread is waiting, another thread B tries to pause thread A. * The pause mechanism wants to put thread A into an artifical-exception state and additionally writes the register data to the UTCB of thread A. * The pause and syscall mechanism both need the UTCB for themselves. * To guarantee consistency of the UTCB, the pause method is not allowed to be executed while thread A is in a syscall. Otherwise the syscall could overrite the pause data (i.e. register values), if it spontaneously returns.
Assumed my understanding is correct (please tell me, if it is not), I have to wait (i.e. block execution) until the syscall finishes and the pause mechanism can write the register data to the UTCB. Christian wrote, it is possible to return the missing registers from the UTCB without blocking until the syscall finishes. How is it possible, if the register data is not in the UTCB?
Kind regards, Denis
On 30.08.2016 14:49, Denis Huber wrote:
Hallo Christian,
thank you for your answer. It helped me a lot :)
Best regards, Denis
On 30.08.2016 14:34, Christian Prochaska wrote:
Hi Denis,
On 25.08.2016 15:45, Denis Huber wrote:
Is it possible to aquire the thread's registers through simply reading them in the UTCB which is pointed by Thread_state::utcb? If yes, what is the layout of the UTCB in the memory? Or do I also have to pause the thread to find relevant registers?
the thread's registers can be read from the UTCB in userland if the kernel saved them there. On Fiasco.OC, this currently only happens when an exception occurs ('Thread::exception()' in thread-ipc.cpp links '_utcb_handler' to the trap state, which is then copied into the UTCB in 'Thread::copy_ts_to_utcb()' in thread-arm.cpp). When pausing the thread, an artificial exception is triggered, which causes the kernel to copy the thread state into the UTCB. Therefore, it is necessary to pause the thread before the register values are available in the UTCB.
Regards, Christian
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
genode-main mailing list genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Denis,
On 03.03.2017 08:35, Denis Huber wrote:
Hallo Christian, and hallo Genode community.
Preliminary: I want to read the registers of a thread A from a task from another thread B on another task. I am using Genode 16.08 on Fiasco.OC. I am also using the Genode mechanism of Cpu_thread::pause() before Cpu_thread::state(), but do not receive the any register values beside zeros. Christina told me that this problem comes from thread A being in a syscall during the pausing. His suggestion was to extend l4_thread_ex_regs_ret() to return the missing registers from the UTCB in a non-blocking fashion.
I am trying to do this, but I do not understand the syscall mechanism fully. Am I correct with the following understanding:
- Thread A is in a syscall: It is waiting for the answer of its IPC call.
- The answer will be stored in the UTCB.
- While the thread is waiting, another thread B tries to pause thread A.
- The pause mechanism wants to put thread A into an artifical-exception
state and additionally writes the register data to the UTCB of thread A.
- The pause and syscall mechanism both need the UTCB for themselves.
- To guarantee consistency of the UTCB, the pause method is not allowed
to be executed while thread A is in a syscall. Otherwise the syscall could overrite the pause data (i.e. register values), if it spontaneously returns.
And there would also be the problem of how to restart an interrupted syscall in thread A.
Assumed my understanding is correct (please tell me, if it is not), I have to wait (i.e. block execution) until the syscall finishes and the pause mechanism can write the register data to the UTCB. Christian wrote, it is possible to return the missing registers from the UTCB without blocking until the syscall finishes. How is it possible, if the register data is not in the UTCB?
The general idea is that when thread B calls l4_thread_ex_regs_ret() to find out the register state of thread A, the kernel could copy the complete register state of thread A into the UTCB of thread B. So, when l4_thread_ex_regs_ret() returns, thread B would find the complete register state of thread A in its own UTCB. Currently, only the flags, ip and sp are copied into the UTCB of thread B. So, when extending the implementation of the l4_thread_ex_regs_ret() syscall, you would need to find out where the kernel has stored the register state of thread A and then copy it completely into the UTCB of thread B and then, when l4_thread_ex_regs_ret() returns, read the additional registers from the UTCB of thread B. On the user side this could probably look something like:
... ip = ~0UL; sp = ~0UL; flags = L4_THREAD_EX_REGS_TRIGGER_EXCEPTION; l4_thread_ex_regs_ret(kcap, &ip, &sp, &flags); l4_utcb_t *utcb = l4_utcb(); r0 = utcb->mr[3]; r1 = utcb->mr[4]; ...
where, according to the implementation of l4_thread_ex_regs_ret_u() in 'contrib/foc-xxx/src/kernel/foc/l4/pkg/l4sys/include/thread.h', mr[0], mr[1] and mr[2] are currently used to transfer the flags, ip and sp.
Christian