Skip to content

Commit 4963aeb

Browse files
brooniectmarinas
authored andcommitted
kselftest/arm64: signal: Add SME signal handling tests
Add test cases for the SME signal handing ABI patterned off the SVE tests. Due to the small size of the tests and the differences in ABI (especially around needing to account for both streaming SVE and ZA) there is some code duplication here. We currently cover: - Reporting of the vector length. - Lack of support for changing vector length. - Presence and size of register state for streaming SVE and ZA. As with the SVE tests we do not yet have any validation of register contents. Signed-off-by: Mark Brown <broonie@kernel.org> Reviewed-by: Shuah Khan <skhan@linuxfoundation.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Link: https://lore.kernel.org/r/20220419112247.711548-36-broonie@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 5aa45cc commit 4963aeb

10 files changed

Lines changed: 555 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
mangle_*
33
fake_sigreturn_*
4+
sme_*
5+
ssve_*
46
sve_*
7+
za_*
58
!*.[ch]

tools/testing/selftests/arm64/signal/test_signals.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@
3434
enum {
3535
FSSBS_BIT,
3636
FSVE_BIT,
37+
FSME_BIT,
38+
FSME_FA64_BIT,
3739
FMAX_END
3840
};
3941

4042
#define FEAT_SSBS (1UL << FSSBS_BIT)
4143
#define FEAT_SVE (1UL << FSVE_BIT)
44+
#define FEAT_SME (1UL << FSME_BIT)
45+
#define FEAT_SME_FA64 (1UL << FSME_FA64_BIT)
4246

4347
/*
4448
* A descriptor used to describe and configure a test case.

tools/testing/selftests/arm64/signal/test_signals_utils.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ static int sig_copyctx = SIGTRAP;
2727
static char const *const feats_names[FMAX_END] = {
2828
" SSBS ",
2929
" SVE ",
30+
" SME ",
31+
" FA64 ",
3032
};
3133

3234
#define MAX_FEATS_SZ 128
@@ -268,6 +270,10 @@ int test_init(struct tdescr *td)
268270
td->feats_supported |= FEAT_SSBS;
269271
if (getauxval(AT_HWCAP) & HWCAP_SVE)
270272
td->feats_supported |= FEAT_SVE;
273+
if (getauxval(AT_HWCAP2) & HWCAP2_SME)
274+
td->feats_supported |= FEAT_SME;
275+
if (getauxval(AT_HWCAP2) & HWCAP2_SME_FA64)
276+
td->feats_supported |= FEAT_SME_FA64;
271277
if (feats_ok(td)) {
272278
if (td->feats_required & td->feats_supported)
273279
fprintf(stderr,
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 ARM Limited
4+
*
5+
* Attempt to change the streaming SVE vector length in a signal
6+
* handler, this is not supported and is expected to segfault.
7+
*/
8+
9+
#include <signal.h>
10+
#include <ucontext.h>
11+
#include <sys/prctl.h>
12+
13+
#include "test_signals_utils.h"
14+
#include "testcases.h"
15+
16+
struct fake_sigframe sf;
17+
static unsigned int vls[SVE_VQ_MAX];
18+
unsigned int nvls = 0;
19+
20+
static bool sme_get_vls(struct tdescr *td)
21+
{
22+
int vq, vl;
23+
24+
/*
25+
* Enumerate up to SVE_VQ_MAX vector lengths
26+
*/
27+
for (vq = SVE_VQ_MAX; vq > 0; --vq) {
28+
vl = prctl(PR_SVE_SET_VL, vq * 16);
29+
if (vl == -1)
30+
return false;
31+
32+
vl &= PR_SME_VL_LEN_MASK;
33+
34+
/* Skip missing VLs */
35+
vq = sve_vq_from_vl(vl);
36+
37+
vls[nvls++] = vl;
38+
}
39+
40+
/* We need at least two VLs */
41+
if (nvls < 2) {
42+
fprintf(stderr, "Only %d VL supported\n", nvls);
43+
return false;
44+
}
45+
46+
return true;
47+
}
48+
49+
static int fake_sigreturn_ssve_change_vl(struct tdescr *td,
50+
siginfo_t *si, ucontext_t *uc)
51+
{
52+
size_t resv_sz, offset;
53+
struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
54+
struct sve_context *sve;
55+
56+
/* Get a signal context with a SME ZA frame in it */
57+
if (!get_current_context(td, &sf.uc))
58+
return 1;
59+
60+
resv_sz = GET_SF_RESV_SIZE(sf);
61+
head = get_header(head, SVE_MAGIC, resv_sz, &offset);
62+
if (!head) {
63+
fprintf(stderr, "No SVE context\n");
64+
return 1;
65+
}
66+
67+
if (head->size != sizeof(struct sve_context)) {
68+
fprintf(stderr, "Register data present, aborting\n");
69+
return 1;
70+
}
71+
72+
sve = (struct sve_context *)head;
73+
74+
/* No changes are supported; init left us at minimum VL so go to max */
75+
fprintf(stderr, "Attempting to change VL from %d to %d\n",
76+
sve->vl, vls[0]);
77+
sve->vl = vls[0];
78+
79+
fake_sigreturn(&sf, sizeof(sf), 0);
80+
81+
return 1;
82+
}
83+
84+
struct tdescr tde = {
85+
.name = "FAKE_SIGRETURN_SSVE_CHANGE",
86+
.descr = "Attempt to change Streaming SVE VL",
87+
.feats_required = FEAT_SME,
88+
.sig_ok = SIGSEGV,
89+
.timeout = 3,
90+
.init = sme_get_vls,
91+
.run = fake_sigreturn_ssve_change_vl,
92+
};
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 ARM Limited
4+
*
5+
* Verify that using a streaming mode instruction without enabling it
6+
* generates a SIGILL.
7+
*/
8+
9+
#include <signal.h>
10+
#include <ucontext.h>
11+
#include <sys/prctl.h>
12+
13+
#include "test_signals_utils.h"
14+
#include "testcases.h"
15+
16+
int sme_trap_no_sm_trigger(struct tdescr *td)
17+
{
18+
/* SMSTART ZA ; ADDHA ZA0.S, P0/M, P0/M, Z0.S */
19+
asm volatile(".inst 0xd503457f ; .inst 0xc0900000");
20+
21+
return 0;
22+
}
23+
24+
int sme_trap_no_sm_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
25+
{
26+
return 1;
27+
}
28+
29+
struct tdescr tde = {
30+
.name = "SME trap without SM",
31+
.descr = "Check that we get a SIGILL if we use streaming mode without enabling it",
32+
.timeout = 3,
33+
.feats_required = FEAT_SME, /* We need a SMSTART ZA */
34+
.sanity_disabled = true,
35+
.trigger = sme_trap_no_sm_trigger,
36+
.run = sme_trap_no_sm_run,
37+
.sig_ok = SIGILL,
38+
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 ARM Limited
4+
*
5+
* Verify that using an instruction not supported in streaming mode
6+
* traps when in streaming mode.
7+
*/
8+
9+
#include <signal.h>
10+
#include <ucontext.h>
11+
#include <sys/prctl.h>
12+
13+
#include "test_signals_utils.h"
14+
#include "testcases.h"
15+
16+
int sme_trap_non_streaming_trigger(struct tdescr *td)
17+
{
18+
/*
19+
* The framework will handle SIGILL so we need to exit SM to
20+
* stop any other code triggering a further SIGILL down the
21+
* line from using a streaming-illegal instruction.
22+
*/
23+
asm volatile(".inst 0xd503437f; /* SMSTART ZA */ \
24+
cnt v0.16b, v0.16b; \
25+
.inst 0xd503447f /* SMSTOP ZA */");
26+
27+
return 0;
28+
}
29+
30+
int sme_trap_non_streaming_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
31+
{
32+
return 1;
33+
}
34+
35+
struct tdescr tde = {
36+
.name = "SME SM trap unsupported instruction",
37+
.descr = "Check that we get a SIGILL if we use an unsupported instruction in streaming mode",
38+
.feats_required = FEAT_SME,
39+
.feats_incompatible = FEAT_SME_FA64,
40+
.timeout = 3,
41+
.sanity_disabled = true,
42+
.trigger = sme_trap_non_streaming_trigger,
43+
.run = sme_trap_non_streaming_run,
44+
.sig_ok = SIGILL,
45+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 ARM Limited
4+
*
5+
* Verify that accessing ZA without enabling it generates a SIGILL.
6+
*/
7+
8+
#include <signal.h>
9+
#include <ucontext.h>
10+
#include <sys/prctl.h>
11+
12+
#include "test_signals_utils.h"
13+
#include "testcases.h"
14+
15+
int sme_trap_za_trigger(struct tdescr *td)
16+
{
17+
/* ZERO ZA */
18+
asm volatile(".inst 0xc00800ff");
19+
20+
return 0;
21+
}
22+
23+
int sme_trap_za_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
24+
{
25+
return 1;
26+
}
27+
28+
struct tdescr tde = {
29+
.name = "SME ZA trap",
30+
.descr = "Check that we get a SIGILL if we access ZA without enabling",
31+
.timeout = 3,
32+
.sanity_disabled = true,
33+
.trigger = sme_trap_za_trigger,
34+
.run = sme_trap_za_run,
35+
.sig_ok = SIGILL,
36+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2021 ARM Limited
4+
*
5+
* Check that the SME vector length reported in signal contexts is the
6+
* expected one.
7+
*/
8+
9+
#include <signal.h>
10+
#include <ucontext.h>
11+
#include <sys/prctl.h>
12+
13+
#include "test_signals_utils.h"
14+
#include "testcases.h"
15+
16+
struct fake_sigframe sf;
17+
unsigned int vl;
18+
19+
static bool get_sme_vl(struct tdescr *td)
20+
{
21+
int ret = prctl(PR_SME_GET_VL);
22+
if (ret == -1)
23+
return false;
24+
25+
vl = ret;
26+
27+
return true;
28+
}
29+
30+
static int sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
31+
{
32+
size_t resv_sz, offset;
33+
struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
34+
struct za_context *za;
35+
36+
/* Get a signal context which should have a ZA frame in it */
37+
if (!get_current_context(td, &sf.uc))
38+
return 1;
39+
40+
resv_sz = GET_SF_RESV_SIZE(sf);
41+
head = get_header(head, ZA_MAGIC, resv_sz, &offset);
42+
if (!head) {
43+
fprintf(stderr, "No ZA context\n");
44+
return 1;
45+
}
46+
za = (struct za_context *)head;
47+
48+
if (za->vl != vl) {
49+
fprintf(stderr, "ZA sigframe VL %u, expected %u\n",
50+
za->vl, vl);
51+
return 1;
52+
} else {
53+
fprintf(stderr, "got expected VL %u\n", vl);
54+
}
55+
56+
td->pass = 1;
57+
58+
return 0;
59+
}
60+
61+
struct tdescr tde = {
62+
.name = "SME VL",
63+
.descr = "Check that we get the right SME VL reported",
64+
.feats_required = FEAT_SME,
65+
.timeout = 3,
66+
.init = get_sme_vl,
67+
.run = sme_vl,
68+
};

0 commit comments

Comments
 (0)