Skip to content

Commit c397623

Browse files
committed
Merge branch 'for-next/kselftest' into for-next/core
* for-next/kselftest: (28 commits) : Kselftest updates for arm64 kselftest/arm64: Handle EINTR while reading data from children kselftest/arm64: Flag fp-stress as exiting when we begin finishing up kselftest/arm64: Don't repeat termination handler for fp-stress kselftest/arm64: Don't enable v8.5 for MTE selftest builds kselftest/arm64: Fix typo in hwcap check kselftest/arm64: Add hwcap test for RNG kselftest/arm64: Add SVE 2 to the tested hwcaps kselftest/arm64: Add missing newline in hwcap output kselftest/arm64: Fix spelling misakes of signal names kselftest/arm64: Enforce actual ABI for SVE syscalls kselftest/arm64: Correct buffer allocation for SVE Z registers kselftest/arm64: Include larger SVE and SME VLs in signal tests kselftest/arm64: Allow larger buffers in get_signal_context() kselftest/arm64: Preserve any EXTRA_CONTEXT in handle_signal_copyctx() kselftest/arm64: Validate contents of EXTRA_CONTEXT blocks kselftest/arm64: Only validate each signal context once kselftest/arm64: Remove unneeded protype for validate_extra_context() kselftest/arm64: Fix validation of EXTRA_CONTEXT signal context location kselftest/arm64: Fix validatation termination record after EXTRA_CONTEXT kselftest/arm64: Validate signal ucontext in place ...
2 parents b23ec74 + a711987 commit c397623

31 files changed

+1313
-168
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
hwcap
12
ptrace
23
syscall-abi
34
tpidr2

tools/testing/selftests/arm64/abi/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
# Copyright (C) 2021 ARM Limited
33

4-
TEST_GEN_PROGS := ptrace syscall-abi tpidr2
4+
TEST_GEN_PROGS := hwcap ptrace syscall-abi tpidr2
55

