All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v5 13/18] arm: provide a PCS-compliant setjmp implementation
Date: Tue, 10 Oct 2017 16:21:13 +0200	[thread overview]
Message-ID: <1507645279-25188-14-git-send-email-philipp.tomsich@theobroma-systems.com> (raw)
In-Reply-To: <1507645279-25188-1-git-send-email-philipp.tomsich@theobroma-systems.com>

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>

---

Changes in v5: None
Changes in v4: None
Changes in v3:
- converted setjmp/longjmp from inline-assembly to separate .S files
  to improve predicatability if emitted code

Changes in v2: None

 arch/arm/include/asm/setjmp.h | 94 ++++++-------------------------------------
 arch/arm/lib/Makefile         |  6 +++
 arch/arm/lib/setjmp.S         | 37 +++++++++++++++++
 arch/arm/lib/setjmp_aarch64.S | 42 +++++++++++++++++++
 4 files changed, 98 insertions(+), 81 deletions(-)
 create mode 100644 arch/arm/lib/setjmp.S
 create mode 100644 arch/arm/lib/setjmp_aarch64.S

diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h
index c3399a7..517beeb 100644
--- a/arch/arm/include/asm/setjmp.h
+++ b/arch/arm/include/asm/setjmp.h
@@ -1,6 +1,6 @@
 /*
- * (C) Copyright 2016
- * Alexander Graf <agraf@suse.de>
+ * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH
+ * (C) Copyright 2016 Alexander Graf <agraf@suse.de>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -8,89 +8,21 @@
 #ifndef _SETJMP_H_
 #define _SETJMP_H_	1
 
+/*
+ * This really should be opaque, but the EFI implementation wrongly
+ * assumes that a 'struct jmp_buf_data' is defined.
+ */
 struct jmp_buf_data {
-	ulong target;
-	ulong regs[5];
-	int ret;
-};
-
-typedef struct jmp_buf_data jmp_buf[1];
-
-static inline int setjmp(jmp_buf jmp)
-{
-	jmp->ret = 0;
-
-#ifdef CONFIG_ARM64
-	asm volatile(
-		"adr x1, jmp_target\n"
-		"str x1, %0\n"
-		"stp x26, x27, %1\n"
-		"stp x28, x29, %2\n"
-		"mov x1, sp\n"
-		"str x1, %3\n"
-		"jmp_target: "
-		: "=m" (jmp->target), "=m" (jmp->regs[0]),
-		  "=m" (jmp->regs[2]), "=m" (jmp->regs[4])
-		:
-		: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
-		  "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
-		  "x16", "x17", "x18", "x19", "x20", "x21", "x22",
-		  "x23", "x24", "x25", /* x26, x27, x28, x29, sp */
-		  "x30", "cc", "memory");
-#else
-	asm volatile(
-#if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
-		".align 2\n"
-		"adr r0, jmp_target\n"
-		"add r0, r0, $1\n"
+#if defined(__aarch64__)
+	u64  regs[13];
 #else
-		"adr r0, jmp_target\n"
-#endif
-		"mov r1, %0\n"
-		"mov r2, sp\n"
-		"stm r1!, {r0, r2, r4, r5, r6, r7}\n"
-		".align 2\n"
-		"jmp_target: \n"
-		:
-		: "l" (&jmp->target)
-		: "r0", "r1", "r2", "r3", /* "r4", "r5", "r6", "r7", */
-		  "r8", "r9", "r10", "r11", /* sp, */ "ip", "lr",
-		  "cc", "memory");
-#endif
-
-	return jmp->ret;
-}
-
-static inline __noreturn void longjmp(jmp_buf jmp, int ret)
-{
-	jmp->ret = ret;
-
-#ifdef CONFIG_ARM64
-	asm volatile(
-		"ldr x0, %0\n"
-		"ldr x1, %3\n"
-		"mov sp, x1\n"
-		"ldp x26, x27, %1\n"
-		"ldp x28, x25, %2\n"
-		"mov x29, x25\n"
-		"br x0\n"
-		:
-		: "m" (jmp->target), "m" (jmp->regs[0]), "m" (jmp->regs[2]),
-		  "m" (jmp->regs[4])
-		: "x0", "x1", "x25", "x26", "x27", "x28");
-#else
-	asm volatile(
-		"mov r1, %0\n"
-		"ldm r1!, {r0, r2, r4, r5, r6, r7}\n"
-		"mov sp, r2\n"
-		"bx r0\n"
-		:
-		: "l" (&jmp->target)
-		: "r1");
+	u32  regs[10];  /* r4-r9, sl, fp, sp, lr */
 #endif
+};
 
