[PATCH] aarch64: simplify calls to __libc_arm_za_disable in assembly

Yury Khrustalev yury.khrustalev@arm.com
Mon Jun 16 12:25:27 GMT 2025


There is no functional change in this patch.

We remove stores and loads to stack, return address signing, and redundant
CFI directives before and after call to __libc_arm_za_disable().

The __libc_arm_za_disable implementation follows special calling convention
that allows to avoid most of the operations that would be necessary for a
call to a normal function (see [1] for details).

First, we rely on __libc_arm_za_disable() not clobbering certain registers,
and we put return address into one of these registers. Now we don't need
to store it on stack, so we don't need to sign return address using PAC.

Second, as a result of the above, we don't need to update the CFI offset.

This patch provides small optimisation avoiding unnecessary store and load
on stack also simplifies assembly code and CFI directives.

[1]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst

---

base commit: 5b7c8d1cd4

Passes tests on AArch64. OK for trunk?

---
 sysdeps/aarch64/__longjmp.S                  | 23 ++++++++------------
 sysdeps/aarch64/setjmp.S                     | 23 ++++++++------------
 sysdeps/unix/sysv/linux/aarch64/setcontext.S | 23 ++++++++------------
 3 files changed, 27 insertions(+), 42 deletions(-)

diff --git a/sysdeps/aarch64/__longjmp.S b/sysdeps/aarch64/__longjmp.S
index ed5b6b1fba..70ac02c44b 100644
--- a/sysdeps/aarch64/__longjmp.S
+++ b/sysdeps/aarch64/__longjmp.S
@@ -26,21 +26,16 @@
 ENTRY (__longjmp)
 
 #if IS_IN(libc)
-	/* Disable ZA state of SME in libc.a and libc.so, but not in ld.so.  */
-	paciasp
-	cfi_negate_ra_state
-	stp	x29, x30, [sp, -16]!
-	cfi_adjust_cfa_offset (16)
-	cfi_rel_offset (x29, 0)
-	cfi_rel_offset (x30, 8)
-	mov	x29, sp
+	/* Disable ZA state of SME in libc.a and libc.so, but not in ld.so.
+	   The calling convention of __libc_arm_za_disable allows to do
+	   this thus allowing to avoid saving to and reading from stack.
+	   As a result we also don't need to sign the return address and
+	   check it after returning because it is not stored to stack.  */
+	mov	x13, x30
+	cfi_register (x30, x13)
 	bl	__libc_arm_za_disable
-	ldp	x29, x30, [sp], 16
-	cfi_adjust_cfa_offset (-16)
-	cfi_restore (x29)
-	cfi_restore (x30)
-	autiasp
-	cfi_negate_ra_state
+	mov	x30, x13
+	cfi_register (x13, x30)
 #endif
 
 	cfi_def_cfa (x0, 0)
diff --git a/sysdeps/aarch64/setjmp.S b/sysdeps/aarch64/setjmp.S
index c8a2994f46..53c5e7d8cc 100644
--- a/sysdeps/aarch64/setjmp.S
+++ b/sysdeps/aarch64/setjmp.S
@@ -37,21 +37,16 @@ ENTRY_ALIGN (__sigsetjmp, 2)
 1:
 
 #if IS_IN(libc)
-	/* Disable ZA state of SME in libc.a and libc.so, but not in ld.so.  */
-	paciasp
-	cfi_negate_ra_state
-	stp	x29, x30, [sp, -16]!
-	cfi_adjust_cfa_offset (16)
-	cfi_rel_offset (x29, 0)
-	cfi_rel_offset (x30, 8)
-	mov	x29, sp
+	/* Disable ZA state of SME in libc.a and libc.so, but not in ld.so.
+	   The calling convention of __libc_arm_za_disable allows to do
+	   this thus allowing to avoid saving to and reading from stack.
+	   As a result we also don't need to sign the return address and
+	   check it after returning because it is not stored to stack.  */
+	mov	x13, x30
+	cfi_register (x30, x13)
 	bl	__libc_arm_za_disable
-	ldp	x29, x30, [sp], 16
-	cfi_adjust_cfa_offset (-16)
-	cfi_restore (x29)
-	cfi_restore (x30)
-	autiasp
-	cfi_negate_ra_state
+	mov	x30, x13
+	cfi_register (x13, x30)
 #endif
 
 	stp	x19, x20, [x0, #JB_X19<<3]
diff --git a/sysdeps/unix/sysv/linux/aarch64/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/setcontext.S
index 18e4fb7f21..d9716f012e 100644
--- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S
+++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S
@@ -48,21 +48,16 @@ ENTRY (__setcontext)
 	cbz	x0, 1f
 	b	C_SYMBOL_NAME (__syscall_error)
 1:
-	/* Disable ZA of SME.  */
-	paciasp
-	cfi_negate_ra_state
-	stp	x29, x30, [sp, -16]!
-	cfi_adjust_cfa_offset (16)
-	cfi_rel_offset (x29, 0)
-	cfi_rel_offset (x30, 8)
-	mov	x29, sp
+	/* Clear ZA state of SME.  */
+	/* The calling convention of __libc_arm_za_disable allows to do
+	   this thus allowing to avoid saving to and reading from stack.
+	   As a result we also don't need to sign the return address and
+	   check it after returning because it is not stored to stack.  */
+	mov	x13, x30
+	cfi_register (x30, x13)
 	bl	__libc_arm_za_disable
-	ldp	x29, x30, [sp], 16
-	cfi_adjust_cfa_offset (-16)
-	cfi_restore (x29)
-	cfi_restore (x30)
-	autiasp
-	cfi_negate_ra_state
+	mov	x30, x13
+	cfi_register (x13, x30)
 	/* Restore the general purpose registers.  */
 	mov	x0, x9
 	cfi_def_cfa (x0, 0)
-- 
2.39.5



More information about the Libc-alpha mailing list