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