66
include ../../lib.mk
77

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2022 ARM Limited.
4+
*/
5+
6+
#include <errno.h>
7+
#include <signal.h>
8+
#include <stdbool.h>
9+
#include <stddef.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <string.h>
13+
#include <unistd.h>
14+
#include <sys/auxv.h>
15+
#include <sys/prctl.h>
16+
#include <asm/hwcap.h>
17+
#include <asm/sigcontext.h>
18+
#include <asm/unistd.h>
19+
20+
#include "../../kselftest.h"
21+
22+
#define TESTS_PER_HWCAP 2
23+
24+
/*
25+
* Function expected to generate SIGILL when the feature is not
26+
* supported and return when it is supported. If SIGILL is generated
27+
* then the handler must be able to skip over the instruction safely.
28+
*
29+
* Note that it is expected that for many architecture extensions
30+
* there are no specific traps due to no architecture state being
31+
* added so we may not fault if running on a kernel which doesn't know
32+
* to add the hwcap.
33+
*/
34+
typedef void (*sigill_fn)(void);
35+
36+
static void rng_sigill(void)
37+
{
38+
asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
39+
}
40+
41+
static void sme_sigill(void)
42+
{
43+
/* RDSVL x0, #0 */
44+
asm volatile(".inst 0x04bf5800" : : : "x0");
45+
}
46+
47+
static void sve_sigill(void)
48+
{
49+
/* RDVL x0, #0 */
50+
asm volatile(".inst 0x04bf5000" : : : "x0");
51+
}
52+
53+
static void sve2_sigill(void)
54+
{
55+
/* SQABS Z0.b, P0/M, Z0.B */
56+
asm volatile(".inst 0x4408A000" : : : "z0");
57+
}
58+
59+
static void sveaes_sigill(void)
60+
{
61+
/* AESD z0.b, z0.b, z0.b */
62+
asm volatile(".inst 0x4522e400" : : : "z0");
63+
}
64+
65+
static void svepmull_sigill(void)
66+
{
67+
/* PMULLB Z0.Q, Z0.D, Z0.D */
68+
asm volatile(".inst 0x45006800" : : : "z0");
69+
}
70+
71+
static void svebitperm_sigill(void)
72+
{
73+
/* BDEP Z0.B, Z0.B, Z0.B */
74+
asm volatile(".inst 0x4500b400" : : : "z0");
75+
}
76+
77+
static void svesha3_sigill(void)
78+
{
79+
/* EOR3 Z0.D, Z0.D, Z0.D, Z0.D */
80+
asm volatile(".inst 0x4203800" : : : "z0");
81+
}
82+
83+
static void svesm4_sigill(void)
84+
{
85+
/* SM4E Z0.S, Z0.S, Z0.S */
86+
asm volatile(".inst 0x4523e000" : : : "z0");
87+
}
88+
89+
static void svei8mm_sigill(void)
90+
{
91+
/* USDOT Z0.S, Z0.B, Z0.B[0] */
92+
asm volatile(".inst 0x44a01800" : : : "z0");
93+
}
94+
95+
static void svef32mm_sigill(void)
96+
{
97+
/* FMMLA Z0.S, Z0.S, Z0.S */
98+
asm volatile(".inst 0x64a0e400" : : : "z0");
99+
}
100+
101+
static void svef64mm_sigill(void)
102+
{
103+
/* FMMLA Z0.D, Z0.D, Z0.D */
104+
asm volatile(".inst 0x64e0e400" : : : "z0");
105+
}
106+
107+
static void svebf16_sigill(void)
108+
{
109+
/* BFCVT Z0.H, P0/M, Z0.S */
110+
asm volatile(".inst 0x658aa000" : : : "z0");
111+
}
112+
113+
static const struct hwcap_data {
114+
const char *name;
115+
unsigned long at_hwcap;
116+
unsigned long hwcap_bit;
117+
const char *cpuinfo;
118+
sigill_fn sigill_fn;
119+
bool sigill_reliable;
120+
} hwcaps[] = {
121+
{
122+
.name = "RNG",
123+
.at_hwcap = AT_HWCAP2,
124+
.hwcap_bit = HWCAP2_RNG,
125+
.cpuinfo = "rng",
126+
.sigill_fn = rng_sigill,
127+
},
128+
{
129+
.name = "SME",
130+
.at_hwcap = AT_HWCAP2,
131+
.hwcap_bit = HWCAP2_SME,
132+
.cpuinfo = "sme",
133+
.sigill_fn = sme_sigill,
134+
.sigill_reliable = true,
135+
},
136+
{
137+
.name = "SVE",
138+
.at_hwcap = AT_HWCAP,
139+
.hwcap_bit = HWCAP_SVE,
140+
.cpuinfo = "sve",
141+
.sigill_fn = sve_sigill,
142+
.sigill_reliable = true,
143+
},
144+
{
145+
.name = "SVE 2",
146+
.at_hwcap = AT_HWCAP2,
147+
.hwcap_bit = HWCAP2_SVE2,
148+
.cpuinfo = "sve2",
149+
.sigill_fn = sve2_sigill,
150+
},
151+
{
152+
.name = "SVE AES",
153+
.at_hwcap = AT_HWCAP2,
154+
.hwcap_bit = HWCAP2_SVEAES,
155+
.cpuinfo = "sveaes",
156+
.sigill_fn = sveaes_sigill,
157+
},
158+
{
159+
.name = "SVE2 PMULL",
160+
.at_hwcap = AT_HWCAP2,
161+
.hwcap_bit = HWCAP2_SVEPMULL,
162+
.cpuinfo = "svepmull",
163+
.sigill_fn = svepmull_sigill,
164+
},
165+
{
166+
.name = "SVE2 BITPERM",
167+
.at_hwcap = AT_HWCAP2,
168+
.hwcap_bit = HWCAP2_SVEBITPERM,
169+
.cpuinfo = "svebitperm",
170+
.sigill_fn = svebitperm_sigill,
171+
},
172+
{
173+
.name = "SVE2 SHA3",
174+
.at_hwcap = AT_HWCAP2,
175+
.hwcap_bit = HWCAP2_SVESHA3,
176+
.cpuinfo = "svesha3",
177+
.sigill_fn = svesha3_sigill,
178+
},
179+
{
180+
.name = "SVE2 SM4",
181+
.at_hwcap = AT_HWCAP2,
182+
.hwcap_bit = HWCAP2_SVESM4,
183+
.cpuinfo = "svesm4",
184+
.sigill_fn = svesm4_sigill,
185+
},
186+
{
187+
.name = "SVE2 I8MM",
188+
.at_hwcap = AT_HWCAP2,
189+
.hwcap_bit = HWCAP2_SVEI8MM,
190+
.cpuinfo = "svei8mm",
191+
.sigill_fn = svei8mm_sigill,
192+
},
193+
{
194+
.name = "SVE2 F32MM",
195+
.at_hwcap = AT_HWCAP2,
196+
.hwcap_bit = HWCAP2_SVEF32MM,
197+
.cpuinfo = "svef32mm",
198+
.sigill_fn = svef32mm_sigill,
199+
},
200+
{
201+
.name = "SVE2 F64MM",
202+
.at_hwcap = AT_HWCAP2,
203+
.hwcap_bit = HWCAP2_SVEF64MM,
204+
.cpuinfo = "svef64mm",
205+
.sigill_fn = svef64mm_sigill,
206+
},
207+
{
208+
.name = "SVE2 BF16",
209+
.at_hwcap = AT_HWCAP2,
210+
.hwcap_bit = HWCAP2_SVEBF16,
211+
.cpuinfo = "svebf16",
212+
.sigill_fn = svebf16_sigill,
213+
},
214+
{
215+
.name = "SVE2 EBF16",
216+
.at_hwcap = AT_HWCAP2,
217+
.hwcap_bit = HWCAP2_SVE_EBF16,
218+
.cpuinfo = "sveebf16",
219+
},
220+
};
221+
222+
static bool seen_sigill;
223+
224+
static void handle_sigill(int sig, siginfo_t *info, void *context)
225+
{
226+
ucontext_t *uc = context;
227+
228+
seen_sigill = true;
229+
230+
/* Skip over the offending instruction */
231+
uc->uc_mcontext.pc += 4;
232+
}
233+
234+
bool cpuinfo_present(const char *name)
235+
{
236+
FILE *f;
237+
char buf[2048], name_space[30], name_newline[30];
238+
char *s;
239+
240+
/*
241+
* The feature should appear with a leading space and either a
242+
* trailing space or a newline.
243+
*/
244+
snprintf(name_space, sizeof(name_space), " %s ", name);
245+
snprintf(name_newline, sizeof(name_newline), " %s\n", name);
246+
247+
f = fopen("/proc/cpuinfo", "r");
248+
if (!f) {
249+
ksft_print_msg("Failed to open /proc/cpuinfo\n");
250+
return false;
251+
}
252+
253+
while (fgets(buf, sizeof(buf), f)) {
254+
/* Features: line? */
255+
if (strncmp(buf, "Features\t:", strlen("Features\t:")) != 0)
256+
continue;
257+
258+
/* All CPUs should be symmetric, don't read any more */
259+
fclose(f);
260+
261+
s = strstr(buf, name_space);
262+
if (s)
263+
return true;
264+
s = strstr(buf, name_newline);
265+
if (s)
266+
return true;
267+
268+
return false;
269+
}
270+
271+
ksft_print_msg("Failed to find Features in /proc/cpuinfo\n");
272+
fclose(f);
273+
return false;
274+
}
275+
276+
int main(void)
277+
{
278+
const struct hwcap_data *hwcap;
279+
int i, ret;
280+
bool have_cpuinfo, have_hwcap;
281+
struct sigaction sa;
282+
283+
ksft_print_header();
284+
ksft_set_plan(ARRAY_SIZE(hwcaps) * TESTS_PER_HWCAP);
285+
286+
memset(&sa, 0, sizeof(sa));
287+
sa.sa_sigaction = handle_sigill;
288+
sa.sa_flags = SA_RESTART | SA_SIGINFO;
289+
sigemptyset(&sa.sa_mask);
290+
ret = sigaction(SIGILL, &sa, NULL);
291+
if (ret < 0)
292+
ksft_exit_fail_msg("Failed to install SIGILL handler: %s (%d)\n",
293+
strerror(errno), errno);
294+
295+
for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
296+
hwcap = &hwcaps[i];
297+
298+
have_hwcap = getauxval(hwcap->at_hwcap) & hwcap->hwcap_bit;
299+
have_cpuinfo = cpuinfo_present(hwcap->cpuinfo);
300+
301+
if (have_hwcap)
302+
ksft_print_msg("%s present\n", hwcap->name);
303+
304+
ksft_test_result(have_hwcap == have_cpuinfo,
305+
"cpuinfo_match_%s\n", hwcap->name);
306+
307+
if (hwcap->sigill_fn) {
308+
seen_sigill = false;
309+
hwcap->sigill_fn();
310+
311+
if (have_hwcap) {
312+
/* Should be able to use the extension */
313+
ksft_test_result(!seen_sigill, "sigill_%s\n",
314+
hwcap->name);
315+
} else if (hwcap->sigill_reliable) {
316+
/* Guaranteed a SIGILL */
317+
ksft_test_result(seen_sigill, "sigill_%s\n",
318+
hwcap->name);
319+
} else {
320+
/* Missing SIGILL might be fine */
321+
ksft_print_msg("SIGILL %sreported for %s\n",
322+
seen_sigill ? "" : "not ",
323+
hwcap->name);
324+
ksft_test_result_skip("sigill_%s\n",
325+
hwcap->name);
326+
}
327+
} else {
328+
ksft_test_result_skip("sigill_%s\n",
329+
hwcap->name);
330+
}
331+
}
332+
333+
ksft_print_cnts();
334+
335+
return 0;
336+
}

0 commit comments

Comments
 (0)