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 = ®s; 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 = ®s; 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 = ®s; 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