Skip to contentSkip to conversation

kselftest/arm64: SVE signal handling tests

PATCH In review Mark Brown 2 participants 8 messages Aug 19, 2021 – Aug 23, 2021

Subsystems (2)
lore
Share & tools
lore

Mark Brown

author
#0 lore raw

cover kselftest/arm64: SVE signal handling tests

Currently we have no real tests for SVE signal handling (though the stress test does trigger the code paths as it regularly sends signals to the test processes). Add some basic coverage, this is very much incomplete but it's more coverage than we currently have, a TODO file is included with some omissions that occurred to me.

Mark Brown (6):
kselftest/arm64: signal: Add SVE to the set of features we can check
for
kselftest/arm64: signal: Support signal frames with SVE register data kselftest/arm64: signal: Check SVE signal frame shows expected vector
length
kselftest/arm64: signal: Verify that signals can't change the SVE
vector length
kselftest/arm64: signal: Add test case for SVE register state in
signals
kselftest/arm64: signal: Add a TODO list for signal handling tests

 .../testing/selftests/arm64/signal/.gitignore |   1 +
 .../selftests/arm64/signal/test_signals.h     |   2 +
 .../arm64/signal/test_signals_utils.c         |   3 +
 .../selftests/arm64/signal/testcases/TODO     |   2 +
 .../testcases/fake_sigreturn_sve_change_vl.c  |  92 +++++++++++++
 .../arm64/signal/testcases/sve_regs.c         | 126 ++++++++++++++++++
 .../selftests/arm64/signal/testcases/sve_vl.c |  68 ++++++++++
 .../arm64/signal/testcases/testcases.c        |  34 ++++-
 8 files changed, 325 insertions(+), 3 deletions(-)
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/TODO
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/sve_regs.c
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/sve_vl.c

base-commit: ff1176468d368232b684f75e82563369208bc371

Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#1 lore raw

PATCH 1/6 kselftest/arm64: signal: Add SVE to the set of features we can check for

Allow testcases for SVE signal handling to flag the dependency and be skipped on systems without SVE support.

---
 tools/testing/selftests/arm64/signal/test_signals.h       | 2 ++
 tools/testing/selftests/arm64/signal/test_signals_utils.c | 3 +++
 2 files changed, 5 insertions(+)
tools/testing/selftests/arm64/signal/test_signals.h +2 -0
index f96baf1cef1a..ebe8694dbef0 100644
@@ -33,10 +33,12 @@
  */
 enum {
 	FSSBS_BIT,
+	FSVE_BIT,
 	FMAX_END
 };
 
 #define FEAT_SSBS		(1UL << FSSBS_BIT)
+#define FEAT_SVE		(1UL << FSVE_BIT)
 
 /*
  * A descriptor used to describe and configure a test case.
tools/testing/selftests/arm64/signal/test_signals_utils.c +3 -0
index 2de6e5ed5e25..6836510a522f 100644
@@ -26,6 +26,7 @@ static int sig_copyctx = SIGTRAP;
 
 static char const *const feats_names[FMAX_END] = {
 	" SSBS ",
+	" SVE ",
 };
 
 #define MAX_FEATS_SZ	128
@@ -263,6 +264,8 @@ int test_init(struct tdescr *td)
 		 */
 		if (getauxval(AT_HWCAP) & HWCAP_SSBS)
 			td->feats_supported |= FEAT_SSBS;
+		if (getauxval(AT_HWCAP) & HWCAP_SVE)
+			td->feats_supported |= FEAT_SVE;
 		if (feats_ok(td))
 			fprintf(stderr,
 				"Required Features: [%s] supported\n",
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#2 lore raw

PATCH 2/6 kselftest/arm64: signal: Support signal frames with SVE register data

In reply to Mark Brown

A signal frame with SVE may validly either be a bare struct sve_context or a struct sve_context followed by vector length dependent register data. Support either in the generic helpers for the signal tests, and while we're at it validate the SVE vector length reported.

---
 .../arm64/signal/testcases/testcases.c        | 34 +++++++++++++++++--
 1 file changed, 31 insertions(+), 3 deletions(-)
tools/testing/selftests/arm64/signal/testcases/testcases.c +31 -3
index 61ebcdf63831..8c2a57fc2f9c 100644
@@ -50,12 +50,38 @@ bool validate_extra_context(struct extra_context *extra, char **err)
 	return true;
 }
 
