Skip to content

Commit 57d7713

Browse files
charlie-rivospalmer-dabbelt
authored andcommitted
selftests: riscv: Fix vector tests
Overhaul the riscv vector tests to use kselftest_harness to help the test cases correctly report the results and decouple the individual test cases from each other. With this refactoring, only run the test cases if vector is reported and properly report the test case as skipped otherwise. The v_initval_nolibc test was previously not checking if vector was supported and used a function (malloc) which invalidates the state of the vector registers. Signed-off-by: Charlie Jenkins <[email protected]> Tested-by: Yangyu Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 7fa00fd commit 57d7713

File tree

8 files changed

+337
-193
lines changed

8 files changed

+337
-193
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
vstate_exec_nolibc
22
vstate_prctl
3-
v_initval_nolibc
3+
v_initval
4+
v_exec_initval_nolibc

tools/testing/selftests/riscv/vector/Makefile

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,27 @@
22
# Copyright (C) 2021 ARM Limited
33
# Originally tools/testing/arm64/abi/Makefile
44

5-
TEST_GEN_PROGS := vstate_prctl v_initval_nolibc
6-
TEST_GEN_PROGS_EXTENDED := vstate_exec_nolibc
5+
TEST_GEN_PROGS := v_initval vstate_prctl
6+
TEST_GEN_PROGS_EXTENDED := vstate_exec_nolibc v_exec_initval_nolibc
77

88
include ../../lib.mk
99

10-
$(OUTPUT)/vstate_prctl: vstate_prctl.c ../hwprobe/sys_hwprobe.S
10+
$(OUTPUT)/sys_hwprobe.o: ../hwprobe/sys_hwprobe.S
11+
$(CC) -static -c -o$@ $(CFLAGS) $^
12+
13+
$(OUTPUT)/v_helpers.o: v_helpers.c
14+
$(CC) -static -c -o$@ $(CFLAGS) $^
15+
16+
$(OUTPUT)/vstate_prctl: vstate_prctl.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
1117
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
1218

1319
$(OUTPUT)/vstate_exec_nolibc: vstate_exec_nolibc.c
1420
$(CC) -nostdlib -static -include ../../../../include/nolibc/nolibc.h \
1521
-Wall $(CFLAGS) $(LDFLAGS) $^ -o $@ -lgcc
1622

