BL31: Introduce jump primitives

This patch introduces setjmp() and ongjmp() primitives to enable
standard setjmp/longjmp style execution. Both APIs parameters take a
pointer to struct jmpbuf type, which hosts CPU registers saved/restored
during jump.

As per the standard usage:

  - setjmp() return 0 when a jump is setup; and a non-zero value when
    returning from jump.

  - The caller of setjmp() must not return, or otherwise update stack
    pointer since.

Change-Id: I4af1d32e490cfa547979631b762b4cba188d0551
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
diff --git a/lib/aarch64/setjmp.S b/lib/aarch64/setjmp.S
new file mode 100644
index 0000000..9060cb7
--- /dev/null
+++ b/lib/aarch64/setjmp.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <setjmp.h>
+
+	.globl	setjmp
+	.globl	longjmp
+
+/*
+ * int setjmp(struct jmpbuf *buf);
+ *
+ * Sets a jump point in the buffer specified in x0. Returns 0 to the caller when
+ * when setting up the jump, and 1 when returning from the jump.
+ */
+func setjmp
+	mov	x7, sp
+
+	stp	x19, x20, [x0, #JMP_CTX_X19]
+	stp	x21, x22, [x0, #JMP_CTX_X21]
+	stp	x23, x24, [x0, #JMP_CTX_X23]
+	stp	x25, x26, [x0, #JMP_CTX_X25]
+	stp	x27, x28, [x0, #JMP_CTX_X27]
+	stp	x29, x30, [x0, #JMP_CTX_X29]
+	stp	x7, xzr, [x0, #JMP_CTX_SP]
+
+	mov	x0, #0
+	ret
+endfunc setjmp
+
+
+/*
+ * void longjmp(struct jmpbuf *buf);
+ *
+ * Return to a jump point setup by setjmp()
+ */
+func longjmp
+	ldp	x7, xzr, [x0, #JMP_CTX_SP]
+
+#if ENABLE_ASSERTIONS
+	/*
+	 * Since we're unwinding the stack, assert that the stack being reset to
+	 * is shallower.
+	 */
+	mov	x19, sp
+	cmp	x7, x19
+	ASM_ASSERT(ge)
+#endif
+
+	ldp	x19, x20, [x0, #JMP_CTX_X19]
+	ldp	x21, x22, [x0, #JMP_CTX_X21]
+	ldp	x23, x24, [x0, #JMP_CTX_X23]
+	ldp	x25, x26, [x0, #JMP_CTX_X25]
+	ldp	x27, x28, [x0, #JMP_CTX_X27]
+	ldp	x29, x30, [x0, #JMP_CTX_X29]
+
+	mov	sp, x7
+
+	mov	x0, #1
+	ret
+endfunc longjmp