-	while (1) { }
-}
+typedef struct jmp_buf_data jmp_buf[1];
 
+int setjmp(jmp_buf jmp);
+void longjmp(jmp_buf jmp, int ret);
 
 #endif /* _SETJMP_H_ */
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 6e1c436..abffa10 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -17,6 +17,12 @@ else
 obj-y	+= vectors.o crt0.o
 endif
 
+ifdef CONFIG_ARM64
+obj-y   += setjmp_aarch64.o
+else
+obj-y   += setjmp.o
+endif
+
 ifndef CONFIG_SPL_BUILD
 ifdef CONFIG_ARM64
 obj-y	+= relocate_64.o
diff --git a/arch/arm/lib/setjmp.S b/arch/arm/lib/setjmp.S
new file mode 100644
index 0000000..6746e5e
--- /dev/null
+++ b/arch/arm/lib/setjmp.S
@@ -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
diff --git a/arch/arm/lib/setjmp_aarch64.S b/arch/arm/lib/setjmp_aarch64.S
new file mode 100644
index 0000000..b68edb8
--- /dev/null
+++ b/arch/arm/lib/setjmp_aarch64.S
@@ -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
-- 
2.1.4

  parent reply	other threads:[~2017-10-10 14:21 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-10 14:21 [U-Boot] [PATCH v5 00/18] rockchip: back-to-bootrom: replace assembly-implementation with C-code Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 01/18] arm: boot0 hook: move boot0 hook before '_start' Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 02/18] rockchip: boot0: align to 0x20 for armv7 '_start' Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-11-09 12:59   ` [U-Boot] [PATCH v5 " Andy Yan
2017-11-09 13:03     ` Dr. Philipp Tomsich
2017-11-10  3:43       ` Kever Yang
2017-10-10 14:21 ` [U-Boot] [PATCH v5 03/18] rockchip: enable boot0-hook for all Rockchip SoCs Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 04/18] rockchip: mkimage: use spl_boot0 " Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 05/18] rockchip: rk3288: use aligned address for SPL_TEXT_BASE Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 06/18] rockchip: rk3036: " Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 07/18] socfpga: boot0 hook: adjust to unified boot0 semantics Philipp Tomsich
2017-11-06 17:26   ` Dr. Philipp Tomsich
2017-11-06 17:54     ` Marek Vasut
2017-11-06 17:55       ` Dr. Philipp Tomsich
2017-11-06 17:57         ` Marek Vasut
2017-11-07  4:46           ` Chee, Tien Fong
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 08/18] bcm235xx: " Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 09/18] bcm281xx: " Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 10/18] rockchip: boot0 hook: support early return for RK3188/RK3066-style BROM Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 11/18] arm: make save_boot_params_ret prototype visible for AArch64 Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 12/18] arm: mark save_boot_params_ret as a function Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` Philipp Tomsich [this message]
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, 13/18] arm: provide a PCS-compliant setjmp implementation Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 14/18] rockchip: back-to-bootrom: replace assembly-implementation with C-code Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 15/18] rockchip: rk3188: use boot0 hook to load up SPL in 2 steps Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 16/18] rockchip: back-to-bootrom: allow passing a cmd to the bootrom Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 17/18] rockchip: rk3188: move CONFIG_SPL_* entries from rk3188_common.h to Kconfig Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-10 14:21 ` [U-Boot] [PATCH v5 18/18] rockchip: mkimage: remove unused code-paths (spl_boot0 is now implied) Philipp Tomsich
2017-11-07 14:18   ` [U-Boot] [U-Boot, v5, " Philipp Tomsich
2017-10-11 13:07 ` [U-Boot] [PATCH v5 00/18] rockchip: back-to-bootrom: replace assembly-implementation with C-code Heiko Stuebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1507645279-25188-14-git-send-email-philipp.tomsich@theobroma-systems.com \
    --to=philipp.tomsich@theobroma-systems.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.