SPARC: Update the Flush windows software trap
This commit re-implements the SPARC V8 ABI "Flush windows" software trap. The trap is generated by C++ compilers for exceptions and also by the C standard library function longjmp(). There were two issues with the previous implementation: 1. It did reads and writes via the stack pointer of the trap window, which is not defined. 2. It executed with traps enabled but without the processor run-time state set to safely handle traps. In particular there was no valid stack for trap processing. Even though interrupt priority was set to highest level, the behavior at other traps was not deterministic. For example non-maskable interrupt (15) trap or bus error trap for instruction fetch. This new implementation does not store backup copies of CPU registers to the stack, and it executes with traps disabled. Fixes #63901 Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
This commit is contained in:
parent
3f1eed17f8
commit
fd4e66499c
1 changed files with 68 additions and 43 deletions
|
@ -83,60 +83,85 @@ SECTION_FUNC(TEXT, __sparc_trap_window_underflow)
|
|||
* "By executing a type 3 trap, a process asks the system to flush all its
|
||||
* register windows to the stack."
|
||||
*
|
||||
* This implementation uses the window overflow trap handler to perform the
|
||||
* actual window flush.
|
||||
*
|
||||
* On entry:
|
||||
* %l0: psr
|
||||
* %l1: pc
|
||||
* %l2: npc
|
||||
*/
|
||||
SECTION_FUNC(TEXT, __sparc_trap_flush_windows)
|
||||
/* push a few registers which are needed later to the stack */
|
||||
sub %sp, 0x10, %sp
|
||||
std %l0, [%sp + 0x40 + 0x00]
|
||||
st %l2, [%sp + 0x40 + 0x08]
|
||||
st %g2, [%sp + 0x40 + 0x0c]
|
||||
/* Save global registers used by the routine */
|
||||
mov %g3, %l3
|
||||
mov %g4, %l4
|
||||
mov %g5, %l5
|
||||
mov %g1, %l6
|
||||
mov %g2, %l7
|
||||
|
||||
restore
|
||||
/* In window where we trapped from. This window will not be flushed. */
|
||||
/* Uses g3=psr, g4=1, g2=wim, g1,g5=scratch */
|
||||
mov %l0, %g3
|
||||
set 1, %g4
|
||||
rd %wim, %g2
|
||||
|
||||
/* Set highest processor interrupt level and enable traps. */
|
||||
rd %psr, %g2
|
||||
or %g2, PSR_PIL, %g2
|
||||
wr %g2, PSR_ET, %psr
|
||||
nop
|
||||
nop
|
||||
/*
|
||||
* We can always restore the previous window. Check if we can restore
|
||||
* the window after that.
|
||||
*/
|
||||
and %l0, PSR_CWP, %g1
|
||||
add %g1, 2, %g1
|
||||
ba .LcheckNextWindow
|
||||
restore
|
||||
|
||||
/* Execute "save" NWINDOWS-1 times. */
|
||||
set CONFIG_SPARC_NWIN-2, %g2
|
||||
1:
|
||||
save
|
||||
cmp %g2, %g0
|
||||
bne 1b
|
||||
sub %g2, 1, %g2
|
||||
/* Flush window to stack */
|
||||
.LflushWindow:
|
||||
std %l0, [%sp + 0x00]
|
||||
std %l2, [%sp + 0x08]
|
||||
std %l4, [%sp + 0x10]
|
||||
std %l6, [%sp + 0x18]
|
||||
std %i0, [%sp + 0x20]
|
||||
std %i2, [%sp + 0x28]
|
||||
std %i4, [%sp + 0x30]
|
||||
std %i6, [%sp + 0x38]
|
||||
|
||||
/* Execute "restore" NWINDOWS-1 times. */
|
||||
set CONFIG_SPARC_NWIN-2, %g2
|
||||
2:
|
||||
restore
|
||||
cmp %g2, %g0
|
||||
bne 2b
|
||||
sub %g2, 1, %g2
|
||||
/*
|
||||
* Check if next window is invalid by comparing
|
||||
* (1 << ((cwp + 1) % NWIN)) with WIM
|
||||
*/
|
||||
.LcheckNextWindow:
|
||||
set CONFIG_SPARC_NWIN, %g5
|
||||
cmp %g1, %g5
|
||||
bge,a .Lnowrap
|
||||
sub %g1, %g5, %g1
|
||||
.Lnowrap:
|
||||
sll %g4, %g1, %g5
|
||||
cmp %g5, %g2
|
||||
be .LflushWindowDone
|
||||
inc %g1
|
||||
|
||||
save
|
||||
|
||||
/* pop registers from stack which are used for the trap return */
|
||||
ldd [%sp + 0x40 + 0x00], %l0
|
||||
ld [%sp + 0x40 + 0x08], %l2
|
||||
ld [%sp + 0x40 + 0x0c], %g2
|
||||
add %sp, 0x10, %sp
|
||||
|
||||
/* Restore %psr as it was on trap entry. */
|
||||
wr %l0, %psr
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
/* We need to flush the next window */
|
||||
ba .LflushWindow
|
||||
restore
|
||||
|
||||
/*
|
||||
* All used windows have been flushed. Set WIM to cause trap for CWP+2.
|
||||
* When we return from this trap it will be CWP+1 that will trap, that
|
||||
* is, the next restore or rett.
|
||||
*/
|
||||
.LflushWindowDone:
|
||||
/* We can not restore %psr from %l0 because we may be in any window. */
|
||||
wr %g3, %psr
|
||||
and %g3, PSR_CWP, %g1
|
||||
add %g1, 2, %g1
|
||||
set CONFIG_SPARC_NWIN, %g5
|
||||
/* We are now back in the trap window. */
|
||||
cmp %g1, %g5
|
||||
bge,a .Lnowrap2
|
||||
sub %g1, %g5, %g1
|
||||
.Lnowrap2:
|
||||
sll %g4, %g1, %g1
|
||||
wr %g1, %wim
|
||||
mov %l3, %g3
|
||||
mov %l4, %g4
|
||||
mov %l5, %g5
|
||||
mov %l6, %g1
|
||||
mov %l7, %g2
|
||||
jmp %l2
|
||||
rett %l2 + 4
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue