1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <sys/prctl.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <sys/wait.h>
6 #include <sys/types.h>
7 #include <stdlib.h>
8 
9 #include "../../kselftest_harness.h"
10 #include "v_helpers.h"
11 
12 #define NEXT_PROGRAM "./vstate_exec_nolibc"
13 
test_and_compare_child(long provided,long expected,int inherit,int xtheadvector)14 int test_and_compare_child(long provided, long expected, int inherit, int xtheadvector)
15 {
16 	int rc;
17 
18 	rc = prctl(PR_RISCV_V_SET_CONTROL, provided);
19 	if (rc != 0) {
20 		printf("prctl with provided arg %lx failed with code %d\n",
21 		       provided, rc);
22 		return -1;
23 	}
24 	rc = launch_test(NEXT_PROGRAM, inherit, xtheadvector);
25 	if (rc != expected) {
26 		printf("Test failed, check %d != %ld\n", rc, expected);
27 		return -2;
28 	}
29 	return 0;
30 }
31 
32 #define PR_RISCV_V_VSTATE_CTRL_CUR_SHIFT 0
33 #define PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT 2
34 
TEST(get_control_no_v)35 TEST(get_control_no_v)
36 {
37 	long rc;
38 
39 	if (is_vector_supported() || is_xtheadvector_supported())
40 		SKIP(return, "Test expects vector to be not supported");
41 
42 	rc = prctl(PR_RISCV_V_GET_CONTROL);
43 	EXPECT_EQ(-1, rc)
44 	TH_LOG("GET_CONTROL should fail on kernel/hw without ZVE32X");
45 	EXPECT_EQ(EINVAL, errno)
46 	TH_LOG("GET_CONTROL should fail on kernel/hw without ZVE32X");
47 }
48 
TEST(set_control_no_v)49 TEST(set_control_no_v)
50 {
51 	long rc;
52 
53 	if (is_vector_supported() || is_xtheadvector_supported())
54 		SKIP(return, "Test expects vector to be not supported");
55 
56 	rc = prctl(PR_RISCV_V_SET_CONTROL, PR_RISCV_V_VSTATE_CTRL_ON);
57 	EXPECT_EQ(-1, rc)
58 	TH_LOG("SET_CONTROL should fail on kernel/hw without ZVE32X");
59 	EXPECT_EQ(EINVAL, errno)
60 	TH_LOG("SET_CONTROL should fail on kernel/hw without ZVE32X");
61 }
62 
TEST(vstate_on_current)63 TEST(vstate_on_current)
64 {
65 	long flag;
66 	long rc;
67 
68 	if (!is_vector_supported() && !is_xtheadvector_supported())
69 		SKIP(return, "Vector not supported");
70 
71 	flag = PR_RISCV_V_VSTATE_CTRL_ON;
72 	rc = prctl(PR_RISCV_V_SET_CONTROL, flag);
73 	EXPECT_EQ(0, rc) TH_LOG("Enabling V for current should always succeed");
74 }
75 
TEST(vstate_off_eperm)76 TEST(vstate_off_eperm)
77 {
78 	long flag;
79 	long rc;
80 
81 	if (!is_vector_supported() && !is_xtheadvector_supported())
82 		SKIP(return, "Vector not supported");
83 
84 	flag = PR_RISCV_V_VSTATE_CTRL_OFF;
85 	rc = prctl(PR_RISCV_V_SET_CONTROL, flag);
86 	EXPECT_EQ(EPERM, errno)
87 	TH_LOG("Disabling V in current thread with V enabled must fail with EPERM(%d)", errno);
88 	EXPECT_EQ(-1, rc)
89 	TH_LOG("Disabling V in current thread with V enabled must fail with EPERM(%d)", errno);
90 }
91 
TEST(vstate_on_no_nesting)92 TEST(vstate_on_no_nesting)
93 {
94 	long flag;
95 	int xtheadvector = 0;
96 
97 	if (!is_vector_supported()) {
98 		if (is_xtheadvector_supported())
99 			xtheadvector = 1;
100 		else
101 			SKIP(return, "Vector not supported");
102 	}
103 
104 	/* Turn on next's vector explicitly and test */
105 	flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
106 
107 	EXPECT_EQ(0, test_and_compare_child(flag, PR_RISCV_V_VSTATE_CTRL_ON, 0, xtheadvector));
108 }
109 
TEST(vstate_off_nesting)110 TEST(vstate_off_nesting)
111 {
112 	long flag;
113 	int xtheadvector = 0;
114 
115 	if (!is_vector_supported()) {
116 		if (is_xtheadvector_supported())
117 			xtheadvector = 1;
118 		else
119 			SKIP(return, "Vector not supported");
120 	}
121 
122 	/* Turn off next's vector explicitly and test */
123 	flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
124 
125 	EXPECT_EQ(0, test_and_compare_child(flag, PR_RISCV_V_VSTATE_CTRL_OFF, 1, xtheadvector));
126 }
127 
TEST(vstate_on_inherit_no_nesting)128 TEST(vstate_on_inherit_no_nesting)
129 {
130 	long flag, expected;
131 	int xtheadvector = 0;
132 
133 	if (!is_vector_supported()) {
134 		if (is_xtheadvector_supported())
135 			xtheadvector = 1;
136 		else
137 			SKIP(return, "Vector not supported");
138 	}
139 
140 	/* Turn on next's vector explicitly and test no inherit */
141 	flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
142 	flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
143 	expected = flag | PR_RISCV_V_VSTATE_CTRL_ON;
144 
145 	EXPECT_EQ(0, test_and_compare_child(flag, expected, 0, xtheadvector));
146 }
147 
TEST(vstate_on_inherit)148 TEST(vstate_on_inherit)
149 {
150 	long flag, expected;
151 	int xtheadvector = 0;
152 
153 	if (!is_vector_supported()) {
154 		if (is_xtheadvector_supported())
155 			xtheadvector = 1;
156 		else
157 			SKIP(return, "Vector not supported");
158 	}
159 
160 	/* Turn on next's vector explicitly and test inherit */
161 	flag = PR_RISCV_V_VSTATE_CTRL_ON << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
162 	flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
163 	expected = flag | PR_RISCV_V_VSTATE_CTRL_ON;
164 
165 	EXPECT_EQ(0, test_and_compare_child(flag, expected, 1, xtheadvector));
166 }
167 
TEST(vstate_off_inherit_no_nesting)168 TEST(vstate_off_inherit_no_nesting)
169 {
170 	long flag, expected;
171 	int xtheadvector = 0;
172 
173 	if (!is_vector_supported()) {
174 		if (is_xtheadvector_supported())
175 			xtheadvector = 1;
176 		else
177 			SKIP(return, "Vector not supported");
178 	}
179 	/* Turn off next's vector explicitly and test no inherit */
180 	flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
181 	flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
182 	expected = flag | PR_RISCV_V_VSTATE_CTRL_OFF;
183 
184 	EXPECT_EQ(0, test_and_compare_child(flag, expected, 0, xtheadvector));
185 }
186 
TEST(vstate_off_inherit)187 TEST(vstate_off_inherit)
188 {
189 	long flag, expected;
190 	int xtheadvector = 0;
191 
192 	if (!is_vector_supported()) {
193 		if (is_xtheadvector_supported())
194 			xtheadvector = 1;
195 		else
196 			SKIP(return, "Vector not supported");
197 	}
198 
199 	/* Turn off next's vector explicitly and test inherit */
200 	flag = PR_RISCV_V_VSTATE_CTRL_OFF << PR_RISCV_V_VSTATE_CTRL_NEXT_SHIFT;
201 	flag |= PR_RISCV_V_VSTATE_CTRL_INHERIT;
202 	expected = flag | PR_RISCV_V_VSTATE_CTRL_OFF;
203 
204 	EXPECT_EQ(0, test_and_compare_child(flag, expected, 1, xtheadvector));
205 }
206 
207 /* arguments should fail with EINVAL */
TEST(inval_set_control_1)208 TEST(inval_set_control_1)
209 {
210 	int rc;
211 
212 	if (!is_vector_supported() && !is_xtheadvector_supported())
213 		SKIP(return, "Vector not supported");
214 
215 	rc = prctl(PR_RISCV_V_SET_CONTROL, 0xff0);
216 	EXPECT_EQ(-1, rc);
217 	EXPECT_EQ(EINVAL, errno);
218 }
219 
220 /* arguments should fail with EINVAL */
TEST(inval_set_control_2)221 TEST(inval_set_control_2)
222 {
223 	int rc;
224 
225 	if (!is_vector_supported() && !is_xtheadvector_supported())
226 		SKIP(return, "Vector not supported");
227 
228 	rc = prctl(PR_RISCV_V_SET_CONTROL, 0x3);
229 	EXPECT_EQ(-1, rc);
230 	EXPECT_EQ(EINVAL, errno);
231 }
232 
233 /* arguments should fail with EINVAL */
TEST(inval_set_control_3)234 TEST(inval_set_control_3)
235 {
236 	int rc;
237 
238 	if (!is_vector_supported() && !is_xtheadvector_supported())
239 		SKIP(return, "Vector not supported");
240 
241 	rc = prctl(PR_RISCV_V_SET_CONTROL, 0xc);
242 	EXPECT_EQ(-1, rc);
243 	EXPECT_EQ(EINVAL, errno);
244 }
245 
246 TEST_HARNESS_MAIN
247