summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/arm64/signal
diff options
context:
space:
mode:
authorWill Deacon <will@kernel.org>2024-09-12 13:43:57 +0100
committerWill Deacon <will@kernel.org>2024-09-12 13:43:57 +0100
commit2ef52ca02cfb1d13dbdfb96878fabe3a420b3da7 (patch)
tree36128cd8ad990e951b9cba5a0a603311af0e0f5e /tools/testing/selftests/arm64/signal
parent982a847c71d43eefd530e865314cbf31309619e2 (diff)
parentd736d4fc763090f9a02dc5556174de9768093f43 (diff)
Merge branch 'for-next/selftests' into for-next/core
* for-next/selftests: kselftest/arm64: Fix build warnings for ptrace kselftest/arm64: Actually test SME vector length changes via sigreturn kselftest/arm64: signal: fix/refactor SVE vector length enumeration
Diffstat (limited to 'tools/testing/selftests/arm64/signal')
-rw-r--r--tools/testing/selftests/arm64/signal/Makefile2
-rw-r--r--tools/testing/selftests/arm64/signal/sve_helpers.c56
-rw-r--r--tools/testing/selftests/arm64/signal/sve_helpers.h21
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c46
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c30
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/ssve_regs.c36
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c36
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/sve_regs.c32
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/za_no_regs.c32
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/za_regs.c36
10 files changed, 139 insertions, 188 deletions
diff --git a/tools/testing/selftests/arm64/signal/Makefile b/tools/testing/selftests/arm64/signal/Makefile
index 8f5febaf1a9a..edb3613513b8 100644
--- a/tools/testing/selftests/arm64/signal/Makefile
+++ b/tools/testing/selftests/arm64/signal/Makefile
@@ -23,7 +23,7 @@ $(TEST_GEN_PROGS): $(PROGS)
# Common test-unit targets to build common-layout test-cases executables
# Needs secondary expansion to properly include the testcase c-file in pre-reqs
COMMON_SOURCES := test_signals.c test_signals_utils.c testcases/testcases.c \
- signals.S
+ signals.S sve_helpers.c
COMMON_HEADERS := test_signals.h test_signals_utils.h testcases/testcases.h
.SECONDEXPANSION:
diff --git a/tools/testing/selftests/arm64/signal/sve_helpers.c b/tools/testing/selftests/arm64/signal/sve_helpers.c
new file mode 100644
index 000000000000..0acc121af306
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/sve_helpers.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 ARM Limited
+ *
+ * Common helper functions for SVE and SME functionality.
+ */
+
+#include <stdbool.h>
+#include <kselftest.h>
+#include <asm/sigcontext.h>
+#include <sys/prctl.h>
+
+unsigned int vls[SVE_VQ_MAX];
+unsigned int nvls;
+
+int sve_fill_vls(bool use_sme, int min_vls)
+{
+ int vq, vl;
+ int pr_set_vl = use_sme ? PR_SME_SET_VL : PR_SVE_SET_VL;
+ int len_mask = use_sme ? PR_SME_VL_LEN_MASK : PR_SVE_VL_LEN_MASK;
+
+ /*
+ * Enumerate up to SVE_VQ_MAX vector lengths
+ */
+ for (vq = SVE_VQ_MAX; vq > 0; --vq) {
+ vl = prctl(pr_set_vl, vq * 16);
+ if (vl == -1)
+ return KSFT_FAIL;
+
+ vl &= len_mask;
+
+ /*
+ * Unlike SVE, SME does not require the minimum vector length
+ * to be implemented, or the VLs to be consecutive, so any call
+ * to the prctl might return the single implemented VL, which
+ * might be larger than 16. So to avoid this loop never
+ * terminating, bail out here when we find a higher VL than
+ * we asked for.
+ * See the ARM ARM, DDI 0487K.a, B1.4.2: I_QQRNR and I_NWYBP.
+ */
+ if (vq < sve_vq_from_vl(vl))
+ break;
+
+ /* Skip missing VLs */
+ vq = sve_vq_from_vl(vl);
+
+ vls[nvls++] = vl;
+ }
+
+ if (nvls < min_vls) {
+ fprintf(stderr, "Only %d VL supported\n", nvls);
+ return KSFT_SKIP;
+ }
+
+ return KSFT_PASS;
+}
diff --git a/tools/testing/selftests/arm64/signal/sve_helpers.h b/tools/testing/selftests/arm64/signal/sve_helpers.h
new file mode 100644
index 000000000000..50948ce471cc
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/sve_helpers.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 ARM Limited
+ *
+ * Common helper functions for SVE and SME functionality.
+ */
+
+#ifndef __SVE_HELPERS_H__
+#define __SVE_HELPERS_H__
+
+#include <stdbool.h>
+
+#define VLS_USE_SVE false
+#define VLS_USE_SME true
+
+extern unsigned int vls[];
+extern unsigned int nvls;
+
+int sve_fill_vls(bool use_sme, int min_vls);
+
+#endif
diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c
index ebd5815b54bb..dfd6a2badf9f 100644
--- a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c
+++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c
@@ -6,44 +6,28 @@
* handler, this is not supported and is expected to segfault.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
struct fake_sigframe sf;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sme_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SME, 2);
- /*
- * Enumerate up to SVE_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SVE_SET_VL, vq * 16);
- if (vl == -1)
- return false;
+ if (!res)
+ return true;
- vl &= PR_SME_VL_LEN_MASK;
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
-
- vls[nvls++] = vl;
- }
-
- /* We need at least two VLs */
- if (nvls < 2) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
-
- return true;
+ return false;
}
static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
@@ -51,30 +35,30 @@ static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
{
size_t resv_sz, offset;
struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
- struct sve_context *sve;
+ struct za_context *za;
/* Get a signal context with a SME ZA frame in it */
if (!get_current_context(td, &sf.uc, sizeof(sf.uc)))
return 1;
resv_sz = GET_SF_RESV_SIZE(sf);
- head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+ head = get_header(head, ZA_MAGIC, resv_sz, &offset);
if (!head) {
- fprintf(stderr, "No SVE context\n");
+ fprintf(stderr, "No ZA context\n");
return 1;
}
- if (head->size != sizeof(struct sve_context)) {
+ if (head->size != sizeof(struct za_context)) {
fprintf(stderr, "Register data present, aborting\n");
return 1;
}
- sve = (struct sve_context *)head;
+ za = (struct za_context *)head;
/* No changes are supported; init left us at minimum VL so go to max */
fprintf(stderr, "Attempting to change VL from %d to %d\n",
- sve->vl, vls[0]);
- sve->vl = vls[0];
+ za->vl, vls[0]);
+ za->vl = vls[0];
fake_sigreturn(&sf, sizeof(sf), 0);
diff --git a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
index e2a452190511..e1ccf8f85a70 100644
--- a/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
+++ b/tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
@@ -12,40 +12,22 @@
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
struct fake_sigframe sf;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sve_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SVE, 2);
- /*
- * Enumerate up to SVE_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SVE_SET_VL, vq * 16);
- if (vl == -1)
- return false;
+ if (!res)
+ return true;
- vl &= PR_SVE_VL_LEN_MASK;
-
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
-
- vls[nvls++] = vl;
- }
-
- /* We need at least two VLs */
- if (nvls < 2) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
+ if (res == KSFT_SKIP)
td->result = KSFT_SKIP;
- return false;
- }
- return true;
+ return false;
}
static int fake_sigreturn_sve_change_vl(struct tdescr *td,
diff --git a/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c b/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c
index 3d37daafcff5..6dbe48cf8b09 100644
--- a/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c
+++ b/tools/testing/selftests/arm64/signal/testcases/ssve_regs.c
@@ -6,51 +6,31 @@
* set up as expected.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
static union {
ucontext_t uc;
char buf[1024 * 64];
} context;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sme_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SME, 1);
- /*
- * Enumerate up to SVE_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SME_SET_VL, vq * 16);
- if (vl == -1)
- return false;
-
- vl &= PR_SME_VL_LEN_MASK;
-
- /* Did we find the lowest supported VL? */
- if (vq < sve_vq_from_vl(vl))
- break;
+ if (!res)
+ return true;
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
-
- vls[nvls++] = vl;
- }
-
- /* We need at least one VL */
- if (nvls < 1) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- return true;
+ return false;
}
static void setup_ssve_regs(void)
diff --git a/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c b/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c
index 9dc5f128bbc0..5557e116e973 100644
--- a/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c
+++ b/tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c
@@ -6,51 +6,31 @@
* signal frames is set up as expected when enabled simultaneously.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
static union {
ucontext_t uc;
char buf[1024 * 128];
} context;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sme_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SME, 1);
- /*
- * Enumerate up to SVE_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SME_SET_VL, vq * 16);
- if (vl == -1)
- return false;
-
- vl &= PR_SME_VL_LEN_MASK;
-
- /* Did we find the lowest supported VL? */
- if (vq < sve_vq_from_vl(vl))
- break;
+ if (!res)
+ return true;
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
-
- vls[nvls++] = vl;
- }
-
- /* We need at least one VL */
- if (nvls < 1) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- return true;
+ return false;
}
static void setup_regs(void)
diff --git a/tools/testing/selftests/arm64/signal/testcases/sve_regs.c b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c
index 8b16eabbb769..8143eb1c58c1 100644
--- a/tools/testing/selftests/arm64/signal/testcases/sve_regs.c
+++ b/tools/testing/selftests/arm64/signal/testcases/sve_regs.c
@@ -6,47 +6,31 @@
* expected.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
static union {
ucontext_t uc;
char buf[1024 * 64];
} context;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sve_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SVE, 1);
- /*
- * Enumerate up to SVE_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SVE_SET_VL, vq * 16);
- if (vl == -1)
- return false;
-
- vl &= PR_SVE_VL_LEN_MASK;
-
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
+ if (!res)
+ return true;
- vls[nvls++] = vl;
- }
-
- /* We need at least one VL */
- if (nvls < 1) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- return true;
+ return false;
}
static void setup_sve_regs(void)
diff --git a/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c b/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c
index 4d6f94b6178f..ce26e9c2fa5e 100644
--- a/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c
+++ b/tools/testing/selftests/arm64/signal/testcases/za_no_regs.c
@@ -6,47 +6,31 @@
* expected.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
static union {
ucontext_t uc;
char buf[1024 * 128];
} context;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sme_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SME, 1);
- /*
- * Enumerate up to SME_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SME_SET_VL, vq * 16);
- if (vl == -1)
- return false;
-
- vl &= PR_SME_VL_LEN_MASK;
-
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
+ if (!res)
+ return true;
- vls[nvls++] = vl;
- }
-
- /* We need at least one VL */
- if (nvls < 1) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- return true;
+ return false;
}
static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
diff --git a/tools/testing/selftests/arm64/signal/testcases/za_regs.c b/tools/testing/selftests/arm64/signal/testcases/za_regs.c
index 174ad6656696..b9e13f27f1f9 100644
--- a/tools/testing/selftests/arm64/signal/testcases/za_regs.c
+++ b/tools/testing/selftests/arm64/signal/testcases/za_regs.c
@@ -6,51 +6,31 @@
* expected.
*/
+#include <kselftest.h>
#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>
#include "test_signals_utils.h"
+#include "sve_helpers.h"
#include "testcases.h"
static union {
ucontext_t uc;
char buf[1024 * 128];
} context;
-static unsigned int vls[SVE_VQ_MAX];
-unsigned int nvls = 0;
static bool sme_get_vls(struct tdescr *td)
{
- int vq, vl;
+ int res = sve_fill_vls(VLS_USE_SME, 1);
- /*
- * Enumerate up to SME_VQ_MAX vector lengths
- */
- for (vq = SVE_VQ_MAX; vq > 0; --vq) {
- vl = prctl(PR_SME_SET_VL, vq * 16);
- if (vl == -1)
- return false;
-
- vl &= PR_SME_VL_LEN_MASK;
-
- /* Did we find the lowest supported VL? */
- if (vq < sve_vq_from_vl(vl))
- break;
+ if (!res)
+ return true;
- /* Skip missing VLs */
- vq = sve_vq_from_vl(vl);
-
- vls[nvls++] = vl;
- }
-
- /* We need at least one VL */
- if (nvls < 1) {
- fprintf(stderr, "Only %d VL supported\n", nvls);
- return false;
- }
+ if (res == KSFT_SKIP)
+ td->result = KSFT_SKIP;
- return true;
+ return false;
}
static void setup_za_regs(void)