1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2023 ARM Limited. 4 * Original author: Mark Brown <broonie@kernel.org> 5 */ 6 7 #define _GNU_SOURCE 8 9 #include <errno.h> 10 #include <stdbool.h> 11 #include <stddef.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include <sys/auxv.h> 18 #include <sys/prctl.h> 19 #include <sys/ptrace.h> 20 #include <sys/types.h> 21 #include <sys/uio.h> 22 #include <sys/wait.h> 23 24 #include <linux/kernel.h> 25 26 #include <asm/sigcontext.h> 27 #include <asm/sve_context.h> 28 #include <asm/ptrace.h> 29 30 #include "kselftest.h" 31 32 #include "fp-ptrace.h" 33 34 #include <linux/bits.h> 35 36 #define FPMR_LSCALE2_MASK GENMASK(37, 32) 37 #define FPMR_NSCALE_MASK GENMASK(31, 24) 38 #define FPMR_LSCALE_MASK GENMASK(22, 16) 39 #define FPMR_OSC_MASK GENMASK(15, 15) 40 #define FPMR_OSM_MASK GENMASK(14, 14) 41 42 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */ 43 #ifndef NT_ARM_SVE 44 #define NT_ARM_SVE 0x405 45 #endif 46 47 #ifndef NT_ARM_SSVE 48 #define NT_ARM_SSVE 0x40b 49 #endif 50 51 #ifndef NT_ARM_ZA 52 #define NT_ARM_ZA 0x40c 53 #endif 54 55 #ifndef NT_ARM_ZT 56 #define NT_ARM_ZT 0x40d 57 #endif 58 59 #ifndef NT_ARM_FPMR 60 #define NT_ARM_FPMR 0x40e 61 #endif 62 63 #define ARCH_VQ_MAX 256 64 65 /* VL 128..2048 in powers of 2 */ 66 #define MAX_NUM_VLS 5 67 68 /* Sentinel for detecting buffer bytes the kernel did not write */ 69 #define REGSET_SENTINEL 0xa5 70 71 /* 72 * FPMR bits we can set without doing feature checks to see if values 73 * are valid. 74 */ 75 #define FPMR_SAFE_BITS (FPMR_LSCALE2_MASK | FPMR_NSCALE_MASK | \ 76 FPMR_LSCALE_MASK | FPMR_OSC_MASK | FPMR_OSM_MASK) 77 78 #define NUM_FPR 32 79 __uint128_t v_in[NUM_FPR]; 80 __uint128_t v_expected[NUM_FPR]; 81 __uint128_t v_out[NUM_FPR]; 82 83 char z_in[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)]; 84 char z_expected[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)]; 85 char z_out[__SVE_ZREGS_SIZE(ARCH_VQ_MAX)]; 86 87 char p_in[__SVE_PREGS_SIZE(ARCH_VQ_MAX)]; 88 char p_expected[__SVE_PREGS_SIZE(ARCH_VQ_MAX)]; 89 char p_out[__SVE_PREGS_SIZE(ARCH_VQ_MAX)]; 90 91 char ffr_in[__SVE_PREG_SIZE(ARCH_VQ_MAX)]; 92 char ffr_expected[__SVE_PREG_SIZE(ARCH_VQ_MAX)]; 93 char ffr_out[__SVE_PREG_SIZE(ARCH_VQ_MAX)]; 94 95 char za_in[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)]; 96 char za_expected[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)]; 97 char za_out[ZA_SIG_REGS_SIZE(ARCH_VQ_MAX)]; 98 99 char zt_in[ZT_SIG_REG_BYTES]; 100 char zt_expected[ZT_SIG_REG_BYTES]; 101 char zt_out[ZT_SIG_REG_BYTES]; 102 103 uint64_t fpmr_in, fpmr_expected, fpmr_out; 104 105 uint64_t sve_vl_out; 106 uint64_t sme_vl_out; 107 uint64_t svcr_in, svcr_expected, svcr_out; 108 109 void load_and_save(int flags); 110 111 static bool got_alarm; 112 113 static void handle_alarm(int sig, siginfo_t *info, void *context) 114 { 115 got_alarm = true; 116 } 117 118 static bool sve_supported(void) 119 { 120 return getauxval(AT_HWCAP) & HWCAP_SVE; 121 } 122 123 static bool sme_supported(void) 124 { 125 return getauxval(AT_HWCAP2) & HWCAP2_SME; 126 } 127 128 static bool sme2_supported(void) 129 { 130 return getauxval(AT_HWCAP2) & HWCAP2_SME2; 131 } 132 133 static bool fa64_supported(void) 134 { 135 return getauxval(AT_HWCAP2) & HWCAP2_SME_FA64; 136 } 137 138 static bool fpmr_supported(void) 139 { 140 return getauxval(AT_HWCAP2) & HWCAP2_FPMR; 141 } 142 143 static bool compare_buffer(const char *name, void *out, 144 void *expected, size_t size) 145 { 146 void *tmp; 147 148 if (memcmp(out, expected, size) == 0) 149 return true; 150 151 ksft_print_msg("Mismatch in %s\n", name); 152 153 /* Did we just get zeros back? */ 154 tmp = malloc(size); 155 if (!tmp) { 156 ksft_print_msg("OOM allocating %lu bytes for %s\n", 157 size, name); 158 ksft_exit_fail(); 159 } 160 memset(tmp, 0, size); 161 162 if (memcmp(out, tmp, size) == 0) 163 ksft_print_msg("%s is zero\n", name); 164 165 free(tmp); 166 167 return false; 168 } 169 170 static bool buffer_is_filled(const void *buffer, size_t size, 171 unsigned char value) 172 { 173 const unsigned char *bytes = buffer; 174 size_t i; 175 176 for (i = 0; i < size; i++) { 177 if (bytes[i] != value) 178 return false; 179 } 180 181 return true; 182 } 183 184 struct test_config { 185 int sve_vl_in; 186 int sve_vl_expected; 187 int sme_vl_in; 188 int sme_vl_expected; 189 int svcr_in; 190 int svcr_expected; 191 }; 192 193 struct test_definition { 194 const char *name; 195 bool sve_vl_change; 196 bool (*supported)(struct test_config *config); 197 void (*set_expected_values)(struct test_config *config); 198 void (*modify_values)(pid_t child, struct test_config *test_config); 199 }; 200 201 static int vl_in(struct test_config *config) 202 { 203 int vl; 204 205 if (config->svcr_in & SVCR_SM) 206 vl = config->sme_vl_in; 207 else 208 vl = config->sve_vl_in; 209 210 return vl; 211 } 212 213 static int vl_expected(struct test_config *config) 214 { 215 int vl; 216 217 if (config->svcr_expected & SVCR_SM) 218 vl = config->sme_vl_expected; 219 else 220 vl = config->sve_vl_expected; 221 222 return vl; 223 } 224 225 static void run_child(struct test_config *config) 226 { 227 int ret, flags; 228 229 /* Let the parent attach to us */ 230 ret = ptrace(PTRACE_TRACEME, 0, 0, 0); 231 if (ret < 0) 232 ksft_exit_fail_msg("PTRACE_TRACEME failed: %s (%d)\n", 233 strerror(errno), errno); 234 235 /* VL setup */ 236 if (sve_supported()) { 237 ret = prctl(PR_SVE_SET_VL, config->sve_vl_in); 238 if (ret != config->sve_vl_in) { 239 ksft_print_msg("Failed to set SVE VL %d: %d\n", 240 config->sve_vl_in, ret); 241 } 242 } 243 244 if (sme_supported()) { 245 ret = prctl(PR_SME_SET_VL, config->sme_vl_in); 246 if (ret != config->sme_vl_in) { 247 ksft_print_msg("Failed to set SME VL %d: %d\n", 248 config->sme_vl_in, ret); 249 } 250 } 251 252 /* Load values and wait for the parent */ 253 flags = 0; 254 if (sve_supported()) 255 flags |= HAVE_SVE; 256 if (sme_supported()) 257 flags |= HAVE_SME; 258 if (sme2_supported()) 259 flags |= HAVE_SME2; 260 if (fa64_supported()) 261 flags |= HAVE_FA64; 262 if (fpmr_supported()) 263 flags |= HAVE_FPMR; 264 265 load_and_save(flags); 266 267 exit(0); 268 } 269 270 static void read_one_child_regs(pid_t child, char *name, 271 struct iovec *iov_parent, 272 struct iovec *iov_child) 273 { 274 int len = iov_parent->iov_len; 275 int ret; 276 277 ret = process_vm_readv(child, iov_parent, 1, iov_child, 1, 0); 278 if (ret == -1) 279 ksft_print_msg("%s read failed: %s (%d)\n", 280 name, strerror(errno), errno); 281 else if (ret != len) 282 ksft_print_msg("Short read of %s: %d\n", name, ret); 283 } 284 285 static void read_child_regs(pid_t child) 286 { 287 struct iovec iov_parent, iov_child; 288 289 /* 290 * Since the child fork()ed from us the buffer addresses are 291 * the same in parent and child. 292 */ 293 iov_parent.iov_base = &v_out; 294 iov_parent.iov_len = sizeof(v_out); 295 iov_child.iov_base = &v_out; 296 iov_child.iov_len = sizeof(v_out); 297 read_one_child_regs(child, "FPSIMD", &iov_parent, &iov_child); 298 299 if (sve_supported() || sme_supported()) { 300 iov_parent.iov_base = &sve_vl_out; 301 iov_parent.iov_len = sizeof(sve_vl_out); 302 iov_child.iov_base = &sve_vl_out; 303 iov_child.iov_len = sizeof(sve_vl_out); 304 read_one_child_regs(child, "SVE VL", &iov_parent, &iov_child); 305 306 iov_parent.iov_base = &z_out; 307 iov_parent.iov_len = sizeof(z_out); 308 iov_child.iov_base = &z_out; 309 iov_child.iov_len = sizeof(z_out); 310 read_one_child_regs(child, "Z", &iov_parent, &iov_child); 311 312 iov_parent.iov_base = &p_out; 313 iov_parent.iov_len = sizeof(p_out); 314 iov_child.iov_base = &p_out; 315 iov_child.iov_len = sizeof(p_out); 316 read_one_child_regs(child, "P", &iov_parent, &iov_child); 317 318 iov_parent.iov_base = &ffr_out; 319 iov_parent.iov_len = sizeof(ffr_out); 320 iov_child.iov_base = &ffr_out; 321 iov_child.iov_len = sizeof(ffr_out); 322 read_one_child_regs(child, "FFR", &iov_parent, &iov_child); 323 } 324 325 if (sme_supported()) { 326 iov_parent.iov_base = &sme_vl_out; 327 iov_parent.iov_len = sizeof(sme_vl_out); 328 iov_child.iov_base = &sme_vl_out; 329 iov_child.iov_len = sizeof(sme_vl_out); 330 read_one_child_regs(child, "SME VL", &iov_parent, &iov_child); 331 332 iov_parent.iov_base = &svcr_out; 333 iov_parent.iov_len = sizeof(svcr_out); 334 iov_child.iov_base = &svcr_out; 335 iov_child.iov_len = sizeof(svcr_out); 336 read_one_child_regs(child, "SVCR", &iov_parent, &iov_child); 337 338 iov_parent.iov_base = &za_out; 339 iov_parent.iov_len = sizeof(za_out); 340 iov_child.iov_base = &za_out; 341 iov_child.iov_len = sizeof(za_out); 342 read_one_child_regs(child, "ZA", &iov_parent, &iov_child); 343 } 344 345 if (sme2_supported()) { 346 iov_parent.iov_base = &zt_out; 347 iov_parent.iov_len = sizeof(zt_out); 348 iov_child.iov_base = &zt_out; 349 iov_child.iov_len = sizeof(zt_out); 350 read_one_child_regs(child, "ZT", &iov_parent, &iov_child); 351 } 352 353 if (fpmr_supported()) { 354 iov_parent.iov_base = &fpmr_out; 355 iov_parent.iov_len = sizeof(fpmr_out); 356 iov_child.iov_base = &fpmr_out; 357 iov_child.iov_len = sizeof(fpmr_out); 358 read_one_child_regs(child, "FPMR", &iov_parent, &iov_child); 359 } 360 } 361 362 static bool continue_breakpoint(pid_t child, 363 enum __ptrace_request restart_type) 364 { 365 struct user_pt_regs pt_regs; 366 struct iovec iov; 367 int ret; 368 369 /* Get PC */ 370 iov.iov_base = &pt_regs; 371 iov.iov_len = sizeof(pt_regs); 372 ret = ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov); 373 if (ret < 0) { 374 ksft_print_msg("Failed to get PC: %s (%d)\n", 375 strerror(errno), errno); 376 return false; 377 } 378 379 /* Skip over the BRK */ 380 pt_regs.pc += 4; 381 ret = ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, &iov); 382 if (ret < 0) { 383 ksft_print_msg("Failed to skip BRK: %s (%d)\n", 384 strerror(errno), errno); 385 return false; 386 } 387 388 /* Restart */ 389 ret = ptrace(restart_type, child, 0, 0); 390 if (ret < 0) { 391 ksft_print_msg("Failed to restart child: %s (%d)\n", 392 strerror(errno), errno); 393 return false; 394 } 395 396 return true; 397 } 398 399 static bool check_ptrace_values_sve(pid_t child, struct test_config *config) 400 { 401 struct user_sve_header *sve; 402 struct user_fpsimd_state *fpsimd; 403 struct iovec iov; 404 size_t buf_size; 405 int ret, vq; 406 bool pass = true; 407 408 if (!sve_supported()) 409 return true; 410 411 vq = __sve_vq_from_vl(config->sve_vl_in); 412 413 buf_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE); 414 iov.iov_len = buf_size; 415 iov.iov_base = malloc(buf_size); 416 if (!iov.iov_base) { 417 ksft_print_msg("OOM allocating %lu byte SVE buffer\n", 418 iov.iov_len); 419 return false; 420 } 421 422 memset(iov.iov_base, REGSET_SENTINEL, buf_size); 423 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SVE, &iov); 424 if (ret != 0) { 425 ksft_print_msg("Failed to read initial SVE: %s (%d)\n", 426 strerror(errno), errno); 427 pass = false; 428 goto out; 429 } 430 431 sve = iov.iov_base; 432 433 if (sve->vl != config->sve_vl_in) { 434 ksft_print_msg("Mismatch in initial SVE VL: %d != %d\n", 435 sve->vl, config->sve_vl_in); 436 pass = false; 437 } 438 439 /* If we are in streaming mode we should just read FPSIMD */ 440 if ((config->svcr_in & SVCR_SM) && (sve->flags & SVE_PT_REGS_SVE)) { 441 ksft_print_msg("NT_ARM_SVE reports SVE with PSTATE.SM\n"); 442 pass = false; 443 } 444 445 if (svcr_in & SVCR_SM) { 446 if (sve->size != sizeof(*sve)) { 447 ksft_print_msg("NT_ARM_SVE reports data with PSTATE.SM\n"); 448 pass = false; 449 } 450 if (!buffer_is_filled(iov.iov_base + sizeof(*sve), 451 buf_size - sizeof(*sve), REGSET_SENTINEL)) { 452 ksft_print_msg("NT_ARM_SVE wrote beyond its header with PSTATE.SM\n"); 453 pass = false; 454 } 455 goto out; 456 } else { 457 if (sve->size != SVE_PT_SIZE(vq, sve->flags)) { 458 ksft_print_msg("Mismatch in SVE header size: %d != %lu\n", 459 sve->size, SVE_PT_SIZE(vq, sve->flags)); 460 pass = false; 461 } 462 } 463 464 /* The registers might be in completely different formats! */ 465 if (sve->flags & SVE_PT_REGS_SVE) { 466 if (!compare_buffer("initial SVE Z", 467 iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0), 468 z_in, SVE_PT_SVE_ZREGS_SIZE(vq))) 469 pass = false; 470 471 if (!compare_buffer("initial SVE P", 472 iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0), 473 p_in, SVE_PT_SVE_PREGS_SIZE(vq))) 474 pass = false; 475 476 if (!compare_buffer("initial SVE FFR", 477 iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq), 478 ffr_in, SVE_PT_SVE_PREG_SIZE(vq))) 479 pass = false; 480 } else { 481 fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET; 482 if (!compare_buffer("initial V via SVE", &fpsimd->vregs[0], 483 v_in, sizeof(v_in))) 484 pass = false; 485 } 486 487 out: 488 free(iov.iov_base); 489 return pass; 490 } 491 492 static bool check_ptrace_values_ssve(pid_t child, struct test_config *config) 493 { 494 struct user_sve_header *sve; 495 struct user_fpsimd_state *fpsimd; 496 struct iovec iov; 497 size_t buf_size; 498 int ret, vq; 499 bool pass = true; 500 501 if (!sme_supported()) 502 return true; 503 504 vq = __sve_vq_from_vl(config->sme_vl_in); 505 506 buf_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE); 507 iov.iov_len = buf_size; 508 iov.iov_base = malloc(buf_size); 509 if (!iov.iov_base) { 510 ksft_print_msg("OOM allocating %lu byte SSVE buffer\n", 511 iov.iov_len); 512 return false; 513 } 514 515 memset(iov.iov_base, REGSET_SENTINEL, buf_size); 516 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_SSVE, &iov); 517 if (ret != 0) { 518 ksft_print_msg("Failed to read initial SSVE: %s (%d)\n", 519 strerror(errno), errno); 520 pass = false; 521 goto out; 522 } 523 524 sve = iov.iov_base; 525 526 if (sve->vl != config->sme_vl_in) { 527 ksft_print_msg("Mismatch in initial SSVE VL: %d != %d\n", 528 sve->vl, config->sme_vl_in); 529 pass = false; 530 } 531 532 if ((config->svcr_in & SVCR_SM) && !(sve->flags & SVE_PT_REGS_SVE)) { 533 ksft_print_msg("NT_ARM_SSVE reports FPSIMD with PSTATE.SM\n"); 534 pass = false; 535 } 536 537 if (!(svcr_in & SVCR_SM)) { 538 if (sve->size != sizeof(*sve)) { 539 ksft_print_msg("NT_ARM_SSVE reports data without PSTATE.SM\n"); 540 pass = false; 541 } 542 if (!buffer_is_filled(iov.iov_base + sizeof(*sve), 543 buf_size - sizeof(*sve), REGSET_SENTINEL)) { 544 ksft_print_msg("NT_ARM_SSVE wrote beyond its header without PSTATE.SM\n"); 545 pass = false; 546 } 547 goto out; 548 } else { 549 if (sve->size != SVE_PT_SIZE(vq, sve->flags)) { 550 ksft_print_msg("Mismatch in SSVE header size: %d != %lu\n", 551 sve->size, SVE_PT_SIZE(vq, sve->flags)); 552 pass = false; 553 } 554 } 555 556 /* The registers might be in completely different formats! */ 557 if (sve->flags & SVE_PT_REGS_SVE) { 558 if (!compare_buffer("initial SSVE Z", 559 iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0), 560 z_in, SVE_PT_SVE_ZREGS_SIZE(vq))) 561 pass = false; 562 563 if (!compare_buffer("initial SSVE P", 564 iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0), 565 p_in, SVE_PT_SVE_PREGS_SIZE(vq))) 566 pass = false; 567 568 if (!compare_buffer("initial SSVE FFR", 569 iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq), 570 ffr_in, SVE_PT_SVE_PREG_SIZE(vq))) 571 pass = false; 572 } else { 573 fpsimd = iov.iov_base + SVE_PT_FPSIMD_OFFSET; 574 if (!compare_buffer("initial V via SSVE", 575 &fpsimd->vregs[0], v_in, sizeof(v_in))) 576 pass = false; 577 } 578 579 out: 580 free(iov.iov_base); 581 return pass; 582 } 583 584 static bool check_ptrace_values_za(pid_t child, struct test_config *config) 585 { 586 struct user_za_header *za; 587 struct iovec iov; 588 int ret, vq; 589 bool pass = true; 590 591 if (!sme_supported()) 592 return true; 593 594 vq = __sve_vq_from_vl(config->sme_vl_in); 595 596 iov.iov_len = ZA_SIG_CONTEXT_SIZE(vq); 597 iov.iov_base = malloc(iov.iov_len); 598 if (!iov.iov_base) { 599 ksft_print_msg("OOM allocating %lu byte ZA buffer\n", 600 iov.iov_len); 601 return false; 602 } 603 604 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZA, &iov); 605 if (ret != 0) { 606 ksft_print_msg("Failed to read initial ZA: %s (%d)\n", 607 strerror(errno), errno); 608 pass = false; 609 goto out; 610 } 611 612 za = iov.iov_base; 613 614 if (za->vl != config->sme_vl_in) { 615 ksft_print_msg("Mismatch in initial SME VL: %d != %d\n", 616 za->vl, config->sme_vl_in); 617 pass = false; 618 } 619 620 /* If PSTATE.ZA is not set we should just read the header */ 621 if (config->svcr_in & SVCR_ZA) { 622 if (za->size != ZA_PT_SIZE(vq)) { 623 ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n", 624 za->size, ZA_PT_SIZE(vq)); 625 pass = false; 626 } 627 628 if (!compare_buffer("initial ZA", 629 iov.iov_base + ZA_PT_ZA_OFFSET, 630 za_in, ZA_PT_ZA_SIZE(vq))) 631 pass = false; 632 } else { 633 if (za->size != sizeof(*za)) { 634 ksft_print_msg("Unexpected ZA ptrace read size: %d != %lu\n", 635 za->size, sizeof(*za)); 636 pass = false; 637 } 638 } 639 640 out: 641 free(iov.iov_base); 642 return pass; 643 } 644 645 static bool check_ptrace_values_zt(pid_t child, struct test_config *config) 646 { 647 uint8_t buf[512]; 648 struct iovec iov; 649 int ret; 650 651 if (!sme2_supported()) 652 return true; 653 654 iov.iov_base = &buf; 655 iov.iov_len = ZT_SIG_REG_BYTES; 656 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_ZT, &iov); 657 if (ret != 0) { 658 ksft_print_msg("Failed to read initial ZT: %s (%d)\n", 659 strerror(errno), errno); 660 return false; 661 } 662 663 return compare_buffer("initial ZT", buf, zt_in, ZT_SIG_REG_BYTES); 664 } 665 666 static bool check_ptrace_values_fpmr(pid_t child, struct test_config *config) 667 { 668 uint64_t val; 669 struct iovec iov; 670 int ret; 671 672 if (!fpmr_supported()) 673 return true; 674 675 iov.iov_base = &val; 676 iov.iov_len = sizeof(val); 677 ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_FPMR, &iov); 678 if (ret != 0) { 679 ksft_print_msg("Failed to read initial FPMR: %s (%d)\n", 680 strerror(errno), errno); 681 return false; 682 } 683 684 return compare_buffer("initial FPMR", &val, &fpmr_in, sizeof(val)); 685 } 686 687 static bool check_ptrace_values(pid_t child, struct test_config *config) 688 { 689 bool pass = true; 690 struct user_fpsimd_state fpsimd; 691 struct iovec iov; 692 int ret; 693 694 iov.iov_base = &fpsimd; 695 iov.iov_len = sizeof(fpsimd); 696 ret = ptrace(PTRACE_GETREGSET, child, NT_PRFPREG, &iov); 697 if (ret == 0) { 698 if (!compare_buffer("initial V", &fpsimd.vregs, v_in, 699 sizeof(v_in))) { 700 pass = false; 701 } 702 } else { 703 ksft_print_msg("Failed to read initial V: %s (%d)\n", 704 strerror(errno), errno); 705 pass = false; 706 } 707 708 if (!check_ptrace_values_sve(child, config)) 709 pass = false; 710 711 if (!check_ptrace_values_ssve(child, config)) 712 pass = false; 713 714 if (!check_ptrace_values_za(child, config)) 715 pass = false; 716 717 if (!check_ptrace_values_zt(child, config)) 718 pass = false; 719 720 if (!check_ptrace_values_fpmr(child, config)) 721 pass = false; 722 723 return pass; 724 } 725 726 static bool run_parent(pid_t child, struct test_definition *test, 727 struct test_config *config) 728 { 729 int wait_status, ret; 730 pid_t pid; 731 bool pass; 732 733 /* Initial attach */ 734 while (1) { 735 pid = waitpid(child, &wait_status, 0); 736 if (pid < 0) { 737 if (errno == EINTR) 738 continue; 739 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n", 740 strerror(errno), errno); 741 } 742 743 if (pid == child) 744 break; 745 } 746 747 if (WIFEXITED(wait_status)) { 748 ksft_print_msg("Child exited loading values with status %d\n", 749 WEXITSTATUS(wait_status)); 750 pass = false; 751 goto out; 752 } 753 754 if (WIFSIGNALED(wait_status)) { 755 ksft_print_msg("Child died from signal %d loading values\n", 756 WTERMSIG(wait_status)); 757 pass = false; 758 goto out; 759 } 760 761 /* Read initial values via ptrace */ 762 pass = check_ptrace_values(child, config); 763 764 /* Do whatever writes we want to do */ 765 if (test->modify_values) 766 test->modify_values(child, config); 767 768 if (!continue_breakpoint(child, PTRACE_CONT)) 769 goto cleanup; 770 771 while (1) { 772 pid = waitpid(child, &wait_status, 0); 773 if (pid < 0) { 774 if (errno == EINTR) 775 continue; 776 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n", 777 strerror(errno), errno); 778 } 779 780 if (pid == child) 781 break; 782 } 783 784 if (WIFEXITED(wait_status)) { 785 ksft_print_msg("Child exited saving values with status %d\n", 786 WEXITSTATUS(wait_status)); 787 pass = false; 788 goto out; 789 } 790 791 if (WIFSIGNALED(wait_status)) { 792 ksft_print_msg("Child died from signal %d saving values\n", 793 WTERMSIG(wait_status)); 794 pass = false; 795 goto out; 796 } 797 798 /* See what happened as a result */ 799 read_child_regs(child); 800 801 if (!continue_breakpoint(child, PTRACE_DETACH)) 802 goto cleanup; 803 804 /* The child should exit cleanly */ 805 got_alarm = false; 806 alarm(1); 807 while (1) { 808 if (got_alarm) { 809 ksft_print_msg("Wait for child timed out\n"); 810 goto cleanup; 811 } 812 813 pid = waitpid(child, &wait_status, 0); 814 if (pid < 0) { 815 if (errno == EINTR) 816 continue; 817 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n", 818 strerror(errno), errno); 819 } 820 821 if (pid == child) 822 break; 823 } 824 alarm(0); 825 826 if (got_alarm) { 827 ksft_print_msg("Timed out waiting for child\n"); 828 pass = false; 829 goto cleanup; 830 } 831 832 if (pid == child && WIFSIGNALED(wait_status)) { 833 ksft_print_msg("Child died from signal %d cleaning up\n", 834 WTERMSIG(wait_status)); 835 pass = false; 836 goto out; 837 } 838 839 if (pid == child && WIFEXITED(wait_status)) { 840 if (WEXITSTATUS(wait_status) != 0) { 841 ksft_print_msg("Child exited with error %d\n", 842 WEXITSTATUS(wait_status)); 843 pass = false; 844 } 845 } else { 846 ksft_print_msg("Child did not exit cleanly\n"); 847 pass = false; 848 goto cleanup; 849 } 850 851 goto out; 852 853 cleanup: 854 ret = kill(child, SIGKILL); 855 if (ret != 0) { 856 ksft_print_msg("kill() failed: %s (%d)\n", 857 strerror(errno), errno); 858 return false; 859 } 860 861 while (1) { 862 pid = waitpid(child, &wait_status, 0); 863 if (pid < 0) { 864 if (errno == EINTR) 865 continue; 866 ksft_exit_fail_msg("waitpid() failed: %s (%d)\n", 867 strerror(errno), errno); 868 } 869 870 if (pid == child) 871 break; 872 } 873 874 out: 875 return pass; 876 } 877 878 static void fill_random(void *buf, size_t size) 879 { 880 int i; 881 uint32_t *lbuf = buf; 882 883 /* random() returns a 32 bit number regardless of the size of long */ 884 for (i = 0; i < size / sizeof(uint32_t); i++) 885 lbuf[i] = random(); 886 } 887 888 static void fill_random_ffr(void *buf, size_t vq) 889 { 890 uint8_t *lbuf = buf; 891 int bits, i; 892 893 /* 894 * Only values with a continuous set of 0..n bits set are 895 * valid for FFR, set all bits then clear a random number of 896 * high bits. 897 */ 898 memset(buf, 0, __SVE_FFR_SIZE(vq)); 899 900 bits = random() % (__SVE_FFR_SIZE(vq) * 8); 901 for (i = 0; i < bits / 8; i++) 902 lbuf[i] = 0xff; 903 if (bits / 8 != __SVE_FFR_SIZE(vq)) 904 lbuf[i] = (1 << (bits % 8)) - 1; 905 } 906 907 static void fpsimd_to_sve(__uint128_t *v, char *z, int vl) 908 { 909 int vq = __sve_vq_from_vl(vl); 910 int i; 911 __uint128_t *p; 912 913 if (!vl) 914 return; 915 916 for (i = 0; i < __SVE_NUM_ZREGS; i++) { 917 p = (__uint128_t *)&z[__SVE_ZREG_OFFSET(vq, i)]; 918 *p = v[i]; 919 } 920 } 921 922 static void set_initial_values(struct test_config *config) 923 { 924 int vq = __sve_vq_from_vl(vl_in(config)); 925 int sme_vq = __sve_vq_from_vl(config->sme_vl_in); 926 927 svcr_in = config->svcr_in; 928 svcr_expected = config->svcr_expected; 929 svcr_out = 0; 930 931 fill_random(&v_in, sizeof(v_in)); 932 memcpy(v_expected, v_in, sizeof(v_in)); 933 memset(v_out, 0, sizeof(v_out)); 934 935 /* Changes will be handled in the test case */ 936 if (sve_supported() || (config->svcr_in & SVCR_SM)) { 937 /* The low 128 bits of Z are shared with the V registers */ 938 fill_random(&z_in, __SVE_ZREGS_SIZE(vq)); 939 fpsimd_to_sve(v_in, z_in, vl_in(config)); 940 memcpy(z_expected, z_in, __SVE_ZREGS_SIZE(vq)); 941 memset(z_out, 0, sizeof(z_out)); 942 943 fill_random(&p_in, __SVE_PREGS_SIZE(vq)); 944 memcpy(p_expected, p_in, __SVE_PREGS_SIZE(vq)); 945 memset(p_out, 0, sizeof(p_out)); 946 947 if ((config->svcr_in & SVCR_SM) && !fa64_supported()) 948 memset(ffr_in, 0, __SVE_PREG_SIZE(vq)); 949 else 950 fill_random_ffr(&ffr_in, vq); 951 memcpy(ffr_expected, ffr_in, __SVE_PREG_SIZE(vq)); 952 memset(ffr_out, 0, __SVE_PREG_SIZE(vq)); 953 } 954 955 if (config->svcr_in & SVCR_ZA) 956 fill_random(za_in, ZA_SIG_REGS_SIZE(sme_vq)); 957 else 958 memset(za_in, 0, ZA_SIG_REGS_SIZE(sme_vq)); 959 if (config->svcr_expected & SVCR_ZA) 960 memcpy(za_expected, za_in, ZA_SIG_REGS_SIZE(sme_vq)); 961 else 962 memset(za_expected, 0, ZA_SIG_REGS_SIZE(sme_vq)); 963 if (sme_supported()) 964 memset(za_out, 0, sizeof(za_out)); 965 966 if (sme2_supported()) { 967 if (config->svcr_in & SVCR_ZA) 968 fill_random(zt_in, ZT_SIG_REG_BYTES); 969 else 970 memset(zt_in, 0, ZT_SIG_REG_BYTES); 971 if (config->svcr_expected & SVCR_ZA) 972 memcpy(zt_expected, zt_in, ZT_SIG_REG_BYTES); 973 else 974 memset(zt_expected, 0, ZT_SIG_REG_BYTES); 975 memset(zt_out, 0, sizeof(zt_out)); 976 } 977 978 if (fpmr_supported()) { 979 fill_random(&fpmr_in, sizeof(fpmr_in)); 980 fpmr_in &= FPMR_SAFE_BITS; 981 fpmr_expected = fpmr_in; 982 } else { 983 fpmr_in = 0; 984 fpmr_expected = 0; 985 fpmr_out = 0; 986 } 987 } 988 989 static bool check_memory_values(struct test_config *config) 990 { 991 bool pass = true; 992 int vq, sme_vq; 993 994 if (!compare_buffer("saved V", v_out, v_expected, sizeof(v_out))) 995 pass = false; 996 997 vq = __sve_vq_from_vl(vl_expected(config)); 998 sme_vq = __sve_vq_from_vl(config->sme_vl_expected); 999 1000 if (svcr_out != svcr_expected) { 1001 ksft_print_msg("Mismatch in saved SVCR %lx != %lx\n", 1002 svcr_out, svcr_expected); 1003 pass = false; 1004 } 1005 1006 if (sve_vl_out != config->sve_vl_expected) { 1007 ksft_print_msg("Mismatch in SVE VL: %ld != %d\n", 1008 sve_vl_out, config->sve_vl_expected); 1009 pass = false; 1010 } 1011 1012 if (sme_vl_out != config->sme_vl_expected) { 1013 ksft_print_msg("Mismatch in SME VL: %ld != %d\n", 1014 sme_vl_out, config->sme_vl_expected); 1015 pass = false; 1016 } 1017 1018 if (!compare_buffer("saved Z", z_out, z_expected, 1019 __SVE_ZREGS_SIZE(vq))) 1020 pass = false; 1021 1022 if (!compare_buffer("saved P", p_out, p_expected, 1023 __SVE_PREGS_SIZE(vq))) 1024 pass = false; 1025 1026 if (!compare_buffer("saved FFR", ffr_out, ffr_expected, 1027 __SVE_PREG_SIZE(vq))) 1028 pass = false; 1029 1030 if (!compare_buffer("saved ZA", za_out, za_expected, 1031 ZA_PT_ZA_SIZE(sme_vq))) 1032 pass = false; 1033 1034 if (!compare_buffer("saved ZT", zt_out, zt_expected, ZT_SIG_REG_BYTES)) 1035 pass = false; 1036 1037 if (fpmr_out != fpmr_expected) { 1038 ksft_print_msg("Mismatch in saved FPMR: %lx != %lx\n", 1039 fpmr_out, fpmr_expected); 1040 pass = false; 1041 } 1042 1043 return pass; 1044 } 1045 1046 static bool sve_sme_same(struct test_config *config) 1047 { 1048 if (config->sve_vl_in != config->sve_vl_expected) 1049 return false; 1050 1051 if (config->sme_vl_in != config->sme_vl_expected) 1052 return false; 1053 1054 if (config->svcr_in != config->svcr_expected) 1055 return false; 1056 1057 return true; 1058 } 1059 1060 static bool sve_write_supported(struct test_config *config) 1061 { 1062 if (!sve_supported() && !sme_supported()) 1063 return false; 1064 1065 if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA)) 1066 return false; 1067 1068 if (config->svcr_expected & SVCR_SM) { 1069 if (config->sve_vl_in != config->sve_vl_expected) { 1070 return false; 1071 } 1072 1073 /* Changing the SME VL disables ZA */ 1074 if ((config->svcr_expected & SVCR_ZA) && 1075 (config->sme_vl_in != config->sme_vl_expected)) { 1076 return false; 1077 } 1078 } else { 1079 if (config->sme_vl_in != config->sme_vl_expected) { 1080 return false; 1081 } 1082 1083 if (!sve_supported()) 1084 return false; 1085 } 1086 1087 return true; 1088 } 1089 1090 static bool sve_write_fpsimd_supported(struct test_config *config) 1091 { 1092 if (!sve_supported() && !sme_supported()) 1093 return false; 1094 1095 if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA)) 1096 return false; 1097 1098 if (config->svcr_expected & SVCR_SM) 1099 return false; 1100 1101 if (config->sme_vl_in != config->sme_vl_expected) 1102 return false; 1103 1104 return true; 1105 } 1106 1107 static void fpsimd_write_expected(struct test_config *config) 1108 { 1109 int vl; 1110 1111 fill_random(&v_expected, sizeof(v_expected)); 1112 1113 /* The SVE registers are flushed by a FPSIMD write */ 1114 vl = vl_expected(config); 1115 1116 memset(z_expected, 0, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl))); 1117 memset(p_expected, 0, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl))); 1118 memset(ffr_expected, 0, __SVE_PREG_SIZE(__sve_vq_from_vl(vl))); 1119 1120 fpsimd_to_sve(v_expected, z_expected, vl); 1121 } 1122 1123 static void fpsimd_write(pid_t child, struct test_config *test_config) 1124 { 1125 struct user_fpsimd_state fpsimd; 1126 struct iovec iov; 1127 int ret; 1128 1129 memset(&fpsimd, 0, sizeof(fpsimd)); 1130 memcpy(&fpsimd.vregs, v_expected, sizeof(v_expected)); 1131 1132 iov.iov_base = &fpsimd; 1133 iov.iov_len = sizeof(fpsimd); 1134 ret = ptrace(PTRACE_SETREGSET, child, NT_PRFPREG, &iov); 1135 if (ret == -1) 1136 ksft_print_msg("FPSIMD set failed: (%s) %d\n", 1137 strerror(errno), errno); 1138 } 1139 1140 static bool fpmr_write_supported(struct test_config *config) 1141 { 1142 if (!fpmr_supported()) 1143 return false; 1144 1145 if (!sve_sme_same(config)) 1146 return false; 1147 1148 return true; 1149 } 1150 1151 static void fpmr_write_expected(struct test_config *config) 1152 { 1153 fill_random(&fpmr_expected, sizeof(fpmr_expected)); 1154 fpmr_expected &= FPMR_SAFE_BITS; 1155 } 1156 1157 static void fpmr_write(pid_t child, struct test_config *config) 1158 { 1159 struct iovec iov; 1160 int ret; 1161 1162 iov.iov_len = sizeof(fpmr_expected); 1163 iov.iov_base = &fpmr_expected; 1164 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_FPMR, &iov); 1165 if (ret != 0) 1166 ksft_print_msg("Failed to write FPMR: %s (%d)\n", 1167 strerror(errno), errno); 1168 } 1169 1170 static void sve_write_expected(struct test_config *config) 1171 { 1172 int vl = vl_expected(config); 1173 int sme_vq = __sve_vq_from_vl(config->sme_vl_expected); 1174 1175 if (!vl) 1176 return; 1177 1178 fill_random(z_expected, __SVE_ZREGS_SIZE(__sve_vq_from_vl(vl))); 1179 fill_random(p_expected, __SVE_PREGS_SIZE(__sve_vq_from_vl(vl))); 1180 1181 if ((svcr_expected & SVCR_SM) && !fa64_supported()) 1182 memset(ffr_expected, 0, __SVE_PREG_SIZE(sme_vq)); 1183 else 1184 fill_random_ffr(ffr_expected, __sve_vq_from_vl(vl)); 1185 1186 /* Share the low bits of Z with V */ 1187 fill_random(&v_expected, sizeof(v_expected)); 1188 fpsimd_to_sve(v_expected, z_expected, vl); 1189 1190 if (config->sme_vl_in != config->sme_vl_expected) { 1191 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq)); 1192 memset(zt_expected, 0, sizeof(zt_expected)); 1193 } 1194 } 1195 1196 static void sve_write_sve(pid_t child, struct test_config *config) 1197 { 1198 struct user_sve_header *sve; 1199 struct iovec iov; 1200 int ret, vl, vq, regset; 1201 1202 vl = vl_expected(config); 1203 vq = __sve_vq_from_vl(vl); 1204 1205 if (!vl) 1206 return; 1207 1208 iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_SVE); 1209 iov.iov_base = malloc(iov.iov_len); 1210 if (!iov.iov_base) { 1211 ksft_print_msg("Failed allocating %lu byte SVE write buffer\n", 1212 iov.iov_len); 1213 return; 1214 } 1215 memset(iov.iov_base, 0, iov.iov_len); 1216 1217 sve = iov.iov_base; 1218 sve->size = iov.iov_len; 1219 sve->flags = SVE_PT_REGS_SVE; 1220 sve->vl = vl; 1221 1222 memcpy(iov.iov_base + SVE_PT_SVE_ZREG_OFFSET(vq, 0), 1223 z_expected, SVE_PT_SVE_ZREGS_SIZE(vq)); 1224 memcpy(iov.iov_base + SVE_PT_SVE_PREG_OFFSET(vq, 0), 1225 p_expected, SVE_PT_SVE_PREGS_SIZE(vq)); 1226 memcpy(iov.iov_base + SVE_PT_SVE_FFR_OFFSET(vq), 1227 ffr_expected, SVE_PT_SVE_PREG_SIZE(vq)); 1228 1229 if (svcr_expected & SVCR_SM) 1230 regset = NT_ARM_SSVE; 1231 else 1232 regset = NT_ARM_SVE; 1233 1234 ret = ptrace(PTRACE_SETREGSET, child, regset, &iov); 1235 if (ret != 0) 1236 ksft_print_msg("Failed to write SVE: %s (%d)\n", 1237 strerror(errno), errno); 1238 1239 free(iov.iov_base); 1240 } 1241 1242 static void sve_write_fpsimd(pid_t child, struct test_config *config) 1243 { 1244 struct user_sve_header *sve; 1245 struct user_fpsimd_state *fpsimd; 1246 struct iovec iov; 1247 int ret, vl, vq; 1248 1249 vl = vl_expected(config); 1250 vq = __sve_vq_from_vl(vl); 1251 1252 iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_FPSIMD); 1253 iov.iov_base = malloc(iov.iov_len); 1254 if (!iov.iov_base) { 1255 ksft_print_msg("Failed allocating %lu byte SVE write buffer\n", 1256 iov.iov_len); 1257 return; 1258 } 1259 memset(iov.iov_base, 0, iov.iov_len); 1260 1261 sve = iov.iov_base; 1262 sve->size = iov.iov_len; 1263 sve->flags = SVE_PT_REGS_FPSIMD; 1264 sve->vl = vl; 1265 1266 fpsimd = iov.iov_base + SVE_PT_REGS_OFFSET; 1267 memcpy(&fpsimd->vregs, v_expected, sizeof(v_expected)); 1268 1269 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_SVE, &iov); 1270 if (ret != 0) 1271 ksft_print_msg("Failed to write SVE: %s (%d)\n", 1272 strerror(errno), errno); 1273 1274 free(iov.iov_base); 1275 } 1276 1277 static bool za_write_supported(struct test_config *config) 1278 { 1279 if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM)) 1280 return false; 1281 1282 return true; 1283 } 1284 1285 static void za_write_expected(struct test_config *config) 1286 { 1287 int sme_vq, sve_vq; 1288 1289 sme_vq = __sve_vq_from_vl(config->sme_vl_expected); 1290 1291 if (config->svcr_expected & SVCR_ZA) { 1292 fill_random(za_expected, ZA_PT_ZA_SIZE(sme_vq)); 1293 } else { 1294 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq)); 1295 memset(zt_expected, 0, sizeof(zt_expected)); 1296 } 1297 1298 /* Changing the SME VL flushes ZT, SVE state */ 1299 if (config->sme_vl_in != config->sme_vl_expected) { 1300 sve_vq = __sve_vq_from_vl(vl_expected(config)); 1301 memset(z_expected, 0, __SVE_ZREGS_SIZE(sve_vq)); 1302 memset(p_expected, 0, __SVE_PREGS_SIZE(sve_vq)); 1303 memset(ffr_expected, 0, __SVE_PREG_SIZE(sve_vq)); 1304 memset(zt_expected, 0, sizeof(zt_expected)); 1305 1306 fpsimd_to_sve(v_expected, z_expected, vl_expected(config)); 1307 } 1308 } 1309 1310 static void za_write(pid_t child, struct test_config *config) 1311 { 1312 struct user_za_header *za; 1313 struct iovec iov; 1314 int ret, vq; 1315 1316 vq = __sve_vq_from_vl(config->sme_vl_expected); 1317 1318 if (config->svcr_expected & SVCR_ZA) 1319 iov.iov_len = ZA_PT_SIZE(vq); 1320 else 1321 iov.iov_len = sizeof(*za); 1322 iov.iov_base = malloc(iov.iov_len); 1323 if (!iov.iov_base) { 1324 ksft_print_msg("Failed allocating %lu byte ZA write buffer\n", 1325 iov.iov_len); 1326 return; 1327 } 1328 memset(iov.iov_base, 0, iov.iov_len); 1329 1330 za = iov.iov_base; 1331 za->size = iov.iov_len; 1332 za->vl = config->sme_vl_expected; 1333 if (config->svcr_expected & SVCR_ZA) 1334 memcpy(iov.iov_base + ZA_PT_ZA_OFFSET, za_expected, 1335 ZA_PT_ZA_SIZE(vq)); 1336 1337 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZA, &iov); 1338 if (ret != 0) 1339 ksft_print_msg("Failed to write ZA: %s (%d)\n", 1340 strerror(errno), errno); 1341 1342 free(iov.iov_base); 1343 } 1344 1345 static bool zt_write_supported(struct test_config *config) 1346 { 1347 if (!sme2_supported()) 1348 return false; 1349 if (config->sme_vl_in != config->sme_vl_expected) 1350 return false; 1351 if (!(config->svcr_expected & SVCR_ZA)) 1352 return false; 1353 if ((config->svcr_in & SVCR_SM) != (config->svcr_expected & SVCR_SM)) 1354 return false; 1355 1356 return true; 1357 } 1358 1359 static void zt_write_expected(struct test_config *config) 1360 { 1361 int sme_vq; 1362 1363 sme_vq = __sve_vq_from_vl(config->sme_vl_expected); 1364 1365 if (config->svcr_expected & SVCR_ZA) { 1366 fill_random(zt_expected, sizeof(zt_expected)); 1367 } else { 1368 memset(za_expected, 0, ZA_PT_ZA_SIZE(sme_vq)); 1369 memset(zt_expected, 0, sizeof(zt_expected)); 1370 } 1371 } 1372 1373 static void zt_write(pid_t child, struct test_config *config) 1374 { 1375 struct iovec iov; 1376 int ret; 1377 1378 iov.iov_len = ZT_SIG_REG_BYTES; 1379 iov.iov_base = zt_expected; 1380 ret = ptrace(PTRACE_SETREGSET, child, NT_ARM_ZT, &iov); 1381 if (ret != 0) 1382 ksft_print_msg("Failed to write ZT: %s (%d)\n", 1383 strerror(errno), errno); 1384 } 1385 1386 /* Actually run a test */ 1387 static void run_test(struct test_definition *test, struct test_config *config) 1388 { 1389 pid_t child; 1390 char name[1024]; 1391 bool pass; 1392 1393 if (sve_supported() && sme_supported()) 1394 snprintf(name, sizeof(name), "%s, SVE %d->%d, SME %d/%x->%d/%x", 1395 test->name, 1396 config->sve_vl_in, config->sve_vl_expected, 1397 config->sme_vl_in, config->svcr_in, 1398 config->sme_vl_expected, config->svcr_expected); 1399 else if (sve_supported()) 1400 snprintf(name, sizeof(name), "%s, SVE %d->%d", test->name, 1401 config->sve_vl_in, config->sve_vl_expected); 1402 else if (sme_supported()) 1403 snprintf(name, sizeof(name), "%s, SME %d/%x->%d/%x", 1404 test->name, 1405 config->sme_vl_in, config->svcr_in, 1406 config->sme_vl_expected, config->svcr_expected); 1407 else 1408 snprintf(name, sizeof(name), "%s", test->name); 1409 1410 if (test->supported && !test->supported(config)) { 1411 ksft_test_result_skip("%s\n", name); 1412 return; 1413 } 1414 1415 set_initial_values(config); 1416 1417 if (test->set_expected_values) 1418 test->set_expected_values(config); 1419 1420 child = fork(); 1421 if (child < 0) 1422 ksft_exit_fail_msg("fork() failed: %s (%d)\n", 1423 strerror(errno), errno); 1424 /* run_child() never returns */ 1425 if (child == 0) 1426 run_child(config); 1427 1428 pass = run_parent(child, test, config); 1429 if (!check_memory_values(config)) 1430 pass = false; 1431 1432 ksft_test_result(pass, "%s\n", name); 1433 } 1434 1435 static void run_tests(struct test_definition defs[], int count, 1436 struct test_config *config) 1437 { 1438 int i; 1439 1440 for (i = 0; i < count; i++) 1441 run_test(&defs[i], config); 1442 } 1443 1444 static struct test_definition base_test_defs[] = { 1445 { 1446 .name = "No writes", 1447 .supported = sve_sme_same, 1448 }, 1449 { 1450 .name = "FPSIMD write", 1451 .supported = sve_sme_same, 1452 .set_expected_values = fpsimd_write_expected, 1453 .modify_values = fpsimd_write, 1454 }, 1455 { 1456 .name = "FPMR write", 1457 .supported = fpmr_write_supported, 1458 .set_expected_values = fpmr_write_expected, 1459 .modify_values = fpmr_write, 1460 }, 1461 }; 1462 1463 static struct test_definition sve_test_defs[] = { 1464 { 1465 .name = "SVE write", 1466 .supported = sve_write_supported, 1467 .set_expected_values = sve_write_expected, 1468 .modify_values = sve_write_sve, 1469 }, 1470 { 1471 .name = "SVE write FPSIMD format", 1472 .supported = sve_write_fpsimd_supported, 1473 .set_expected_values = fpsimd_write_expected, 1474 .modify_values = sve_write_fpsimd, 1475 }, 1476 }; 1477 1478 static struct test_definition za_test_defs[] = { 1479 { 1480 .name = "ZA write", 1481 .supported = za_write_supported, 1482 .set_expected_values = za_write_expected, 1483 .modify_values = za_write, 1484 }, 1485 }; 1486 1487 static struct test_definition zt_test_defs[] = { 1488 { 1489 .name = "ZT write", 1490 .supported = zt_write_supported, 1491 .set_expected_values = zt_write_expected, 1492 .modify_values = zt_write, 1493 }, 1494 }; 1495 1496 static int sve_vls[MAX_NUM_VLS], sme_vls[MAX_NUM_VLS]; 1497 static int sve_vl_count, sme_vl_count; 1498 1499 static void probe_vls(const char *name, int vls[], int *vl_count, int set_vl) 1500 { 1501 unsigned int vq; 1502 int vl; 1503 1504 *vl_count = 0; 1505 1506 for (vq = ARCH_VQ_MAX; vq > 0; vq /= 2) { 1507 vl = prctl(set_vl, vq * 16); 1508 if (vl == -1) 1509 ksft_exit_fail_msg("SET_VL failed: %s (%d)\n", 1510 strerror(errno), errno); 1511 1512 vl &= PR_SVE_VL_LEN_MASK; 1513 1514 if (*vl_count && (vl == vls[*vl_count - 1])) 1515 break; 1516 1517 vq = sve_vq_from_vl(vl); 1518 1519 vls[*vl_count] = vl; 1520 *vl_count += 1; 1521 } 1522 1523 if (*vl_count > 2) { 1524 /* Just use the minimum and maximum */ 1525 vls[1] = vls[*vl_count - 1]; 1526 ksft_print_msg("%d %s VLs, using %d and %d\n", 1527 *vl_count, name, vls[0], vls[1]); 1528 *vl_count = 2; 1529 } else { 1530 ksft_print_msg("%d %s VLs\n", *vl_count, name); 1531 } 1532 } 1533 1534 static struct { 1535 int svcr_in, svcr_expected; 1536 } svcr_combinations[] = { 1537 { .svcr_in = 0, .svcr_expected = 0, }, 1538 { .svcr_in = 0, .svcr_expected = SVCR_SM, }, 1539 { .svcr_in = 0, .svcr_expected = SVCR_ZA, }, 1540 /* Can't enable both SM and ZA with a single ptrace write */ 1541 1542 { .svcr_in = SVCR_SM, .svcr_expected = 0, }, 1543 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM, }, 1544 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_ZA, }, 1545 { .svcr_in = SVCR_SM, .svcr_expected = SVCR_SM | SVCR_ZA, }, 1546 1547 { .svcr_in = SVCR_ZA, .svcr_expected = 0, }, 1548 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM, }, 1549 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_ZA, }, 1550 { .svcr_in = SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, }, 1551 1552 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = 0, }, 1553 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM, }, 1554 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_ZA, }, 1555 { .svcr_in = SVCR_SM | SVCR_ZA, .svcr_expected = SVCR_SM | SVCR_ZA, }, 1556 }; 1557 1558 static void run_sve_tests(void) 1559 { 1560 struct test_config test_config; 1561 int i, j; 1562 1563 if (!sve_supported()) 1564 return; 1565 1566 test_config.sme_vl_in = sme_vls[0]; 1567 test_config.sme_vl_expected = sme_vls[0]; 1568 test_config.svcr_in = 0; 1569 test_config.svcr_expected = 0; 1570 1571 for (i = 0; i < sve_vl_count; i++) { 1572 test_config.sve_vl_in = sve_vls[i]; 1573 1574 for (j = 0; j < sve_vl_count; j++) { 1575 test_config.sve_vl_expected = sve_vls[j]; 1576 1577 run_tests(base_test_defs, 1578 ARRAY_SIZE(base_test_defs), 1579 &test_config); 1580 if (sve_supported()) 1581 run_tests(sve_test_defs, 1582 ARRAY_SIZE(sve_test_defs), 1583 &test_config); 1584 } 1585 } 1586 } 1587 1588 static void run_sme_tests(void) 1589 { 1590 struct test_config test_config; 1591 int i, j, k; 1592 1593 if (!sme_supported()) 1594 return; 1595 1596 test_config.sve_vl_in = sve_vls[0]; 1597 test_config.sve_vl_expected = sve_vls[0]; 1598 1599 /* 1600 * Every SME VL/SVCR combination 1601 */ 1602 for (i = 0; i < sme_vl_count; i++) { 1603 test_config.sme_vl_in = sme_vls[i]; 1604 1605 for (j = 0; j < sme_vl_count; j++) { 1606 test_config.sme_vl_expected = sme_vls[j]; 1607 1608 for (k = 0; k < ARRAY_SIZE(svcr_combinations); k++) { 1609 test_config.svcr_in = svcr_combinations[k].svcr_in; 1610 test_config.svcr_expected = svcr_combinations[k].svcr_expected; 1611 1612 run_tests(base_test_defs, 1613 ARRAY_SIZE(base_test_defs), 1614 &test_config); 1615 run_tests(sve_test_defs, 1616 ARRAY_SIZE(sve_test_defs), 1617 &test_config); 1618 run_tests(za_test_defs, 1619 ARRAY_SIZE(za_test_defs), 1620 &test_config); 1621 1622 if (sme2_supported()) 1623 run_tests(zt_test_defs, 1624 ARRAY_SIZE(zt_test_defs), 1625 &test_config); 1626 } 1627 } 1628 } 1629 } 1630 1631 int main(void) 1632 { 1633 struct test_config test_config; 1634 struct sigaction sa; 1635 int tests, ret, tmp; 1636 1637 srandom(getpid()); 1638 1639 ksft_print_header(); 1640 1641 if (sve_supported()) { 1642 probe_vls("SVE", sve_vls, &sve_vl_count, PR_SVE_SET_VL); 1643 1644 tests = ARRAY_SIZE(base_test_defs) + 1645 ARRAY_SIZE(sve_test_defs); 1646 tests *= sve_vl_count * sve_vl_count; 1647 } else { 1648 /* Only run the FPSIMD tests */ 1649 sve_vl_count = 1; 1650 tests = ARRAY_SIZE(base_test_defs); 1651 } 1652 1653 if (sme_supported()) { 1654 probe_vls("SME", sme_vls, &sme_vl_count, PR_SME_SET_VL); 1655 1656 tmp = ARRAY_SIZE(base_test_defs) + ARRAY_SIZE(sve_test_defs) 1657 + ARRAY_SIZE(za_test_defs); 1658 1659 if (sme2_supported()) 1660 tmp += ARRAY_SIZE(zt_test_defs); 1661 1662 tmp *= sme_vl_count * sme_vl_count; 1663 tmp *= ARRAY_SIZE(svcr_combinations); 1664 tests += tmp; 1665 } else { 1666 sme_vl_count = 1; 1667 } 1668 1669 if (sme2_supported()) 1670 ksft_print_msg("SME2 supported\n"); 1671 1672 if (fa64_supported()) 1673 ksft_print_msg("FA64 supported\n"); 1674 1675 if (fpmr_supported()) 1676 ksft_print_msg("FPMR supported\n"); 1677 1678 ksft_set_plan(tests); 1679 1680 /* Get signal handers ready before we start any children */ 1681 memset(&sa, 0, sizeof(sa)); 1682 sa.sa_sigaction = handle_alarm; 1683 sa.sa_flags = SA_RESTART | SA_SIGINFO; 1684 sigemptyset(&sa.sa_mask); 1685 ret = sigaction(SIGALRM, &sa, NULL); 1686 if (ret < 0) 1687 ksft_print_msg("Failed to install SIGALRM handler: %s (%d)\n", 1688 strerror(errno), errno); 1689 1690 /* 1691 * Run the test set if there is no SVE or SME, with those we 1692 * have to pick a VL for each run. 1693 */ 1694 if (!sve_supported() && !sme_supported()) { 1695 test_config.sve_vl_in = 0; 1696 test_config.sve_vl_expected = 0; 1697 test_config.sme_vl_in = 0; 1698 test_config.sme_vl_expected = 0; 1699 test_config.svcr_in = 0; 1700 test_config.svcr_expected = 0; 1701 1702 run_tests(base_test_defs, ARRAY_SIZE(base_test_defs), 1703 &test_config); 1704 } 1705 1706 run_sve_tests(); 1707 run_sme_tests(); 1708 1709 ksft_finished(); 1710 } 1711