Kevin D. Kissell wrote:
David Daney wrote:
Kevin D. Kissell wrote:
But it *could* be a trap or system call instruction, or a load/store
that would provoke a TLB exception. In the usual cases, however, as
I believe David was alluding, either the exception will ultimately
unwind to return to execute the magic alignment trap, or the thread
will exit, and could free the emulation slot as part of general cleanup.
But there's a case that isn't handled in this model, and that's the
case of an exception (or interrupt that falls in the 2-instruction
window) resulting in a signal that is caught and dispatched, and
where either the signal handler does a longjmp and restarts FP
computation, or where the signal handler itself contains a FP branch
with yet another delay slot to be emulated. One *could* get alarm
signal before the original delay slot instruction is executed, so
recycling the same vdso cache line would be premature. It's hard to
get away from something distinctly stack-like if one wants to cover
System calls we don't have to handle, they will eventually return to
the break instruction following the delay slot instruction and be
handled by the normal processing.
I am thinking that all other exceptions will result in one of three
1) They will work like system calls and return to the 'break'.
2) The thread will exit.
3) They result in a signal being sent to the thread. We can handle it
in force_signal(). In this case we would adjust the eip to point at
the original location of the instruction and clean things up. If the
signal handler tries to restart the instruction, the FP emulator will
re-run the emulation.
That's presumably OK if we *know* that the delay slot instruction has
*not* executed prior to the signal being taken. But if it has, it may
have had side-effects, i.e. imagine if it's an "ADD.S f4, f4, f6". We
can't re-run the emulation without generating erroneous processor
state. What do we do if, between the ADD.S and the
FP instructions are always emulated, so they don't do this delay slot
BREAK-that-replaces-my-old-alignment-trap, a timer interrupt comes in,
causing a SIGALRM which is caught and which executes another FP branch?
When I first wrote the delay slot handling code, I dreamed of disabling
interrupts during the delay slot instruction emulation - I think I even
coded it that way at one point - but it's fundamentally uncool to go off
into user mode with interrupts off.
Asynchronous signals could be a problem. I would have to think about
I really think that once the delay slot emulation machinery has been put
into motion, that fact needs to become a part of the thread state.
Currently, it's encoded, in a sense, in the stack pointer and the stack
contents. If we no longer stack it, and use a more static instruction
buffer as a trampoline, then I think it needs to be tagged as part of
the kernel's thread state.
Exactly. I had planned on augmenting the thread state to handle all of
That knowledge might be used in various ways. I still think it would
work to check that state and cause any signals to that thread need to be
deferred until it has processed the BREAK instruction to restore the
pre-emulation instruction flow. Once the state has been restored from
the dsemul record, the signal can be dispatched rather than returning
directly to the branch target. I don't like putting another check into
the context restore code, though.
A cruftier, but less inefficient-in-the-expected-case approach would be
a variant on what you suggest above. Signal dispatch could check the
EPC, and *if* EPC shows that the delay slot exception hasn't yet
executed, it could roll back the EPC to re-execute the FP branch after
the signal. If the delay slot instruction *has* executed, but not the
following BREAK, the signal dispatch code could preemptively do the
dsemulret cleanup and restore the pre-emulation stack and post-emulation
EPC before doing the signal dispatch.