1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2021 ARM Limited
4 *
5 * Verify that the SVE register context in signal frames is set up as
6 * expected.
7 */
8
9 #include <kselftest.h>
10 #include <signal.h>
11 #include <ucontext.h>
12 #include <sys/prctl.h>
13
14 #include "test_signals_utils.h"
15 #include "sve_helpers.h"
16 #include "testcases.h"
17
18 static union {
19 ucontext_t uc;
20 char buf[1024 * 64];
21 } context;
22
sve_get_vls(struct tdescr * td)23 static bool sve_get_vls(struct tdescr *td)
24 {
25 int res = sve_fill_vls(VLS_USE_SVE, 1);
26
27 if (!res)
28 return true;
29
30 if (res == KSFT_SKIP)
31 td->result = KSFT_SKIP;
32
33 return false;
34 }
35
setup_sve_regs(void)36 static void setup_sve_regs(void)
37 {
38 /* RDVL x16, #1 so we should have SVE regs; real data is TODO */
39 asm volatile(".inst 0x04bf5030" : : : "x16" );
40 }
41
do_one_sve_vl(struct tdescr * td,siginfo_t * si,ucontext_t * uc,unsigned int vl)42 static int do_one_sve_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
43 unsigned int vl)
44 {
45 size_t offset;
46 struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context);
47 struct sve_context *sve;
48
49 fprintf(stderr, "Testing VL %d\n", vl);
50
51 if (prctl(PR_SVE_SET_VL, vl) == -1) {
52 fprintf(stderr, "Failed to set VL\n");
53 return 1;
54 }
55
56 /*
57 * Get a signal context which should have a SVE frame and registers
58 * in it.
59 */
60 setup_sve_regs();
61 if (!get_current_context(td, &context.uc, sizeof(context)))
62 return 1;
63
64 head = get_header(head, SVE_MAGIC, GET_BUF_RESV_SIZE(context),
65 &offset);
66 if (!head) {
67 fprintf(stderr, "No SVE context\n");
68 return 1;
69 }
70
71 sve = (struct sve_context *)head;
72 if (sve->vl != vl) {
73 fprintf(stderr, "Got VL %d, expected %d\n", sve->vl, vl);
74 return 1;
75 }
76
77 /* The actual size validation is done in get_current_context() */
78 fprintf(stderr, "Got expected size %u and VL %d\n",
79 head->size, sve->vl);
80
81 return 0;
82 }
83
sve_regs(struct tdescr * td,siginfo_t * si,ucontext_t * uc)84 static int sve_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
85 {
86 int i;
87
88 for (i = 0; i < nvls; i++) {
89 if (do_one_sve_vl(td, si, uc, vls[i]))
90 return 1;
91 }
92
93 td->pass = 1;
94
95 return 0;
96 }
97
98 struct tdescr tde = {
99 .name = "SVE registers",
100 .descr = "Check that we get the right SVE registers reported",
101 .feats_required = FEAT_SVE,
102 .timeout = 3,
103 .init = sve_get_vls,
104 .run = sve_regs,
105 };
106