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
sme_get_vls(struct tdescr * td)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
fake_sigreturn_ssve_change_vl(struct tdescr * td,siginfo_t * si,ucontext_t * uc)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, sizeof(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 };
93