1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021 ARM Limited. 4 * Original author: Mark Brown <broonie@kernel.org> 5 */ 6 #include <assert.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <stdbool.h> 10 #include <stddef.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <sys/auxv.h> 16 #include <sys/prctl.h> 17 #include <sys/types.h> 18 #include <sys/wait.h> 19 #include <asm/sigcontext.h> 20 #include <asm/hwcap.h> 21 22 #include "../../kselftest.h" 23 #include "rdvl.h" 24 25 #define ARCH_MIN_VL SVE_VL_MIN 26 27 struct vec_data { 28 const char *name; 29 unsigned long hwcap_type; 30 unsigned long hwcap; 31 const char *rdvl_binary; 32 int (*rdvl)(void); 33 34 int prctl_get; 35 int prctl_set; 36 const char *default_vl_file; 37 38 int default_vl; 39 int min_vl; 40 int max_vl; 41 }; 42 43 #define VEC_SVE 0 44 #define VEC_SME 1 45 46 static struct vec_data vec_data[] = { 47 [VEC_SVE] = { 48 .name = "SVE", 49 .hwcap_type = AT_HWCAP, 50 .hwcap = HWCAP_SVE, 51 .rdvl = rdvl_sve, 52 .rdvl_binary = "./rdvl-sve", 53 .prctl_get = PR_SVE_GET_VL, 54 .prctl_set = PR_SVE_SET_VL, 55 .default_vl_file = "/proc/sys/abi/sve_default_vector_length", 56 }, 57 [VEC_SME] = { 58 .name = "SME", 59 .hwcap_type = AT_HWCAP2, 60 .hwcap = HWCAP2_SME, 61 .rdvl = rdvl_sme, 62 .rdvl_binary = "./rdvl-sme", 63 .prctl_get = PR_SME_GET_VL, 64 .prctl_set = PR_SME_SET_VL, 65 .default_vl_file = "/proc/sys/abi/sme_default_vector_length", 66 }, 67 }; 68 69 static bool vec_type_supported(struct vec_data *data) 70 { 71 return getauxval(data->hwcap_type) & data->hwcap; 72 } 73 74 static int stdio_read_integer(FILE *f, const char *what, int *val) 75 { 76 int n = 0; 77 int ret; 78 79 ret = fscanf(f, "%d%*1[\n]%n", val, &n); 80 if (ret < 1 || n < 1) { 81 ksft_print_msg("failed to parse integer from %s\n", what); 82 return -1; 83 } 84 85 return 0; 86 } 87 88 /* Start a new process and return the vector length it sees */ 89 static int get_child_rdvl(struct vec_data *data) 90 { 91 FILE *out; 92 int pipefd[2]; 93 pid_t pid, child; 94 int read_vl, ret; 95 96 ret = pipe(pipefd); 97 if (ret == -1) { 98 ksft_print_msg("pipe() failed: %d (%s)\n", 99 errno, strerror(errno)); 100 return -1; 101 } 102 103 fflush(stdout); 104 105 child = fork(); 106 if (child == -1) { 107 ksft_print_msg("fork() failed: %d (%s)\n", 108 errno, strerror(errno)); 109 close(pipefd[0]); 110 close(pipefd[1]); 111 return -1; 112 } 113 114 /* Child: put vector length on the pipe */ 115 if (child == 0) { 116 /* 117 * Replace stdout with the pipe, errors to stderr from 118 * here as kselftest prints to stdout. 119 */ 120 ret = dup2(pipefd[1], 1); 121 if (ret == -1) { 122 fprintf(stderr, "dup2() %d\n", errno); 123 exit(EXIT_FAILURE); 124 } 125 126 /* exec() a new binary which puts the VL on stdout */ 127 ret = execl(data->rdvl_binary, data->rdvl_binary, NULL); 128 fprintf(stderr, "execl(%s) failed: %d (%s)\n", 129 data->rdvl_binary, errno, strerror(errno)); 130 131 exit(EXIT_FAILURE); 132 } 133 134 close(pipefd[1]); 135 136 /* Parent; wait for the exit status from the child & verify it */ 137 do { 138 pid = wait(&ret); 139 if (pid == -1) { 140 ksft_print_msg("wait() failed: %d (%s)\n", 141 errno, strerror(errno)); 142 close(pipefd[0]); 143 return -1; 144 } 145 } while (pid != child); 146 147 assert(pid == child); 148 149 if (!WIFEXITED(ret)) { 150 ksft_print_msg("child exited abnormally\n"); 151 close(pipefd[0]); 152 return -1; 153 } 154 155 if (WEXITSTATUS(ret) != 0) { 156 ksft_print_msg("child returned error %d\n", 157 WEXITSTATUS(ret)); 158 close(pipefd[0]); 159 return -1; 160 } 161 162 out = fdopen(pipefd[0], "r"); 163 if (!out) { 164 ksft_print_msg("failed to open child stdout\n"); 165 close(pipefd[0]); 166 return -1; 167 } 168 169 ret = stdio_read_integer(out, "child", &read_vl); 170 fclose(out); 171 if (ret != 0) 172 return ret; 173 174 return read_vl; 175 } 176 177 static int file_read_integer(const char *name, int *val) 178 { 179 FILE *f; 180 int ret; 181 182 f = fopen(name, "r"); 183 if (!f) { 184 ksft_test_result_fail("Unable to open %s: %d (%s)\n", 185 name, errno, 186 strerror(errno)); 187 return -1; 188 } 189 190 ret = stdio_read_integer(f, name, val); 191 fclose(f); 192 193 return ret; 194 } 195 196 static int file_write_integer(const char *name, int val) 197 { 198 FILE *f; 199 200 f = fopen(name, "w"); 201 if (!f) { 202 ksft_test_result_fail("Unable to open %s: %d (%s)\n", 203 name, errno, 204 strerror(errno)); 205 return -1; 206 } 207 208 fprintf(f, "%d", val); 209 fclose(f); 210 211 return 0; 212 } 213 214 /* 215 * Verify that we can read the default VL via proc, checking that it 216 * is set in a freshly spawned child. 217 */ 218 static void proc_read_default(struct vec_data *data) 219 { 220 int default_vl, child_vl, ret; 221 222 ret = file_read_integer(data->default_vl_file, &default_vl); 223 if (ret != 0) 224 return; 225 226 /* Is this the actual default seen by new processes? */ 227 child_vl = get_child_rdvl(data); 228 if (child_vl != default_vl) { 229 ksft_test_result_fail("%s is %d but child VL is %d\n", 230 data->default_vl_file, 231 default_vl, child_vl); 232 return; 233 } 234 235 ksft_test_result_pass("%s default vector length %d\n", data->name, 236 default_vl); 237 data->default_vl = default_vl; 238 } 239 240 /* Verify that we can write a minimum value and have it take effect */ 241 static void proc_write_min(struct vec_data *data) 242 { 243 int ret, new_default, child_vl; 244 245 if (geteuid() != 0) { 246 ksft_test_result_skip("Need to be root to write to /proc\n"); 247 return; 248 } 249 250 ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL); 251 if (ret != 0) 252 return; 253 254 /* What was the new value? */ 255 ret = file_read_integer(data->default_vl_file, &new_default); 256 if (ret != 0) 257 return; 258 259 /* Did it take effect in a new process? */ 260 child_vl = get_child_rdvl(data); 261 if (child_vl != new_default) { 262 ksft_test_result_fail("%s is %d but child VL is %d\n", 263 data->default_vl_file, 264 new_default, child_vl); 265 return; 266 } 267 268 ksft_test_result_pass("%s minimum vector length %d\n", data->name, 269 new_default); 270 data->min_vl = new_default; 271 272 file_write_integer(data->default_vl_file, data->default_vl); 273 } 274 275 /* Verify that we can write a maximum value and have it take effect */ 276 static void proc_write_max(struct vec_data *data) 277 { 278 int ret, new_default, child_vl; 279 280 if (geteuid() != 0) { 281 ksft_test_result_skip("Need to be root to write to /proc\n"); 282 return; 283 } 284 285 /* -1 is accepted by the /proc interface as the maximum VL */ 286 ret = file_write_integer(data->default_vl_file, -1); 287 if (ret != 0) 288 return; 289 290 /* What was the new value? */ 291 ret = file_read_integer(data->default_vl_file, &new_default); 292 if (ret != 0) 293 return; 294 295 /* Did it take effect in a new process? */ 296 child_vl = get_child_rdvl(data); 297 if (child_vl != new_default) { 298 ksft_test_result_fail("%s is %d but child VL is %d\n", 299 data->default_vl_file, 300 new_default, child_vl); 301 return; 302 } 303 304 ksft_test_result_pass("%s maximum vector length %d\n", data->name, 305 new_default); 306 data->max_vl = new_default; 307 308 file_write_integer(data->default_vl_file, data->default_vl); 309 } 310 311 /* Can we read back a VL from prctl? */ 312 static void prctl_get(struct vec_data *data) 313 { 314 int ret; 315 316 ret = prctl(data->prctl_get); 317 if (ret == -1) { 318 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n", 319 data->name, errno, strerror(errno)); 320 return; 321 } 322 323 /* Mask out any flags */ 324 ret &= PR_SVE_VL_LEN_MASK; 325 326 /* Is that what we can read back directly? */ 327 if (ret == data->rdvl()) 328 ksft_test_result_pass("%s current VL is %d\n", 329 data->name, ret); 330 else 331 ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n", 332 data->name, ret, data->rdvl()); 333 } 334 335 /* Does the prctl let us set the VL we already have? */ 336 static void prctl_set_same(struct vec_data *data) 337 { 338 int cur_vl = data->rdvl(); 339 int ret; 340 341 ret = prctl(data->prctl_set, cur_vl); 342 if (ret < 0) { 343 ksft_test_result_fail("%s prctl set failed: %d (%s)\n", 344 data->name, errno, strerror(errno)); 345 return; 346 } 347 348 ksft_test_result(cur_vl == data->rdvl(), 349 "%s set VL %d and have VL %d\n", 350 data->name, cur_vl, data->rdvl()); 351 } 352 353 /* Can we set a new VL for this process? */ 354 static void prctl_set(struct vec_data *data) 355 { 356 int ret; 357 358 if (data->min_vl == data->max_vl) { 359 ksft_test_result_skip("%s only one VL supported\n", 360 data->name); 361 return; 362 } 363 364 /* Try to set the minimum VL */ 365 ret = prctl(data->prctl_set, data->min_vl); 366 if (ret < 0) { 367 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 368 data->name, data->min_vl, 369 errno, strerror(errno)); 370 return; 371 } 372 373 if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) { 374 ksft_test_result_fail("%s prctl set %d but return value is %d\n", 375 data->name, data->min_vl, data->rdvl()); 376 return; 377 } 378 379 if (data->rdvl() != data->min_vl) { 380 ksft_test_result_fail("%s set %d but RDVL is %d\n", 381 data->name, data->min_vl, data->rdvl()); 382 return; 383 } 384 385 /* Try to set the maximum VL */ 386 ret = prctl(data->prctl_set, data->max_vl); 387 if (ret < 0) { 388 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 389 data->name, data->max_vl, 390 errno, strerror(errno)); 391 return; 392 } 393 394 if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) { 395 ksft_test_result_fail("%s prctl() set %d but return value is %d\n", 396 data->name, data->max_vl, data->rdvl()); 397 return; 398 } 399 400 /* The _INHERIT flag should not be present when we read the VL */ 401 ret = prctl(data->prctl_get); 402 if (ret == -1) { 403 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n", 404 data->name, errno, strerror(errno)); 405 return; 406 } 407 408 if (ret & PR_SVE_VL_INHERIT) { 409 ksft_test_result_fail("%s prctl() reports _INHERIT\n", 410 data->name); 411 return; 412 } 413 414 ksft_test_result_pass("%s prctl() set min/max\n", data->name); 415 } 416 417 /* If we didn't request it a new VL shouldn't affect the child */ 418 static void prctl_set_no_child(struct vec_data *data) 419 { 420 int ret, child_vl; 421 422 if (data->min_vl == data->max_vl) { 423 ksft_test_result_skip("%s only one VL supported\n", 424 data->name); 425 return; 426 } 427 428 ret = prctl(data->prctl_set, data->min_vl); 429 if (ret < 0) { 430 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 431 data->name, data->min_vl, 432 errno, strerror(errno)); 433 return; 434 } 435 436 /* Ensure the default VL is different */ 437 ret = file_write_integer(data->default_vl_file, data->max_vl); 438 if (ret != 0) 439 return; 440 441 /* Check that the child has the default we just set */ 442 child_vl = get_child_rdvl(data); 443 if (child_vl != data->max_vl) { 444 ksft_test_result_fail("%s is %d but child VL is %d\n", 445 data->default_vl_file, 446 data->max_vl, child_vl); 447 return; 448 } 449 450 ksft_test_result_pass("%s vector length used default\n", data->name); 451 452 file_write_integer(data->default_vl_file, data->default_vl); 453 } 454 455 /* If we didn't request it a new VL shouldn't affect the child */ 456 static void prctl_set_for_child(struct vec_data *data) 457 { 458 int ret, child_vl; 459 460 if (data->min_vl == data->max_vl) { 461 ksft_test_result_skip("%s only one VL supported\n", 462 data->name); 463 return; 464 } 465 466 ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT); 467 if (ret < 0) { 468 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 469 data->name, data->min_vl, 470 errno, strerror(errno)); 471 return; 472 } 473 474 /* The _INHERIT flag should be present when we read the VL */ 475 ret = prctl(data->prctl_get); 476 if (ret == -1) { 477 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n", 478 data->name, errno, strerror(errno)); 479 return; 480 } 481 if (!(ret & PR_SVE_VL_INHERIT)) { 482 ksft_test_result_fail("%s prctl() does not report _INHERIT\n", 483 data->name); 484 return; 485 } 486 487 /* Ensure the default VL is different */ 488 ret = file_write_integer(data->default_vl_file, data->max_vl); 489 if (ret != 0) 490 return; 491 492 /* Check that the child inherited our VL */ 493 child_vl = get_child_rdvl(data); 494 if (child_vl != data->min_vl) { 495 ksft_test_result_fail("%s is %d but child VL is %d\n", 496 data->default_vl_file, 497 data->min_vl, child_vl); 498 return; 499 } 500 501 ksft_test_result_pass("%s vector length was inherited\n", data->name); 502 503 file_write_integer(data->default_vl_file, data->default_vl); 504 } 505 506 /* _ONEXEC takes effect only in the child process */ 507 static void prctl_set_onexec(struct vec_data *data) 508 { 509 int ret, child_vl; 510 511 if (data->min_vl == data->max_vl) { 512 ksft_test_result_skip("%s only one VL supported\n", 513 data->name); 514 return; 515 } 516 517 /* Set a known value for the default and our current VL */ 518 ret = file_write_integer(data->default_vl_file, data->max_vl); 519 if (ret != 0) 520 return; 521 522 ret = prctl(data->prctl_set, data->max_vl); 523 if (ret < 0) { 524 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 525 data->name, data->min_vl, 526 errno, strerror(errno)); 527 return; 528 } 529 530 /* Set a different value for the child to have on exec */ 531 ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC); 532 if (ret < 0) { 533 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n", 534 data->name, data->min_vl, 535 errno, strerror(errno)); 536 return; 537 } 538 539 /* Our current VL should stay the same */ 540 if (data->rdvl() != data->max_vl) { 541 ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n", 542 data->name); 543 return; 544 } 545 546 /* Check that the child inherited our VL */ 547 child_vl = get_child_rdvl(data); 548 if (child_vl != data->min_vl) { 549 ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n", 550 data->min_vl, child_vl); 551 return; 552 } 553 554 ksft_test_result_pass("%s vector length set on exec\n", data->name); 555 556 file_write_integer(data->default_vl_file, data->default_vl); 557 } 558 559 /* For each VQ verify that setting via prctl() does the right thing */ 560 static void prctl_set_all_vqs(struct vec_data *data) 561 { 562 int ret, vq, vl, new_vl, i; 563 int orig_vls[ARRAY_SIZE(vec_data)]; 564 int errors = 0; 565 566 if (!data->min_vl || !data->max_vl) { 567 ksft_test_result_skip("%s Failed to enumerate VLs, not testing VL setting\n", 568 data->name); 569 return; 570 } 571 572 for (i = 0; i < ARRAY_SIZE(vec_data); i++) { 573 if (!vec_type_supported(&vec_data[i])) 574 continue; 575 orig_vls[i] = vec_data[i].rdvl(); 576 } 577 578 for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) { 579 vl = sve_vl_from_vq(vq); 580 581 /* Attempt to set the VL */ 582 ret = prctl(data->prctl_set, vl); 583 if (ret < 0) { 584 errors++; 585 ksft_print_msg("%s prctl set failed for %d: %d (%s)\n", 586 data->name, vl, 587 errno, strerror(errno)); 588 continue; 589 } 590 591 new_vl = ret & PR_SVE_VL_LEN_MASK; 592 593 /* Check that we actually have the reported new VL */ 594 if (data->rdvl() != new_vl) { 595 ksft_print_msg("Set %s VL %d but RDVL reports %d\n", 596 data->name, new_vl, data->rdvl()); 597 errors++; 598 } 599 600 /* Did any other VLs change? */ 601 for (i = 0; i < ARRAY_SIZE(vec_data); i++) { 602 if (&vec_data[i] == data) 603 continue; 604 605 if (!vec_type_supported(&vec_data[i])) 606 continue; 607 608 if (vec_data[i].rdvl() != orig_vls[i]) { 609 ksft_print_msg("%s VL changed from %d to %d\n", 610 vec_data[i].name, orig_vls[i], 611 vec_data[i].rdvl()); 612 errors++; 613 } 614 } 615 616 /* Was that the VL we asked for? */ 617 if (new_vl == vl) 618 continue; 619 620 /* Should round up to the minimum VL if below it */ 621 if (vl < data->min_vl) { 622 if (new_vl != data->min_vl) { 623 ksft_print_msg("%s VL %d returned %d not minimum %d\n", 624 data->name, vl, new_vl, 625 data->min_vl); 626 errors++; 627 } 628 629 continue; 630 } 631 632 /* Should round down to maximum VL if above it */ 633 if (vl > data->max_vl) { 634 if (new_vl != data->max_vl) { 635 ksft_print_msg("%s VL %d returned %d not maximum %d\n", 636 data->name, vl, new_vl, 637 data->max_vl); 638 errors++; 639 } 640 641 continue; 642 } 643 644 /* Otherwise we should've rounded down */ 645 if (!(new_vl < vl)) { 646 ksft_print_msg("%s VL %d returned %d, did not round down\n", 647 data->name, vl, new_vl); 648 errors++; 649 650 continue; 651 } 652 } 653 654 ksft_test_result(errors == 0, "%s prctl() set all VLs, %d errors\n", 655 data->name, errors); 656 } 657 658 typedef void (*test_type)(struct vec_data *); 659 660 static const test_type tests[] = { 661 /* 662 * The default/min/max tests must be first and in this order 663 * to provide data for other tests. 664 */ 665 proc_read_default, 666 proc_write_min, 667 proc_write_max, 668 669 prctl_get, 670 prctl_set_same, 671 prctl_set, 672 prctl_set_no_child, 673 prctl_set_for_child, 674 prctl_set_onexec, 675 prctl_set_all_vqs, 676 }; 677 678 static inline void smstart(void) 679 { 680 asm volatile("msr S0_3_C4_C7_3, xzr"); 681 } 682 683 static inline void smstart_sm(void) 684 { 685 asm volatile("msr S0_3_C4_C3_3, xzr"); 686 } 687 688 static inline void smstop(void) 689 { 690 asm volatile("msr S0_3_C4_C6_3, xzr"); 691 } 692 693 694 /* 695 * Verify we can change the SVE vector length while SME is active and 696 * continue to use SME afterwards. 697 */ 698 static void change_sve_with_za(void) 699 { 700 struct vec_data *sve_data = &vec_data[VEC_SVE]; 701 bool pass = true; 702 int ret, i; 703 704 if (sve_data->min_vl == sve_data->max_vl) { 705 ksft_print_msg("Only one SVE VL supported, can't change\n"); 706 ksft_test_result_skip("change_sve_while_sme\n"); 707 return; 708 } 709 710 /* Ensure we will trigger a change when we set the maximum */ 711 ret = prctl(sve_data->prctl_set, sve_data->min_vl); 712 if (ret != sve_data->min_vl) { 713 ksft_print_msg("Failed to set SVE VL %d: %d\n", 714 sve_data->min_vl, ret); 715 pass = false; 716 } 717 718 /* Enable SM and ZA */ 719 smstart(); 720 721 /* Trigger another VL change */ 722 ret = prctl(sve_data->prctl_set, sve_data->max_vl); 723 if (ret != sve_data->max_vl) { 724 ksft_print_msg("Failed to set SVE VL %d: %d\n", 725 sve_data->max_vl, ret); 726 pass = false; 727 } 728 729 /* 730 * Spin for a bit with SM enabled to try to trigger another 731 * save/restore. We can't use syscalls without exiting 732 * streaming mode. 733 */ 734 for (i = 0; i < 100000000; i++) 735 smstart_sm(); 736 737 /* 738 * TODO: Verify that ZA was preserved over the VL change and 739 * spin. 740 */ 741 742 /* Clean up after ourselves */ 743 smstop(); 744 ret = prctl(sve_data->prctl_set, sve_data->default_vl); 745 if (ret != sve_data->default_vl) { 746 ksft_print_msg("Failed to restore SVE VL %d: %d\n", 747 sve_data->default_vl, ret); 748 pass = false; 749 } 750 751 ksft_test_result(pass, "change_sve_with_za\n"); 752 } 753 754 typedef void (*test_all_type)(void); 755 756 static const struct { 757 const char *name; 758 test_all_type test; 759 } all_types_tests[] = { 760 { "change_sve_with_za", change_sve_with_za }, 761 }; 762 763 int main(void) 764 { 765 bool all_supported = true; 766 int i, j; 767 768 ksft_print_header(); 769 ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data) + 770 ARRAY_SIZE(all_types_tests)); 771 772 for (i = 0; i < ARRAY_SIZE(vec_data); i++) { 773 struct vec_data *data = &vec_data[i]; 774 unsigned long supported; 775 776 supported = vec_type_supported(data); 777 if (!supported) 778 all_supported = false; 779 780 for (j = 0; j < ARRAY_SIZE(tests); j++) { 781 if (supported) 782 tests[j](data); 783 else 784 ksft_test_result_skip("%s not supported\n", 785 data->name); 786 } 787 } 788 789 for (i = 0; i < ARRAY_SIZE(all_types_tests); i++) { 790 if (all_supported) 791 all_types_tests[i].test(); 792 else 793 ksft_test_result_skip("%s\n", all_types_tests[i].name); 794 } 795 796 ksft_exit_pass(); 797 } 798