Hi Vasily,
The kernel differentiates between fault instruction and next instruction in some cases. Might make more sense to just explain some different cases
* If a thread is interrupted by a hardware interrupt, then it should start running again at the address of the next instruction that should be executed. In this case the fault instruction is irrelevant, all the kernel will use is the 'next instruction'. What this really means is the kernel will do nothing to signal to the arch layer that the resume address should be modified. So on architectures like arm (where we store LR) or x86 (where the hardware saves NextIP) when we unstack the user context everything is correct. From the non-arch side of the kernel the thread is always kept at ThreadState_Running, and if you look in activateThread you will see this causes the thread to be untouched when rescheduling it.
* If a thread does a syscall it is more complicated. The kernel may want to start the thread running either at the instruction after the trap instruction, if the syscall completed, or set it running back at the trap instruction if the syscall needs to get restarted. This is where the fault instruction comes in. In handleInvocation you will see if a check for 'if (unlikely(status == EXCEPTION_PREEMPTED))', which if true results in handleInvocation immediately returning. At the point it returns the thread state is set to ThreadState_Restart, and if you look back in activateThread you will see this results in setting the next instruction to 'getRestartPC', which on arm is FaultInstruction. This means that when we resume this thread it will immediately perform the trap instruction again (this is how the kernel does pre-emption for long running operations). If that check for EXCEPTION_PREEMPTED was false and all goes well with the invocation then the 'setThreadState(thread, ThreadState_Running)' at the bottom of the function gets called. This once again means that activateThread does nothing, and this thread will start running at its next instruction, which is assumed to be the instruction after the trap.
Other kinds of faults (vm faults etc) are a bit different in that it is the user level fault handler that gets to pick the next instruction.
Adrian
On Sat 15-Oct-2016 11:02 PM, Vasily A. Sartakov wrote:
we take address that causes syscall from the ksCurThread and set them back. Thus, FaultInstruction should point to something different, right?
I have add FaultInstruction in the same manner as it made in ARM platform:
sub lr, lr, #4
/* Store FaultInstruction */
str lr, [sp, #(PT_FaultInstruction - PT_LR_svc)]
I am tacking address of an instruction causes exception, subtract 4 from the value, and save it into the FauiltInstruction. Now get* and set* functions are:
word_t PURE
getRestartPC(tcb_t *thread)
{
return getRegister(thread, FaultInstruction);
}
void
setNextPC(tcb_t *thread, word_t v)
{
setRegister(thread, CP0_EPC, v);
}
Also, Faultinstruction is part of frameRegisters and «linked» with cp0_epc of seL4_UserContext (sel4arch.xml)
Now both tests are passed:
Starting test 27: TEST_RECYCLE0001
TEST_RECYCLE0001
Running test RECYCLE0001 (Basic endpoint recycle testing.)
<