+bool validate_sve_context(struct sve_context *sve, char **err)
+{
+	/* Size will be rounded up to a multiple of 16 bytes */
+	size_t regs_size
+		= ((SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)) + 15) / 16) * 16;
+
+	if (!sve || !err)
+		return false;
+
+	/* Either a bare sve_context or a sve_context followed by regs data */
+	if ((sve->head.size != sizeof(struct sve_context)) &&
+	    (sve->head.size != regs_size)) {
+		*err = "bad size for SVE context";
+		return false;
+	}
+
+	if (!sve_vl_valid(sve->vl)) {
+		*err = "SVE VL invalid";
+
+		return false;
+	}
+
+	return true;
+}
+
 bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
 {
 	bool terminated = false;
 	size_t offs = 0;
 	int flags = 0;
 	struct extra_context *extra = NULL;
+	struct sve_context *sve = NULL;
 	struct _aarch64_ctx *head =
 		(struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
 
@@ -90,9 +116,8 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
 		case SVE_MAGIC:
 			if (flags & SVE_CTX)
 				*err = "Multiple SVE_MAGIC";
-			else if (head->size !=
-				 sizeof(struct sve_context))
-				*err = "Bad size for sve_context";
+			/* Size is validated in validate_sve_context() */
+			sve = (struct sve_context *)head;
 			flags |= SVE_CTX;
 			break;
 		case EXTRA_MAGIC:
@@ -137,6 +162,9 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
 		if (flags & EXTRA_CTX)
 			if (!validate_extra_context(extra, err))
 				return false;
+		if (flags & SVE_CTX)
+			if (!validate_sve_context(sve, err))
+				return false;
 
 		head = GET_RESV_NEXT_HEAD(head);
 	}
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#3 lore raw

PATCH 3/6 kselftest/arm64: signal: Check SVE signal frame shows expected vector length

In reply to Mark Brown

As a basic check that the SVE signal frame is being set up correctly verify that the vector length in the signal frame is the vector length that the process has.

---
 .../testing/selftests/arm64/signal/.gitignore |  1 +
 .../selftests/arm64/signal/testcases/sve_vl.c | 68 +++++++++++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/sve_vl.c
tools/testing/selftests/arm64/signal/.gitignore +1 -0
index 78c902045ca7..c1742755abb9 100644
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mangle_*
 fake_sigreturn_*
+sve_*
 !*.[ch]
tools/testing/selftests/arm64/signal/testcases/sve_vl.c new file +68 -0

68 lines not on this page · raw message

Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#4 lore raw

PATCH 4/6 kselftest/arm64: signal: Verify that signals can't change the SVE vector length

In reply to Mark Brown

We do not support changing the SVE vector length as part of signal return, verify that this is the case if the system supports multiple vector lengths.

---
 .../testcases/fake_sigreturn_sve_change_vl.c  | 92 +++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c
tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sve_change_vl.c new file +92 -0
new file mode 100644
index 000000000000..bb50b5adbf10
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 ARM Limited
+ *
+ * Attempt to change the SVE vector length in a signal hander, this is not
+ * supported and is expected to segfault.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/prctl.h>
+
+#include "test_signals_utils.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;
+
+	/*
+	 * 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);
+
+		vls[nvls++] = vl;
+	}
+
+	/* We need at least two VLs */
+	if (nvls < 2) {
+		fprintf(stderr, "Only %d VL supported\n", nvls);
+		return false;
+	}
+
+	return true;
+}
+
+static int fake_sigreturn_sve_change_vl(struct tdescr *td,
+					siginfo_t *si, ucontext_t *uc)
+{
+	size_t resv_sz, offset;
+	struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
+	struct sve_context *sve;
+
+	/* Get a signal context with a SVE frame in it */
+	if (!get_current_context(td, &sf.uc))
+		return 1;
+
+	resv_sz = GET_SF_RESV_SIZE(sf);
+	head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+	if (!head) {
+		fprintf(stderr, "No SVE context\n");
+		return 1;
+	}
+
+	if (head->size != sizeof(struct sve_context)) {
+		fprintf(stderr, "SVE register state active, skipping\n");
+		return 1;
+	}
+
+	sve = (struct sve_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];
+
+	fake_sigreturn(&sf, sizeof(sf), 0);
+
+	return 1;
+}
+
+struct tdescr tde = {
+	.name = "FAKE_SIGRETURN_SVE_CHANGE",
+	.descr = "Attempt to change SVE VL",
+	.feats_required = FEAT_SVE,
+	.sig_ok = SIGSEGV,
+	.timeout = 3,
+	.init = sve_get_vls,
+	.run = fake_sigreturn_sve_change_vl,
+};
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#5 lore raw

PATCH 5/6 kselftest/arm64: signal: Add test case for SVE register state in signals

In reply to Mark Brown

Currently this doesn't actually verify that the register contents do the right thing, it just verifes that a SVE context with appropriate size appears.

