xref: /linux/tools/testing/selftests/riscv/vector/validate_v_ptrace.c (revision 26ba30221c03364d6ed9910be8da4c1fd871b07b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <sys/ptrace.h>
3 #include <sys/syscall.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <sys/uio.h>
7 #include <unistd.h>
8 #include <errno.h>
9 
10 #include <linux/ptrace.h>
11 #include <linux/elf.h>
12 
13 #include "kselftest_harness.h"
14 #include "v_helpers.h"
15 
16 #define SR_FS_DIRTY	0x00006000UL
17 #define CSR_VXRM_SHIFT	1
18 
19 volatile unsigned long chld_lock;
20 
21 TEST(ptrace_v_not_enabled)
22 {
23 	pid_t pid;
24 
25 	if (!(is_vector_supported() || is_xtheadvector_supported()))
26 		SKIP(return, "Vector not supported");
27 
28 	chld_lock = 1;
29 	pid = (pid_t)syscall(SYS_clone, SIGCHLD, 0, NULL, 0, NULL);
30 	ASSERT_LE(0, pid)
31 		TH_LOG("clone: %m");
32 
33 	if (pid == 0) {
34 		while (chld_lock == 1)
35 			asm volatile("" : : "g"(chld_lock) : "memory");
36 
37 		asm volatile ("ebreak" : : : );
38 	} else {
39 		struct __riscv_v_regset_state *regset_data;
40 		unsigned long vlenb = get_vr_len();
41 		size_t regset_size;
42 		struct iovec iov;
43 		int status;
44 		int ret;
45 
46 		/* attach */
47 
48 		ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL));
49 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
50 		ASSERT_TRUE(WIFSTOPPED(status));
51 
52 		/* unlock */
53 
54 		ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0));
55 
56 		/* resume and wait for ebreak */
57 
58 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
59 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
60 		ASSERT_TRUE(WIFSTOPPED(status));
61 
62 		/* try to read vector registers from the tracee */
63 
64 		regset_size = sizeof(*regset_data) + vlenb * 32;
65 		regset_data = calloc(1, regset_size);
66 
67 		iov.iov_base = regset_data;
68 		iov.iov_len = regset_size;
69 
70 		/* V extension is available, but not yet enabled for the tracee */
71 
72 		errno = 0;
73 		ret = ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov);
74 		ASSERT_EQ(ENODATA, errno);
75 		ASSERT_EQ(-1, ret);
76 
77 		/* cleanup */
78 		free(regset_data);
79 		ASSERT_EQ(0, kill(pid, SIGKILL));
80 	}
81 }
82 
83 TEST(ptrace_v_early_debug)
84 {
85 	static volatile unsigned long vstart;
86 	static volatile unsigned long vtype;
87 	static volatile unsigned long vlenb;
88 	static volatile unsigned long vcsr;
89 	static volatile unsigned long vl;
90 	bool xtheadvector;
91 	pid_t pid;
92 
93 	if (!(is_vector_supported() || is_xtheadvector_supported()))
94 		SKIP(return, "Vector not supported");
95 
96 	xtheadvector = is_xtheadvector_supported();
97 
98 	chld_lock = 1;
99 	pid = fork();
100 	ASSERT_LE(0, pid)
101 		TH_LOG("fork: %m");
102 
103 	if (pid == 0) {
104 		unsigned long vxsat, vxrm;
105 
106 		vlenb = get_vr_len();
107 
108 		while (chld_lock == 1)
109 			asm volatile ("" : : "g"(chld_lock) : "memory");
110 
111 		asm volatile (
112 			"csrr %[vstart], vstart\n"
113 			"csrr %[vtype], vtype\n"
114 			"csrr %[vl], vl\n"
115 			: [vtype] "=r"(vtype), [vstart] "=r"(vstart), [vl] "=r"(vl)
116 			:
117 			: "memory");
118 
119 		/* no 'is_xtheadvector_supported()' here to avoid clobbering v-state by syscall */
120 		if (xtheadvector) {
121 			asm volatile (
122 				"csrs sstatus, %[bit]\n"
123 				"csrr %[vxsat], vxsat\n"
124 				"csrr %[vxrm], vxrm\n"
125 				: [vxsat] "=r"(vxsat), [vxrm] "=r"(vxrm)
126 				: [bit] "r" (SR_FS_DIRTY)
127 				: "memory");
128 			vcsr = vxsat | vxrm << CSR_VXRM_SHIFT;
129 		} else {
130 			asm volatile (
131 				"csrr %[vcsr], vcsr\n"
132 				: [vcsr] "=r"(vcsr)
133 				:
134 				: "memory");
135 		}
136 
137 		asm volatile (
138 			".option push\n"
139 			".option norvc\n"
140 			"ebreak\n"
141 			".option pop\n");
142 	} else {
143 		struct __riscv_v_regset_state *regset_data;
144 		unsigned long vstart_csr;
145 		unsigned long vlenb_csr;
146 		unsigned long vtype_csr;
147 		unsigned long vcsr_csr;
148 		unsigned long vl_csr;
149 		size_t regset_size;
150 		struct iovec iov;
151 		int status;
152 
153 		/* attach */
154 
155 		ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL));
156 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
157 		ASSERT_TRUE(WIFSTOPPED(status));
158 
159 		/* unlock */
160 
161 		ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0));
162 
163 		/* resume and wait for ebreak */
164 
165 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
166 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
167 		ASSERT_TRUE(WIFSTOPPED(status));
168 
169 		/* read tracee vector csr regs using ptrace PEEKDATA */
170 
171 		errno = 0;
172 		vstart_csr = ptrace(PTRACE_PEEKDATA, pid, &vstart, NULL);
173 		ASSERT_FALSE((errno != 0) && (vstart_csr == -1));
174 
175 		errno = 0;
176 		vl_csr = ptrace(PTRACE_PEEKDATA, pid, &vl, NULL);
177 		ASSERT_FALSE((errno != 0) && (vl_csr == -1));
178 
179 		errno = 0;
180 		vtype_csr = ptrace(PTRACE_PEEKDATA, pid, &vtype, NULL);
181 		ASSERT_FALSE((errno != 0) && (vtype_csr == -1));
182 
183 		errno = 0;
184 		vcsr_csr = ptrace(PTRACE_PEEKDATA, pid, &vcsr, NULL);
185 		ASSERT_FALSE((errno != 0) && (vcsr_csr == -1));
186 
187 		errno = 0;
188 		vlenb_csr = ptrace(PTRACE_PEEKDATA, pid, &vlenb, NULL);
189 		ASSERT_FALSE((errno != 0) && (vlenb_csr == -1));
190 
191 		/* read tracee csr regs using ptrace GETREGSET */
192 
193 		regset_size = sizeof(*regset_data) + vlenb_csr * 32;
194 		regset_data = calloc(1, regset_size);
195 
196 		iov.iov_base = regset_data;
197 		iov.iov_len = regset_size;
198 
199 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
200 
201 		/* compare */
202 
203 		EXPECT_EQ(vstart_csr, regset_data->vstart);
204 		EXPECT_EQ(vtype_csr, regset_data->vtype);
205 		EXPECT_EQ(vlenb_csr, regset_data->vlenb);
206 		EXPECT_EQ(vcsr_csr, regset_data->vcsr);
207 		EXPECT_EQ(vl_csr, regset_data->vl);
208 
209 		/* cleanup */
210 		free(regset_data);
211 		ASSERT_EQ(0, kill(pid, SIGKILL));
212 	}
213 }
214 
215 TEST(ptrace_v_syscall_clobbering)
216 {
217 	pid_t pid;
218 
219 	if (!is_vector_supported() && !is_xtheadvector_supported())
220 		SKIP(return, "Vector not supported");
221 
222 	chld_lock = 1;
223 	pid = fork();
224 	ASSERT_LE(0, pid)
225 		TH_LOG("fork: %m");
226 
227 	if (pid == 0) {
228 		unsigned long vl;
229 
230 		while (chld_lock == 1)
231 			asm volatile("" : : "g"(chld_lock) : "memory");
232 
233 		if (is_xtheadvector_supported()) {
234 			asm volatile (
235 				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
236 				// vsetvli	t4, x0, e16, m2, d1
237 				".4byte		0b00000000010100000111111011010111\n"
238 				"mv		%[new_vl], t4\n"
239 				: [new_vl] "=r" (vl) : : "t4");
240 		} else {
241 			asm volatile (
242 				".option push\n"
243 				".option arch, +zve32x\n"
244 				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
245 				".option pop\n"
246 				: [new_vl] "=r"(vl) : : );
247 		}
248 
249 		while (1) {
250 			asm volatile (
251 				".option push\n"
252 				".option norvc\n"
253 				"ebreak\n"
254 				".option pop\n");
255 
256 			sleep(0);
257 		}
258 	} else {
259 		struct __riscv_v_regset_state *regset_data;
260 		unsigned long vlenb = get_vr_len();
261 		struct user_regs_struct regs;
262 		size_t regset_size;
263 		struct iovec iov;
264 		int status;
265 
266 		/* attach */
267 
268 		ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL));
269 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
270 		ASSERT_TRUE(WIFSTOPPED(status));
271 
272 		/* unlock */
273 
274 		ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0));
275 
276 		/* resume and wait for the 1st ebreak */
277 
278 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
279 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
280 		ASSERT_TRUE(WIFSTOPPED(status));
281 
282 		/* read tracee vector csr regs using ptrace GETREGSET */
283 
284 		regset_size = sizeof(*regset_data) + vlenb * 32;
285 		regset_data = calloc(1, regset_size);
286 
287 		iov.iov_base = regset_data;
288 		iov.iov_len = regset_size;
289 
290 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
291 
292 		/* verify initial vsetvli settings */
293 
294 		if (is_xtheadvector_supported()) {
295 			EXPECT_EQ(5UL, regset_data->vtype);
296 		} else {
297 			EXPECT_EQ(9UL, regset_data->vtype);
298 		}
299 
300 		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
301 		EXPECT_EQ(vlenb, regset_data->vlenb);
302 		EXPECT_EQ(0UL, regset_data->vstart);
303 		EXPECT_EQ(0UL, regset_data->vcsr);
304 
305 		/* skip 1st ebreak, then resume and wait for the 2nd ebreak */
306 
307 		iov.iov_base = &regs;
308 		iov.iov_len = sizeof(regs);
309 
310 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
311 		regs.pc += 4;
312 		ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov));
313 
314 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
315 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
316 		ASSERT_TRUE(WIFSTOPPED(status));
317 
318 		/* read tracee vtype using ptrace GETREGSET */
319 
320 		iov.iov_base = regset_data;
321 		iov.iov_len = regset_size;
322 
323 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
324 
325 		/* verify that V state is illegal after syscall */
326 
327 		EXPECT_EQ((1UL << (__riscv_xlen - 1)), regset_data->vtype);
328 		EXPECT_EQ(vlenb, regset_data->vlenb);
329 		EXPECT_EQ(0UL, regset_data->vstart);
330 		EXPECT_EQ(0UL, regset_data->vcsr);
331 		EXPECT_EQ(0UL, regset_data->vl);
332 
333 		/* cleanup */
334 		free(regset_data);
335 		ASSERT_EQ(0, kill(pid, SIGKILL));
336 	}
337 }
338 
339 FIXTURE(v_csr_invalid)
340 {
341 };
342 
343 FIXTURE_SETUP(v_csr_invalid)
344 {
345 }
346 
347 FIXTURE_TEARDOWN(v_csr_invalid)
348 {
349 }
350 
351 #define VECTOR_1_0		_BITUL(0)
352 #define XTHEAD_VECTOR_0_7	_BITUL(1)
353 
354 #define vector_test(x)		((x) & VECTOR_1_0)
355 #define xthead_test(x)		((x) & XTHEAD_VECTOR_0_7)
356 
357 /* modifications of the initial vsetvli settings */
358 FIXTURE_VARIANT(v_csr_invalid)
359 {
360 	unsigned long vstart;
361 	unsigned long vl;
362 	unsigned long vtype;
363 	unsigned long vcsr;
364 	unsigned long vlenb_mul;
365 	unsigned long vlenb_min;
366 	unsigned long vlenb_max;
367 	unsigned long spec;
368 };
369 
370 /* unexpected vlenb value */
371 FIXTURE_VARIANT_ADD(v_csr_invalid, new_vlenb)
372 {
373 	.vstart = 0x0,
374 	.vl = 0x0,
375 	.vtype = 0x3,
376 	.vcsr = 0x0,
377 	.vlenb_mul = 0x2,
378 	.vlenb_min = 0x0,
379 	.vlenb_max = 0x0,
380 	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
381 };
382 
383 /* invalid reserved bits in vcsr */
384 FIXTURE_VARIANT_ADD(v_csr_invalid, vcsr_invalid_reserved_bits)
385 {
386 	.vstart = 0x0,
387 	.vl = 0x0,
388 	.vtype = 0x3,
389 	.vcsr = 0x1UL << 8,
390 	.vlenb_mul = 0x1,
391 	.vlenb_min = 0x0,
392 	.vlenb_max = 0x0,
393 	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
394 };
395 
396 /* invalid reserved bits in vtype */
397 FIXTURE_VARIANT_ADD(v_csr_invalid, vtype_invalid_reserved_bits)
398 {
399 	.vstart = 0x0,
400 	.vl = 0x0,
401 	.vtype = (0x1UL << 8) | 0x3,
402 	.vcsr = 0x0,
403 	.vlenb_mul = 0x1,
404 	.vlenb_min = 0x0,
405 	.vlenb_max = 0x0,
406 	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
407 };
408 
409 /* set vill bit */
410 FIXTURE_VARIANT_ADD(v_csr_invalid, invalid_vill_bit)
411 {
412 	.vstart = 0x0,
413 	.vl = 0x0,
414 	.vtype = (0x1UL << (__riscv_xlen - 1)) | 0x3,
415 	.vcsr = 0x0,
416 	.vlenb_mul = 0x1,
417 	.vlenb_min = 0x0,
418 	.vlenb_max = 0x0,
419 	.spec = VECTOR_1_0 | XTHEAD_VECTOR_0_7,
420 };
421 
422 /* reserved vsew value: vsew > 3 */
423 FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vsew)
424 {
425 	.vstart = 0x0,
426 	.vl = 0x0,
427 	.vtype = 0x4UL << 3,
428 	.vcsr = 0x0,
429 	.vlenb_mul = 0x1,
430 	.vlenb_min = 0x0,
431 	.vlenb_max = 0x0,
432 	.spec = VECTOR_1_0,
433 };
434 
435 /* XTheadVector: unsupported non-zero VEDIV value */
436 FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vediv)
437 {
438 	.vstart = 0x0,
439 	.vl = 0x0,
440 	.vtype = 0x3UL << 5,
441 	.vcsr = 0x0,
442 	.vlenb_mul = 0x1,
443 	.vlenb_min = 0x0,
444 	.vlenb_max = 0x0,
445 	.spec = XTHEAD_VECTOR_0_7,
446 };
447 
448 /* reserved vlmul value: vlmul == 4 */
449 FIXTURE_VARIANT_ADD(v_csr_invalid, reserved_vlmul)
450 {
451 	.vstart = 0x0,
452 	.vl = 0x0,
453 	.vtype = 0x4,
454 	.vcsr = 0x0,
455 	.vlenb_mul = 0x1,
456 	.vlenb_min = 0x0,
457 	.vlenb_max = 0x0,
458 	.spec = VECTOR_1_0,
459 };
460 
461 /* invalid fractional LMUL for VLEN <= 256: LMUL= 1/8, SEW = 64 */
462 FIXTURE_VARIANT_ADD(v_csr_invalid, frac_lmul1)
463 {
464 	.vstart = 0x0,
465 	.vl = 0x0,
466 	.vtype = 0x1d,
467 	.vcsr = 0x0,
468 	.vlenb_mul = 0x1,
469 	.vlenb_min = 0x0,
470 	.vlenb_max = 0x20,
471 	.spec = VECTOR_1_0,
472 };
473 
474 /* invalid integral LMUL for VLEN <= 16: LMUL= 2, SEW = 64 */
475 FIXTURE_VARIANT_ADD(v_csr_invalid, int_lmul1)
476 {
477 	.vstart = 0x0,
478 	.vl = 0x0,
479 	.vtype = 0x19,
480 	.vcsr = 0x0,
481 	.vlenb_mul = 0x1,
482 	.vlenb_min = 0x0,
483 	.vlenb_max = 0x2,
484 	.spec = VECTOR_1_0,
485 };
486 
487 /* XTheadVector: invalid integral LMUL for VLEN <= 16: LMUL= 2, SEW = 64 */
488 FIXTURE_VARIANT_ADD(v_csr_invalid, int_lmul2)
489 {
490 	.vstart = 0x0,
491 	.vl = 0x0,
492 	.vtype = 0xd,
493 	.vcsr = 0x0,
494 	.vlenb_mul = 0x1,
495 	.vlenb_min = 0x0,
496 	.vlenb_max = 0x2,
497 	.spec = XTHEAD_VECTOR_0_7,
498 };
499 
500 /* invalid VL for VLEN <= 128: LMUL= 2, SEW = 64, VL = 8 */
501 FIXTURE_VARIANT_ADD(v_csr_invalid, vl1)
502 {
503 	.vstart = 0x0,
504 	.vl = 0x8,
505 	.vtype = 0x19,
506 	.vcsr = 0x0,
507 	.vlenb_mul = 0x1,
508 	.vlenb_min = 0x0,
509 	.vlenb_max = 0x10,
510 	.spec = VECTOR_1_0,
511 };
512 
513 /* XTheadVector: invalid VL for VLEN <= 128: LMUL= 2, SEW = 64, VL = 8 */
514 FIXTURE_VARIANT_ADD(v_csr_invalid, vl2)
515 {
516 	.vstart = 0x0,
517 	.vl = 0x8,
518 	.vtype = 0xd,
519 	.vcsr = 0x0,
520 	.vlenb_mul = 0x1,
521 	.vlenb_min = 0x0,
522 	.vlenb_max = 0x10,
523 	.spec = XTHEAD_VECTOR_0_7,
524 };
525 
526 TEST_F(v_csr_invalid, ptrace_v_invalid_values)
527 {
528 	unsigned long vlenb;
529 	pid_t pid;
530 
531 	if (!is_vector_supported() && !is_xtheadvector_supported())
532 		SKIP(return, "Vectors not supported");
533 
534 	if (is_vector_supported() && !vector_test(variant->spec))
535 		SKIP(return, "Test not supported for Vector");
536 
537 	if (is_xtheadvector_supported() && !xthead_test(variant->spec))
538 		SKIP(return, "Test not supported for XTheadVector");
539 
540 	vlenb = get_vr_len();
541 
542 	if (variant->vlenb_min) {
543 		if (vlenb < variant->vlenb_min)
544 			SKIP(return, "This test does not support VLEN < %lu\n",
545 			     variant->vlenb_min * 8);
546 	}
547 
548 	if (variant->vlenb_max) {
549 		if (vlenb > variant->vlenb_max)
550 			SKIP(return, "This test does not support VLEN > %lu\n",
551 			     variant->vlenb_max * 8);
552 	}
553 
554 	chld_lock = 1;
555 	pid = fork();
556 	ASSERT_LE(0, pid)
557 		TH_LOG("fork: %m");
558 
559 	if (pid == 0) {
560 		unsigned long vl;
561 
562 		while (chld_lock == 1)
563 			asm volatile("" : : "g"(chld_lock) : "memory");
564 
565 		if (is_xtheadvector_supported()) {
566 			asm volatile (
567 				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
568 				// vsetvli	t4, x0, e16, m2, d1
569 				".4byte		0b00000000010100000111111011010111\n"
570 				"mv		%[new_vl], t4\n"
571 				: [new_vl] "=r" (vl) : : "t4");
572 		} else {
573 			asm volatile (
574 				".option push\n"
575 				".option arch, +zve32x\n"
576 				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
577 				".option pop\n"
578 				: [new_vl] "=r"(vl) : : );
579 		}
580 
581 		while (1) {
582 			asm volatile (
583 				".option push\n"
584 				".option norvc\n"
585 				"ebreak\n"
586 				"nop\n"
587 				".option pop\n");
588 		}
589 	} else {
590 		struct __riscv_v_regset_state *regset_data;
591 		size_t regset_size;
592 		struct iovec iov;
593 		int status;
594 		int ret;
595 
596 		/* attach */
597 
598 		ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL));
599 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
600 		ASSERT_TRUE(WIFSTOPPED(status));
601 
602 		/* unlock */
603 
604 		ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0));
605 
606 		/* resume and wait for the 1st ebreak */
607 
608 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
609 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
610 		ASSERT_TRUE(WIFSTOPPED(status));
611 
612 		/* read tracee vector csr regs using ptrace GETREGSET */
613 
614 		regset_size = sizeof(*regset_data) + vlenb * 32;
615 		regset_data = calloc(1, regset_size);
616 
617 		iov.iov_base = regset_data;
618 		iov.iov_len = regset_size;
619 
620 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
621 
622 		/* verify initial vsetvli settings */
623 
624 		if (is_xtheadvector_supported()) {
625 			EXPECT_EQ(5UL, regset_data->vtype);
626 		} else {
627 			EXPECT_EQ(9UL, regset_data->vtype);
628 		}
629 
630 		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
631 		EXPECT_EQ(vlenb, regset_data->vlenb);
632 		EXPECT_EQ(0UL, regset_data->vstart);
633 		EXPECT_EQ(0UL, regset_data->vcsr);
634 
635 		/* apply invalid settings from fixture variants */
636 
637 		regset_data->vlenb *= variant->vlenb_mul;
638 		regset_data->vstart = variant->vstart;
639 		regset_data->vtype = variant->vtype;
640 		regset_data->vcsr = variant->vcsr;
641 		regset_data->vl = variant->vl;
642 
643 		iov.iov_base = regset_data;
644 		iov.iov_len = regset_size;
645 
646 		errno = 0;
647 		ret = ptrace(PTRACE_SETREGSET, pid, NT_RISCV_VECTOR, &iov);
648 		ASSERT_EQ(errno, EINVAL);
649 		ASSERT_EQ(ret, -1);
650 
651 		/* cleanup */
652 		free(regset_data);
653 		ASSERT_EQ(0, kill(pid, SIGKILL));
654 	}
655 }
656 
657 FIXTURE(v_csr_valid)
658 {
659 };
660 
661 FIXTURE_SETUP(v_csr_valid)
662 {
663 }
664 
665 FIXTURE_TEARDOWN(v_csr_valid)
666 {
667 }
668 
669 /* modifications of the initial vsetvli settings */
670 FIXTURE_VARIANT(v_csr_valid)
671 {
672 	unsigned long vstart;
673 	unsigned long vl;
674 	unsigned long vtype;
675 	unsigned long vcsr;
676 	unsigned long vlenb_mul;
677 	unsigned long vlenb_min;
678 	unsigned long vlenb_max;
679 	unsigned long spec;
680 };
681 
682 /* valid for VLEN >= 128: LMUL= 1/4, SEW = 32 */
683 FIXTURE_VARIANT_ADD(v_csr_valid, frac_lmul1)
684 {
685 	.vstart = 0x0,
686 	.vl = 0x0,
687 	.vtype = 0x16,
688 	.vcsr = 0x0,
689 	.vlenb_mul = 0x1,
690 	.vlenb_min = 0x10,
691 	.vlenb_max = 0x0,
692 	.spec = VECTOR_1_0,
693 };
694 
695 /* valid for VLEN >= 16: LMUL= 2, SEW = 32 */
696 FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul1)
697 {
698 	.vstart = 0x0,
699 	.vl = 0x0,
700 	.vtype = 0x11,
701 	.vcsr = 0x0,
702 	.vlenb_mul = 0x1,
703 	.vlenb_min = 0x2,
704 	.vlenb_max = 0x0,
705 	.spec = VECTOR_1_0,
706 };
707 
708 /* valid for XTheadVector VLEN >= 16: LMUL= 2, SEW = 32 */
709 FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul2)
710 {
711 	.vstart = 0x0,
712 	.vl = 0x0,
713 	.vtype = 0x9,
714 	.vcsr = 0x0,
715 	.vlenb_mul = 0x1,
716 	.vlenb_min = 0x2,
717 	.vlenb_max = 0x0,
718 	.spec = XTHEAD_VECTOR_0_7,
719 };
720 
721 /* valid for VLEN >= 32: LMUL= 2, SEW = 32, VL = 2 */
722 FIXTURE_VARIANT_ADD(v_csr_valid, int_lmul3)
723 {
724 	.vstart = 0x0,
725 	.vl = 0x2,
726 	.vtype = 0x11,
727 	.vcsr = 0x0,
728 	.vlenb_mul = 0x1,
729 	.vlenb_min = 0x4,
730 	.vlenb_max = 0x0,
731 	.spec = VECTOR_1_0,
732 };
733 
734 TEST_F(v_csr_valid, ptrace_v_valid_values)
735 {
736 	unsigned long vlenb;
737 	pid_t pid;
738 
739 	if (!is_vector_supported() && !is_xtheadvector_supported())
740 		SKIP(return, "Vectors not supported");
741 
742 	if (is_vector_supported() && !vector_test(variant->spec))
743 		SKIP(return, "Test not supported for Vector");
744 
745 	if (is_xtheadvector_supported() && !xthead_test(variant->spec))
746 		SKIP(return, "Test not supported for XTheadVector");
747 
748 	vlenb = get_vr_len();
749 
750 	if (variant->vlenb_min) {
751 		if (vlenb < variant->vlenb_min)
752 			SKIP(return, "This test does not support VLEN < %lu\n",
753 			     variant->vlenb_min * 8);
754 	}
755 	if (variant->vlenb_max) {
756 		if (vlenb > variant->vlenb_max)
757 			SKIP(return, "This test does not support VLEN > %lu\n",
758 			     variant->vlenb_max * 8);
759 	}
760 
761 	chld_lock = 1;
762 	pid = fork();
763 	ASSERT_LE(0, pid)
764 		TH_LOG("fork: %m");
765 
766 	if (pid == 0) {
767 		unsigned long vl;
768 
769 		while (chld_lock == 1)
770 			asm volatile("" : : "g"(chld_lock) : "memory");
771 
772 		if (is_xtheadvector_supported()) {
773 			asm volatile (
774 				// 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
775 				// vsetvli	t4, x0, e16, m2, d1
776 				".4byte		0b00000000010100000111111011010111\n"
777 				"mv		%[new_vl], t4\n"
778 				: [new_vl] "=r" (vl) : : "t4");
779 		} else {
780 			asm volatile (
781 				".option push\n"
782 				".option arch, +zve32x\n"
783 				"vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
784 				".option pop\n"
785 				: [new_vl] "=r"(vl) : : );
786 		}
787 
788 		asm volatile (
789 			".option push\n"
790 			".option norvc\n"
791 			".option arch, +zve32x\n"
792 			"ebreak\n" /* breakpoint 1: apply new V state using ptrace */
793 			"nop\n"
794 			"ebreak\n" /* breakpoint 2: V state clean - context will not be saved */
795 			"vmv.v.i v0, -1\n"
796 			"ebreak\n" /* breakpoint 3: V state dirty - context will be saved */
797 			".option pop\n");
798 	} else {
799 		struct __riscv_v_regset_state *regset_data;
800 		struct user_regs_struct regs;
801 		size_t regset_size;
802 		struct iovec iov;
803 		int status;
804 
805 		/* attach */
806 
807 		ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, NULL, NULL));
808 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
809 		ASSERT_TRUE(WIFSTOPPED(status));
810 
811 		/* unlock */
812 
813 		ASSERT_EQ(0, ptrace(PTRACE_POKEDATA, pid, &chld_lock, 0));
814 
815 		/* resume and wait for the 1st ebreak */
816 
817 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
818 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
819 		ASSERT_TRUE(WIFSTOPPED(status));
820 
821 		/* read tracee vector csr regs using ptrace GETREGSET */
822 
823 		regset_size = sizeof(*regset_data) + vlenb * 32;
824 		regset_data = calloc(1, regset_size);
825 
826 		iov.iov_base = regset_data;
827 		iov.iov_len = regset_size;
828 
829 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
830 
831 		/* verify initial vsetvli settings */
832 
833 		if (is_xtheadvector_supported()) {
834 			EXPECT_EQ(5UL, regset_data->vtype);
835 		} else {
836 			EXPECT_EQ(9UL, regset_data->vtype);
837 		}
838 
839 		EXPECT_EQ(regset_data->vlenb, regset_data->vl);
840 		EXPECT_EQ(vlenb, regset_data->vlenb);
841 		EXPECT_EQ(0UL, regset_data->vstart);
842 		EXPECT_EQ(0UL, regset_data->vcsr);
843 
844 		/* apply valid settings from fixture variants */
845 
846 		regset_data->vlenb *= variant->vlenb_mul;
847 		regset_data->vstart = variant->vstart;
848 		regset_data->vtype = variant->vtype;
849 		regset_data->vcsr = variant->vcsr;
850 		regset_data->vl = variant->vl;
851 
852 		iov.iov_base = regset_data;
853 		iov.iov_len = regset_size;
854 
855 		ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_RISCV_VECTOR, &iov));
856 
857 		/* skip 1st ebreak, then resume and wait for the 2nd ebreak */
858 
859 		iov.iov_base = &regs;
860 		iov.iov_len = sizeof(regs);
861 
862 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
863 		regs.pc += 4;
864 		ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov));
865 
866 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
867 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
868 		ASSERT_TRUE(WIFSTOPPED(status));
869 
870 		/* read tracee vector csr regs using ptrace GETREGSET */
871 
872 		iov.iov_base = regset_data;
873 		iov.iov_len = regset_size;
874 
875 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
876 
877 		/* verify vector csr regs from tracee context */
878 
879 		EXPECT_EQ(regset_data->vstart, variant->vstart);
880 		EXPECT_EQ(regset_data->vtype, variant->vtype);
881 		EXPECT_EQ(regset_data->vcsr, variant->vcsr);
882 		EXPECT_EQ(regset_data->vl, variant->vl);
883 		EXPECT_EQ(regset_data->vlenb, vlenb);
884 
885 		/* skip 2nd ebreak, then resume and wait for the 3rd ebreak */
886 
887 		iov.iov_base = &regs;
888 		iov.iov_len = sizeof(regs);
889 
890 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
891 		regs.pc += 4;
892 		ASSERT_EQ(0, ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov));
893 
894 		ASSERT_EQ(0, ptrace(PTRACE_CONT, pid, NULL, NULL));
895 		ASSERT_EQ(pid, waitpid(pid, &status, 0));
896 		ASSERT_TRUE(WIFSTOPPED(status));
897 
898 		/* read tracee vector csr regs using ptrace GETREGSET */
899 
900 		iov.iov_base = regset_data;
901 		iov.iov_len = regset_size;
902 
903 		ASSERT_EQ(0, ptrace(PTRACE_GETREGSET, pid, NT_RISCV_VECTOR, &iov));
904 
905 		/* verify vector csr regs from tracee context */
906 
907 		EXPECT_EQ(regset_data->vstart, variant->vstart);
908 		EXPECT_EQ(regset_data->vtype, variant->vtype);
909 		EXPECT_EQ(regset_data->vcsr, variant->vcsr);
910 		EXPECT_EQ(regset_data->vl, variant->vl);
911 		EXPECT_EQ(regset_data->vlenb, vlenb);
912 
913 		/* cleanup */
914 		free(regset_data);
915 		ASSERT_EQ(0, kill(pid, SIGKILL));
916 	}
917 }
918 
919 TEST_HARNESS_MAIN
920