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