[v2,1/1] aarch64: simplify __libc_arm_za_disable failure path

Message ID 20260423102256.103668-2-muhammad.kamran@arm.com (mailing list archive)
State Committed
Commit d093102297b8ba326b946b544f52af31ba6d1135
Delegated to: Wilco Dijkstra
Headers
Series aarch64: simplify __libc_arm_za_disable failure path and add a test case |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686

Commit Message

Muhammad Kamran April 23, 2026, 10:22 a.m. UTC
  The failure tail of __libc_arm_za_disable only leads to
__libc_fatal, so it does not need to preserve call frame state.

Remove the PAC prologue, frame setup, saved cntd value, stack
stores, and associated CFI directives from the fatal path, leaving
only the required SME state shutdown and fatal call.

Add tst-sme-za-disable-fail to exercise the abort path by providing
a TPIDR2 block with non-zero reserved bytes and checking that the
process terminates with SIGABRT and the expected fatal message.
---
 sysdeps/aarch64/Makefile                  |  2 +
 sysdeps/aarch64/__arm_za_disable.S        | 12 +---
 sysdeps/aarch64/tst-sme-helper.h          | 12 ++--
 sysdeps/aarch64/tst-sme-za-disable-fail.c | 67 +++++++++++++++++++++++
 4 files changed, 76 insertions(+), 17 deletions(-)
 create mode 100644 sysdeps/aarch64/tst-sme-za-disable-fail.c
  

Comments

Wilco Dijkstra May 18, 2026, 2:13 p.m. UTC | #1
Hi Muhammad,
 
> The failure tail of __libc_arm_za_disable only leads to
> __libc_fatal, so it does not need to preserve call frame state.
>
> Remove the PAC prologue, frame setup, saved cntd value, stack
> stores, and associated CFI directives from the fatal path, leaving
> only the required SME state shutdown and fatal call.
>
> Add tst-sme-za-disable-fail to exercise the abort path by providing
> a TPIDR2 block with non-zero reserved bytes and checking that the
> process terminates with SIGABRT and the expected fatal message.

LGTM - committed.

Cheers,
Wilco
  

Patch

diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index d6c5cc96ca..57132179fd 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -82,9 +82,11 @@  tests-internal += \
   tst-sme-clone3 \
   tst-sme-fork \
   tst-sme-vfork \
+  tst-sme-za-disable-fail \
   # tests-internal
 
 $(objpfx)tst-sme-clone3: $(objpfx)clone3.o $(objpfx)__arm_za_disable.o
+$(objpfx)tst-sme-za-disable-fail: $(objpfx)__arm_za_disable.o
 endif
 
 ifeq ($(subdir),malloc)
diff --git a/sysdeps/aarch64/__arm_za_disable.S b/sysdeps/aarch64/__arm_za_disable.S
index c9663e3bcb..c35e49de97 100644
--- a/sysdeps/aarch64/__arm_za_disable.S
+++ b/sysdeps/aarch64/__arm_za_disable.S
@@ -88,20 +88,10 @@  L(save_loop):
 L(end):
 	ret
 L(fail):
-	paciasp
-	cfi_negate_ra_state
-	stp	x29, x30, [sp, -32]!
-	cfi_adjust_cfa_offset (32)
-	cfi_rel_offset (x29, 0)
-	cfi_rel_offset (x30, 8)
-	mov	x29, sp
-	.inst	0x04e0e3f0  /* cntd	x16  */
-	str	x16, [sp, 16]
-	cfi_rel_offset (46, 16)
 	.inst	0xd503467f  /* smstop  */
 	adrp	x0, L(msg)
 	add	x0, x0, :lo12:L(msg)
-	bl	HIDDEN_JUMPTARGET (__libc_fatal)
+	b	HIDDEN_JUMPTARGET (__libc_fatal)
 END (__libc_arm_za_disable)
 
 	.section        .rodata
