1 // SPDX-License-Identifier: GPL-2.0-only
7 #include "../hwprobe/hwprobe.h"
8 #include "../../kselftest.h"
10 #define NEXT_PROGRAM "./vstate_exec_nolibc"
11 static int launch_test(int test_inherit
)
13 char *exec_argv
[3], *exec_envp
[1];
18 ksft_test_result_fail("fork failed %d", pid
);
23 exec_argv
[0] = NEXT_PROGRAM
;
24 exec_argv
[1] = test_inherit
!= 0 ? "x" : NULL
;
27 /* launch the program again to check inherit */
28 rc
= execve(NEXT_PROGRAM
, exec_argv
, exec_envp
);
31 ksft_test_result_fail("child execve failed %d\n", rc
);
36 rc
= waitpid(-1, &status
, 0);
38 ksft_test_result_fail("waitpid failed\n");
42 if ((WIFEXITED(status
) && WEXITSTATUS(status
) == -1) ||
43 WIFSIGNALED(status
)) {
44 ksft_test_result_fail("child exited abnormally\n");
48 return WEXITSTATUS(status
);
51 int test_and_compare_child(long provided
, long expected
, int inherit
)
55 rc
= prctl(PR_RISCV_V_SET_CONTROL
, provided
);
57 ksft_test_result_fail("prctl with provided arg %lx failed with code %d\n",
61 rc
= launch_test(inherit
);
63 ksft_test_result_fail("Test failed, check %d != %ld\n", rc
,
70 #define PR_RISCV_V_VSTATE_CTRL_CUR_SHIFT 0
71 #define PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT 2
75 struct riscv_hwprobe pair
;
79 pair
.key
= RISCV_HWPROBE_KEY_IMA_EXT_0
;
80 rc
= riscv_hwprobe(&pair
, 1, 0, NULL
, 0);
82 ksft_test_result_fail("hwprobe() failed with %ld\n", rc
);
86 if (pair
.key
!= RISCV_HWPROBE_KEY_IMA_EXT_0
) {
87 ksft_test_result_fail("hwprobe cannot probe RISCV_HWPROBE_KEY_IMA_EXT_0\n");
91 if (!(pair
.value
& RISCV_HWPROBE_EXT_ZVE32X
)) {
92 rc
= prctl(PR_RISCV_V_GET_CONTROL
);
93 if (rc
!= -1 || errno
!= EINVAL
) {
94 ksft_test_result_fail("GET_CONTROL should fail on kernel/hw without ZVE32X\n");
98 rc
= prctl(PR_RISCV_V_SET_CONTROL
, PR_RISCV_V_VSTATE_CTRL_ON
);
99 if (rc
!= -1 || errno
!= EINVAL
) {
100 ksft_test_result_fail("SET_CONTROL should fail on kernel/hw without ZVE32X\n");
104 ksft_test_result_skip("Vector not supported\n");
108 flag
= PR_RISCV_V_VSTATE_CTRL_ON
;
109 rc
= prctl(PR_RISCV_V_SET_CONTROL
, flag
);
111 ksft_test_result_fail("Enabling V for current should always success\n");
115 flag
= PR_RISCV_V_VSTATE_CTRL_OFF
;
116 rc
= prctl(PR_RISCV_V_SET_CONTROL
, flag
);
117 if (rc
!= -1 || errno
!= EPERM
) {
118 ksft_test_result_fail("Disabling current's V alive must fail with EPERM(%d)\n",
123 /* Turn on next's vector explicitly and test */
124 flag
= PR_RISCV_V_VSTATE_CTRL_ON
<< PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT
;
125 if (test_and_compare_child(flag
, PR_RISCV_V_VSTATE_CTRL_ON
, 0))
128 /* Turn off next's vector explicitly and test */
129 flag
= PR_RISCV_V_VSTATE_CTRL_OFF
<< PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT
;
130 if (test_and_compare_child(flag
, PR_RISCV_V_VSTATE_CTRL_OFF
, 0))
133 /* Turn on next's vector explicitly and test inherit */
134 flag
= PR_RISCV_V_VSTATE_CTRL_ON
<< PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT
;
135 flag
|= PR_RISCV_V_VSTATE_CTRL_INHERIT
;
136 expected
= flag
| PR_RISCV_V_VSTATE_CTRL_ON
;
137 if (test_and_compare_child(flag
, expected
, 0))
140 if (test_and_compare_child(flag
, expected
, 1))
143 /* Turn off next's vector explicitly and test inherit */
144 flag
= PR_RISCV_V_VSTATE_CTRL_OFF
<< PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT
;
145 flag
|= PR_RISCV_V_VSTATE_CTRL_INHERIT
;
146 expected
= flag
| PR_RISCV_V_VSTATE_CTRL_OFF
;
147 if (test_and_compare_child(flag
, expected
, 0))
150 if (test_and_compare_child(flag
, expected
, 1))
153 /* arguments should fail with EINVAL */
154 rc
= prctl(PR_RISCV_V_SET_CONTROL
, 0xff0);
155 if (rc
!= -1 || errno
!= EINVAL
) {
156 ksft_test_result_fail("Undefined control argument should return EINVAL\n");
160 rc
= prctl(PR_RISCV_V_SET_CONTROL
, 0x3);
161 if (rc
!= -1 || errno
!= EINVAL
) {
162 ksft_test_result_fail("Undefined control argument should return EINVAL\n");
166 rc
= prctl(PR_RISCV_V_SET_CONTROL
, 0xc);
167 if (rc
!= -1 || errno
!= EINVAL
) {
168 ksft_test_result_fail("Undefined control argument should return EINVAL\n");
172 rc
= prctl(PR_RISCV_V_SET_CONTROL
, 0xc);
173 if (rc
!= -1 || errno
!= EINVAL
) {
174 ksft_test_result_fail("Undefined control argument should return EINVAL\n");
178 ksft_test_result_pass("tests for riscv_v_vstate_ctrl pass\n");