The previous setjmp-implementation (as a static inline function that contained an 'asm volatile' sequence) was extremely fragile: (some versions of) GCC optimised the set of registers. One critical example was the removal of 'r9' from the clobber list, if -ffixed-reg9 was supplied. To increase robustness and ensure PCS-compliant behaviour, the setjmp and longjmp implementation are now in assembly and closely match what one would expect to find in a libc implementation. Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> Tested-by: Andy Yan <andy.yan@rock-chips.com>master
parent
ff143d5556
commit
b4806d6f1f
@ -0,0 +1,37 @@ |
||||
/* |
||||
* (C) 2017 Theobroma Systems Design und Consulting GmbH |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <config.h> |
||||
#include <asm/assembler.h> |
||||
#include <linux/linkage.h> |
||||
|
||||
.pushsection .text.setjmp, "ax" |
||||
ENTRY(setjmp) |
||||
/* |
||||
* A subroutine must preserve the contents of the registers |
||||
* r4-r8, r10, r11 (v1-v5, v7 and v8) and SP (and r9 in PCS |
||||
* variants that designate r9 as v6). |
||||
*/ |
||||
mov ip, sp |
||||
stm a1, {v1-v8, ip, lr} |
||||
mov a1, #0 |
||||
bx lr |
||||
ENDPROC(setjmp) |
||||
.popsection |
||||
|
||||
.pushsection .text.longjmp, "ax" |
||||
ENTRY(longjmp) |
||||
ldm a1, {v1-v8, ip, lr} |
||||
mov sp, ip |
||||
mov a1, a2 |
||||
/* If we were passed a return value of zero, return one instead */ |
||||
cmp a1, #0 |
||||
bne 1f |
||||
mov a1, #1 |
||||
1: |
||||
bx lr |
||||
ENDPROC(longjmp) |
||||
.popsection |
@ -0,0 +1,42 @@ |
||||
/* |
||||
* (C) 2017 Theobroma Systems Design und Consulting GmbH |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <config.h> |
||||
#include <asm/macro.h> |
||||
#include <linux/linkage.h> |
||||
|
||||
.pushsection .text.setjmp, "ax" |
||||
ENTRY(setjmp) |
||||
/* Preserve all callee-saved registers and the SP */ |
||||
stp x19, x20, [x0,#0] |
||||
stp x21, x22, [x0,#16] |
||||
stp x23, x24, [x0,#32] |
||||
stp x25, x26, [x0,#48] |
||||
stp x27, x28, [x0,#64] |
||||
stp x29, x30, [x0,#80] |
||||
mov x2, sp |
||||
str x2, [x0, #96] |
||||
mov x0, #0 |
||||
ret |
||||
ENDPROC(setjmp) |
||||
.popsection |
||||
|
||||
.pushsection .text.longjmp, "ax" |
||||
ENTRY(longjmp) |
||||
ldp x19, x20, [x0,#0] |
||||
ldp x21, x22, [x0,#16] |
||||
ldp x23, x24, [x0,#32] |
||||
ldp x25, x26, [x0,#48] |
||||
ldp x27, x28, [x0,#64] |
||||
ldp x29, x30, [x0,#80] |
||||
ldr x2, [x0,#96] |
||||
mov sp, x2 |
||||
/* Move the return value in place, but return 1 if passed 0. */ |
||||
adds x0, xzr, x1 |
||||
csinc x0, x0, xzr, ne |
||||
ret |
||||
ENDPROC(longjmp) |
||||
.popsection |
Loading…
Reference in new issue