Hi Martin,
On 02/28/2018 04:02 PM, Martin Stein wrote:
Hi Josef,
> [...]
First, I would look at the assembly context at 0x1001bb0 especially what
is done with R1/R9 in the subsequent instructions. You might also play
around with explicit register assignment:
register unsigned my_var asm("r1") = n;
or inline assembler to get a better understanding what you're actually
doing wrong in the perspective of the client.
Maybe the client returns from emulation with a bad IP which you could
check by adding an assembler instruction with an observable side effect
directly behind the LDR (or using a debugger).
You could even write an inline assembler snippet that writes the whole
GPR state after the LDR to RAM when running without emulation. This way,
you can compare the GPR states of the emulation case (inside observer)
and the non-emulation case.
I experimented a bit and after comparing the actual register contents of
R0-R15 inside the child application with the contents of the
Thread_state register backup (R0-R15) that is delivered to my fault
handler, it seems like Genode (or Fiasco.OC or the glue code) delivers
the registers in a strange mapping, where some original regs are mapped
to different regs in the backup, and some do not appear at all. The
mapping is like this:
Thread_state | Child | Child - Alternative Possibility
---------------------------------------------------------
R0 | R9 | R7
R1 | R10 | R4
R2 | R11 |
R3 | |
R4 | |
R5 | |
R6 | |
R7 | |
R8 | R0 |
R9 | R1 |
R10 | R2 |
R11 | R3 |
R12 | R12 | R5
R13 | R13 |
R14 | R14 |
R15 | R15 |
| R6 |
| R8 |
(Alternative Possibility means I couldn't tell which of the two is
actually correct due to equal values. The Thread_state registers that
have no mapping contained values that did not match any of the original
register contents; some of those values appeared in two distinct
Thread_state registers. I assured myself that the child didn't modify
the registers before dumping the contents.)
While this looks pretty strange, I verified the 'mapping' on a few
occasions and after incorporating the mapping into the instruction
emulator/the redundant memory writer, it does what it should, at least
for a limited test case (which doesn't access one of the unmapped
registers).
I should mention that we use a slightly modified Fiasco.OC kernel and
kernel interface, since in the unmodified Genode 16.08/Fiasco.OC,
calling Cpu_thread_component::state() [1] internally calls
Platform_thread::state(), which does not return the contents of all
registers. Instead our modified Platform_thread::state() calls our own
method all_regs() [2] which does that. The modified Fiasco.OC kernel
source files are [3] and [4] with modifications marked with a comment
mentioning "rtcr". But no remapping or other strange things are done there.
My guess is that this register magic is not happening in the base-hw
version of Genode (since Vinit instruction emulation is not using any
remapping and still works), but maybe you still have a clue of what is
going on there.
Best regards,
Josef
[1] state() repos/base/src/core/cpu_thread_component.cc
[2] all_regs():
https://github.com/jmstark/cr-genode/blob/red_mem/repos/base-focnados/src/core/platform_thread.cc
[3]
https://github.com/argos-research/foc/blob/checkpointRestore/l4/pkg/l4sys/include/thread.h
[4]
https://github.com/argos-research/foc/blob/checkpointRestore/kernel/fiasco/src/kern/thread_object.cpp
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
genode-main mailing list
genode-main@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/genode-main