diff --git a/sysdeps/aarch64/tst-sme-helper.h b/sysdeps/aarch64/tst-sme-helper.h
index 2ae2cc2f47..fbf1d4772c 100644
--- a/sysdeps/aarch64/tst-sme-helper.h
+++ b/sysdeps/aarch64/tst-sme-helper.h
@@ -23,7 +23,7 @@  struct blk {
 };
 
 /* Read SVCR to get SM (bit0) and ZA (bit1) state.  */
-static unsigned long
+static unsigned long __attribute_maybe_unused__
 get_svcr (void)
 {
   register unsigned long x0 asm ("x0");
@@ -34,7 +34,7 @@  get_svcr (void)
 }
 
 /* Returns tpidr2.  */
-static void *
+static __attribute_maybe_unused__ void *
 get_tpidr2 (void)
 {
   register unsigned long x0 asm ("x0");
@@ -45,7 +45,7 @@  get_tpidr2 (void)
 }
 
 /* Obtains current streaming SVE vector register size.  */
-static unsigned long
+static unsigned long __attribute_maybe_unused__
 get_svl (void)
 {
   register unsigned long x0 asm ("x0");
@@ -56,7 +56,7 @@  get_svl (void)
 }
 
 /* PSTATE.ZA = 1, set ZA state to active.  */
-static void
+static void __attribute_maybe_unused__
 start_za (void)
 {
   asm volatile (
@@ -64,7 +64,7 @@  start_za (void)
 }
 
 /* Load data into ZA byte by byte from p.  */
-static void __attribute__ ((noinline))
+static void __attribute_maybe_unused__ __attribute__ ((noinline))
 load_za (const void *buf, unsigned long svl)
 {
   register unsigned long x15 asm ("x15") = 0;
@@ -84,7 +84,7 @@  load_za (const void *buf, unsigned long svl)
 }
 
 /* Set tpidr2 to BLK.  */
-static void
+static void __attribute_maybe_unused__
 set_tpidr2 (struct blk *blk)
 {
   register unsigned long x0 asm ("x0") = (unsigned long)blk;
diff --git a/sysdeps/aarch64/tst-sme-za-disable-fail.c b/sysdeps/aarch64/tst-sme-za-disable-fail.c
new file mode 100644
index 0000000000..d3a6bebaf9
--- /dev/null
+++ b/sysdeps/aarch64/tst-sme-za-disable-fail.c
@@ -0,0 +1,67 @@ 
+/* Test that __libc_arm_za_disable aborts on unknown TPIDR2 extensions.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <stdint.h>
+#include <sys/auxv.h>
+
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+
+#include "tst-sme-helper.h"
+
+extern void __libc_arm_za_disable (void);
+
+/* Required by __arm_za_disable.o and provided by the startup code
+   as a hidden symbol.  */
+uint64_t _dl_hwcap2;
+
+static struct blk blk = {
+  .za_save_buffer = NULL,
+  .num_za_save_slices = 0,
+  .__reserved = { 1, 0, 0, 0, 0, 0 },
+};
+
+static void
+do_abort (void *closure)
+{
+  start_za ();
+  set_tpidr2 (closure);
+  __libc_arm_za_disable ();
+}
+
+static int
+do_test (void)
+{
+  _dl_hwcap2 = getauxval (AT_HWCAP2);
+  if ((_dl_hwcap2 & HWCAP2_SME) == 0)
+    FAIL_UNSUPPORTED ("kernel or CPU does not support SME");
+
+  struct support_capture_subprocess result
+      = support_capture_subprocess (do_abort, &blk);
+  support_capture_subprocess_check (&result, "tst-sme-za-disable-fail",
+				    -SIGABRT, sc_allow_stderr);
+  TEST_COMPARE_STRING (result.err.buffer,
+		       "FATAL: __libc_arm_za_disable failed.\n");
+  support_capture_subprocess_free (&result);
+
+  return 0;
+}
+
+#include <support/test-driver.c>