Hello,
I circumvented the problem of finding the correct dataspace by letting the pagefault handler open another ROM connection to the binary at its instantiation. The ELF file contains the VM address of the code section, which allows me to fetch the correct instruction when a pagefault happens.
Then, I can use the instruction decoder (see Vinit @ [1]):
bool ldst = Instruction::load_store(instr, writes, state.format, state.reg); size_t access_size = state.format == Region_map::LSB8 ? 1 : (state.format == Region_map::LSB16 ? 2 : 4);
With this information I should be able to emulate the instruction:
if(!writes) { state.value = 0; memcpy(&state.value,addr + state.addr,access_size); thread_state.set_gpr(state.reg,state.value); } else { thread_state.get_gpr(state.reg, state.value); memcpy(addr + state.addr,&state.value,access_size); }
(For set_gpr() and get_gpr() see Vinit @ [2])
I have a simple sample application that for now only reads repeatedly a memory value and prints it:
unsigned n = 0x12abcdef while(1) { log(n, " sheep"); timer.msleep(1000); }
I let this app run normally for a few seconds and then detach the dataspace to see if emulation is working... it isn't.
The register write - i.e. the simulated load (memory read) instruction - results in weird app behavior: The app outputs "0 sheep" - wrong number - without pausing 1 second. If I comment out the register write, it outputs the same but pauses 1 second like it should. The instruction decoder gives the following info (pf IP is 0x1001bb0):
instruction: e599116c, load, LSB32, reg: 1
Which conforms with what objdump tells me:
1001bb0: e599116c ldr r1, [r9, #364] ; 0x16c
Still, it doesn't work. By trial and error (going through all regs) I found out that writing to r9 instead of r1 (in the pf handler) gives me the desired behaviour: Printing the correct number and waiting 1 second.
But I have no idea why my code above doesn't work (and why r9 does). I know the target register number and write the value into it. Vinit also seems to do it like this: [3] Isn't this exactly what the processor would do? What could I be missing?
Best regards, Josef
[1] os/src/vinit/arm_v7a/instruction.h [2] base-hw/include/arm_v7/base/thread_state.h [3] state() & processed() in os/src/vinit/include/rm_session/component.h