---
 .../arm64/signal/testcases/sve_regs.c         | 126 ++++++++++++++++++
 1 file changed, 126 insertions(+)
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/sve_regs.c
tools/testing/selftests/arm64/signal/testcases/sve_regs.c new file +126 -0
new file mode 100644
index 000000000000..4b2418aa08a9
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 ARM Limited
+ *
+ * Verify that the SVE register context in signal frames is set up as
+ * expected.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/prctl.h>
+
+#include "test_signals_utils.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;
+
+	/*
+	 * 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);
+
+		vls[nvls++] = vl;
+	}
+
+	/* We need at least one VL */
+	if (nvls < 1) {
+		fprintf(stderr, "Only %d VL supported\n", nvls);
+		return false;
+	}
+
+	return true;
+}
+
+static void setup_sve_regs(void)
+{
+	/* RDVL x16, #1 so we should have SVE regs; real data is TODO */
+	asm volatile(".inst 0x04bf5030" : : : "x16" );
+}
+
+static int do_one_sve_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
+			 unsigned int vl)
+{
+	size_t resv_sz, offset;
+	struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
+	struct sve_context *sve;
+
+	fprintf(stderr, "Testing VL %d\n", vl);
+
+	if (prctl(PR_SVE_SET_VL, vl) == -1) {
+		fprintf(stderr, "Failed to set VL\n");
+		return 1;
+	}
+
+	/*
+	 * Get a signal context which should have a SVE frame and registers
+	 * in it.
+	 */
+	setup_sve_regs();
+	if (!get_current_context(td, &sf.uc))
+		return 1;
+
+	resv_sz = GET_SF_RESV_SIZE(sf);
+	head = get_header(head, SVE_MAGIC, resv_sz, &offset);
+	if (!head) {
+		fprintf(stderr, "No SVE context\n");
+		return 1;
+	}
+
+	sve = (struct sve_context *)head;
+	if (sve->vl != vl) {
+		fprintf(stderr, "Got VL %d, expected %d\n", sve->vl, vl);
+		return 1;
+	}
+
+	/* The actual size validation is done in get_current_context() */
+	fprintf(stderr, "Got expected size %u and VL %d\n",
+		head->size, sve->vl);
+
+	return 0;
+}
+
+static int sve_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
+{
+	int i;
+
+	for (i = 0; i < nvls; i++) {
+		/*
+		 * TODO: the signal test helpers can't currently cope
+		 * with signal frames bigger than struct sigcontext,
+		 * skip VLs that will trigger that.
+		 */
+		if (vls[i] > 64)
+			continue;
+
+		if (do_one_sve_vl(td, si, uc, vls[i]))
+			return 1;
+	}
+
+	td->pass = 1;
+
+	return 0;
+}
+
+struct tdescr tde = {
+	.name = "SVE registers",
+	.descr = "Check that we get the right SVE registers reported",
+	.feats_required = FEAT_SVE,
+	.timeout = 3,
+	.init = sve_get_vls,
+	.run = sve_regs,
+};
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
author
#6 lore raw

PATCH 6/6 kselftest/arm64: signal: Add a TODO list for signal handling tests

In reply to Mark Brown

Note down a few gaps in our coverage.

---
 tools/testing/selftests/arm64/signal/testcases/TODO | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 tools/testing/selftests/arm64/signal/testcases/TODO
tools/testing/selftests/arm64/signal/testcases/TODO new file +2 -0
new file mode 100644
index 000000000000..110ff9fd195d
@@ -0,0 +1,2 @@
+- Validate that register contents are saved and restored as expected.
+- Support and validate extra_context.
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
maintainer
#7 lore raw
In reply to Mark Brown
Quoted 18 lines · Mark Brown

Currently we have no real tests for SVE signal handling (though the stress test does trigger the code paths as it regularly sends signals to the test processes). Add some basic coverage, this is very much incomplete but it's more coverage than we currently have, a TODO file is included with some omissions that occurred to me.

Mark Brown (6):
kselftest/arm64: signal: Add SVE to the set of features we can check
for
kselftest/arm64: signal: Support signal frames with SVE register data kselftest/arm64: signal: Check SVE signal frame shows expected vector
length
kselftest/arm64: signal: Verify that signals can't change the SVE
vector length
kselftest/arm64: signal: Add test case for SVE register state in
signals
kselftest/arm64: signal: Add a TODO list for signal handling tests

Quoted 1 line

[...]

Applied to arm64 (for-next/kselftest), thanks!

[1/6] kselftest/arm64: signal: Add SVE to the set of features we can check for

      https://git.kernel.org/arm64/c/d4e4dc4fab68
[2/6] kselftest/arm64: signal: Support signal frames with SVE register data
      https://git.kernel.org/arm64/c/ace19b1845a5
[3/6] kselftest/arm64: signal: Check SVE signal frame shows expected vector length
      https://git.kernel.org/arm64/c/c1f67a19c12e
[4/6] kselftest/arm64: signal: Verify that signals can't change the SVE vector length
      https://git.kernel.org/arm64/c/d25ac50ce8f7
[5/6] kselftest/arm64: signal: Add test case for SVE register state in signals
      https://git.kernel.org/arm64/c/5262b216f4a9
[6/6] kselftest/arm64: signal: Add a TODO list for signal handling tests
      https://git.kernel.org/arm64/c/fa5ca80db89e
Signature · 7 lines
Catalin


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel