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