17-
$(OUTPUT)/v_initval_nolibc: v_initval_nolibc.c
23+
$(OUTPUT)/v_initval: v_initval.c $(OUTPUT)/sys_hwprobe.o $(OUTPUT)/v_helpers.o
24+
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
25+
26+
$(OUTPUT)/v_exec_initval_nolibc: v_exec_initval_nolibc.c
1827
$(CC) -nostdlib -static -include ../../../../include/nolibc/nolibc.h \
1928
-Wall $(CFLAGS) $(LDFLAGS) $^ -o $@ -lgcc
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Get values of vector registers as soon as the program starts to test if
4+
* is properly cleaning the values before starting a new program. Vector
5+
* registers are caller saved, so no function calls may happen before reading
6+
* the values. To further ensure consistency, this file is compiled without
7+
* libc and without auto-vectorization.
8+
*
9+
* To be "clean" all values must be either all ones or all zeroes.
10+
*/
11+
12+
#define __stringify_1(x...) #x
13+
#define __stringify(x...) __stringify_1(x)
14+
15+
int main(int argc, char **argv)
16+
{
17+
char prev_value = 0, value;
18+
unsigned long vl;
19+
int first = 1;
20+
21+
asm volatile (
22+
".option push\n\t"
23+
".option arch, +v\n\t"
24+
"vsetvli %[vl], x0, e8, m1, ta, ma\n\t"
25+
".option pop\n\t"
26+
: [vl] "=r" (vl)
27+
);
28+
29+
#define CHECK_VECTOR_REGISTER(register) ({ \
30+
for (int i = 0; i < vl; i++) { \
31+
asm volatile ( \
32+
".option push\n\t" \
33+
".option arch, +v\n\t" \
34+
"vmv.x.s %0, " __stringify(register) "\n\t" \
35+
"vsrl.vi " __stringify(register) ", " __stringify(register) ", 8\n\t" \
36+
".option pop\n\t" \
37+
: "=r" (value)); \
38+
if (first) { \
39+
first = 0; \
40+
} else if (value != prev_value || !(value == 0x00 || value == 0xff)) { \
41+
printf("Register " __stringify(register) \
42+
" values not clean! value: %u\n", value); \
43+
exit(-1); \
44+
} \
45+
prev_value = value; \
46+
} \
47+
})
48+
49+
CHECK_VECTOR_REGISTER(v0);
50+
CHECK_VECTOR_REGISTER(v1);
51+
CHECK_VECTOR_REGISTER(v2);
52+
CHECK_VECTOR_REGISTER(v3);
53+
CHECK_VECTOR_REGISTER(v4);
54+
CHECK_VECTOR_REGISTER(v5);
55+
CHECK_VECTOR_REGISTER(v6);
56+
CHECK_VECTOR_REGISTER(v7);
57+
CHECK_VECTOR_REGISTER(v8);
58+
CHECK_VECTOR_REGISTER(v9);
59+
CHECK_VECTOR_REGISTER(v10);
60+
CHECK_VECTOR_REGISTER(v11);
61+
CHECK_VECTOR_REGISTER(v12);
62+
CHECK_VECTOR_REGISTER(v13);
63+
CHECK_VECTOR_REGISTER(v14);
64+
CHECK_VECTOR_REGISTER(v15);
65+
CHECK_VECTOR_REGISTER(v16);
66+
CHECK_VECTOR_REGISTER(v17);
67+
CHECK_VECTOR_REGISTER(v18);
68+
CHECK_VECTOR_REGISTER(v19);
69+
CHECK_VECTOR_REGISTER(v20);
70+
CHECK_VECTOR_REGISTER(v21);
71+
CHECK_VECTOR_REGISTER(v22);
72+
CHECK_VECTOR_REGISTER(v23);
73+
CHECK_VECTOR_REGISTER(v24);
74+
CHECK_VECTOR_REGISTER(v25);
75+
CHECK_VECTOR_REGISTER(v26);
76+
CHECK_VECTOR_REGISTER(v27);
77+
CHECK_VECTOR_REGISTER(v28);
78+
CHECK_VECTOR_REGISTER(v29);
79+
CHECK_VECTOR_REGISTER(v30);
80+
CHECK_VECTOR_REGISTER(v31);
81+
82+
#undef CHECK_VECTOR_REGISTER
83+
84+
return 0;
85+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include "../hwprobe/hwprobe.h"
4+
#include <stdbool.h>
5+
#include <stdlib.h>
6+
#include <stdio.h>
7+
#include <unistd.h>
8+
#include <sys/wait.h>
9+
10+
bool is_vector_supported(void)
11+
{
12+
struct riscv_hwprobe pair;
13+
14+
pair.key = RISCV_HWPROBE_KEY_IMA_EXT_0;
15+
riscv_hwprobe(&pair, 1, 0, NULL, 0);
16+
return pair.value & RISCV_HWPROBE_EXT_ZVE32X;
17+
}
18+
19+
int launch_test(char *next_program, int test_inherit)
20+
{
21+
char *exec_argv[3], *exec_envp[1];
22+
int rc, pid, status;
23+
24+
pid = fork();
25+
if (pid < 0) {
26+
printf("fork failed %d", pid);
27+
return -1;
28+
}
29+
30+
if (!pid) {
31+
exec_argv[0] = next_program;
32+
exec_argv[1] = test_inherit != 0 ? "x" : NULL;
33+
exec_argv[2] = NULL;
34+
exec_envp[0] = NULL;
35+
/* launch the program again to check inherit */
36+
rc = execve(next_program, exec_argv, exec_envp);
37+
if (rc) {
38+
perror("execve");
39+
printf("child execve failed %d\n", rc);
40+
exit(-1);
41+
}
42+
}
43+
44+
rc = waitpid(-1, &status, 0);
45+
if (rc < 0) {
46+
printf("waitpid failed\n");
47+
return -3;
48+
}
49+
50+
if ((WIFEXITED(status) && WEXITSTATUS(status) == -1) ||
51+
WIFSIGNALED(status)) {
52+
printf("child exited abnormally\n");
53+
return -4;
54+
}
55+
56+
return WEXITSTATUS(status);
57+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
#include <stdbool.h>
3+
4+
bool is_vector_supported(void);
5+
6+
int launch_test(char *next_program, int test_inherit);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
#include "../../kselftest_harness.h"
4+
#include "v_helpers.h"
5+
6+
#define NEXT_PROGRAM "./v_exec_initval_nolibc"
7+
8+
TEST(v_initval)
9+
{
10+
if (!is_vector_supported())
11+
SKIP(return, "Vector not supported");
12+
13+
ASSERT_EQ(0, launch_test(NEXT_PROGRAM, 0));
14+
}
15+
16+
TEST_HARNESS_MAIN

tools/testing/selftests/riscv/vector/v_initval_nolibc.c

Lines changed: 0 additions & 68 deletions
This file was deleted.

0 commit comments

Comments
 (0)