[v2,1/1] aarch64: simplify __libc_arm_za_disable failure path
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
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
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
@@ -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)
@@ -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
@@ -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;
new file mode 100644
@@ -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>