Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kselftest/arm64: Add SME2 coverage to syscall-abi

Verify that ZT0 is preserved over syscalls when it is present and
PSTATE.ZA is set.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20221208-arm64-sme2-v4-19-f2fa0aef982f@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Brown and committed by
Catalin Marinas
49886aa9 18f8729a

+80 -3
+42 -1
tools/testing/selftests/arm64/abi/syscall-abi-asm.S
··· 23 23 24 24 .arch_extension sve 25 25 26 + #define ID_AA64SMFR0_EL1_SMEver_SHIFT 56 27 + #define ID_AA64SMFR0_EL1_SMEver_WIDTH 4 28 + 26 29 /* 27 30 * LDR (vector to ZA array): 28 31 * LDR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL] ··· 48 45 | ((\offset) & 7) 49 46 .endm 50 47 48 + /* 49 + * LDR (ZT0) 50 + * 51 + * LDR ZT0, nx 52 + */ 53 + .macro _ldr_zt nx 54 + .inst 0xe11f8000 \ 55 + | (((\nx) & 0x1f) << 5) 56 + .endm 57 + 58 + /* 59 + * STR (ZT0) 60 + * 61 + * STR ZT0, nx 62 + */ 63 + .macro _str_zt nx 64 + .inst 0xe13f8000 \ 65 + | (((\nx) & 0x1f) << 5) 66 + .endm 67 + 51 68 .globl do_syscall 52 69 do_syscall: 53 70 // Store callee saved registers x19-x29 (80 bytes) plus x0 and x1 ··· 87 64 msr S3_3_C4_C2_2, x2 88 65 1: 89 66 90 - // Load ZA if it's enabled - uses x12 as scratch due to SME LDR 67 + // Load ZA and ZT0 if enabled - uses x12 as scratch due to SME LDR 91 68 tbz x2, #SVCR_ZA_SHIFT, 1f 92 69 mov w12, #0 93 70 ldr x2, =za_in ··· 96 73 add x12, x12, #1 97 74 cmp x1, x12 98 75 bne 2b 76 + 77 + // ZT0 78 + mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1 79 + ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \ 80 + #ID_AA64SMFR0_EL1_SMEver_WIDTH 81 + cbz x2, 1f 82 + adrp x2, zt_in 83 + add x2, x2, :lo12:zt_in 84 + _ldr_zt 2 99 85 1: 100 86 101 87 // Load GPRs x8-x28, and save our SP/FP for later comparison ··· 267 235 add x12, x12, #1 268 236 cmp x1, x12 269 237 bne 2b 238 + 239 + // ZT0 240 + mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1 241 + ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \ 242 + #ID_AA64SMFR0_EL1_SMEver_WIDTH 243 + cbz x2, 1f 244 + adrp x2, zt_out 245 + add x2, x2, :lo12:zt_out 246 + _str_zt 2 270 247 1: 271 248 272 249 // Save the SVE state if we have some
+38 -2
tools/testing/selftests/arm64/abi/syscall-abi.c
··· 311 311 return errors; 312 312 } 313 313 314 + uint8_t zt_in[ZT_SIG_REG_BYTES] __attribute__((aligned(16))); 315 + uint8_t zt_out[ZT_SIG_REG_BYTES] __attribute__((aligned(16))); 316 + 317 + static void setup_zt(struct syscall_cfg *cfg, int sve_vl, int sme_vl, 318 + uint64_t svcr) 319 + { 320 + fill_random(zt_in, sizeof(zt_in)); 321 + memset(zt_out, 0, sizeof(zt_out)); 322 + } 323 + 324 + static int check_zt(struct syscall_cfg *cfg, int sve_vl, int sme_vl, 325 + uint64_t svcr) 326 + { 327 + int errors = 0; 328 + 329 + if (!(getauxval(AT_HWCAP2) & HWCAP2_SME2)) 330 + return 0; 331 + 332 + if (!(svcr & SVCR_ZA_MASK)) 333 + return 0; 334 + 335 + if (memcmp(zt_in, zt_out, sizeof(zt_in)) != 0) { 336 + ksft_print_msg("SME VL %d ZT does not match\n", sme_vl); 337 + errors++; 338 + } 339 + 340 + return errors; 341 + } 342 + 314 343 typedef void (*setup_fn)(struct syscall_cfg *cfg, int sve_vl, int sme_vl, 315 344 uint64_t svcr); 316 345 typedef int (*check_fn)(struct syscall_cfg *cfg, int sve_vl, int sme_vl, ··· 363 334 { setup_ffr, check_ffr }, 364 335 { setup_svcr, check_svcr }, 365 336 { setup_za, check_za }, 337 + { setup_zt, check_zt }, 366 338 }; 367 339 368 340 static bool do_test(struct syscall_cfg *cfg, int sve_vl, int sme_vl, ··· 504 474 { 505 475 int i; 506 476 int tests = 1; /* FPSIMD */ 477 + int sme_ver; 507 478 508 479 srandom(getpid()); 509 480 ··· 513 482 tests += (sve_count_vls() * sme_count_vls()) * 3; 514 483 ksft_set_plan(ARRAY_SIZE(syscalls) * tests); 515 484 485 + if (getauxval(AT_HWCAP2) & HWCAP2_SME2) 486 + sme_ver = 2; 487 + else 488 + sme_ver = 1; 489 + 516 490 if (getauxval(AT_HWCAP2) & HWCAP2_SME_FA64) 517 - ksft_print_msg("SME with FA64\n"); 491 + ksft_print_msg("SME%d with FA64\n", sme_ver); 518 492 else if (getauxval(AT_HWCAP2) & HWCAP2_SME) 519 - ksft_print_msg("SME without FA64\n"); 493 + ksft_print_msg("SME%d without FA64\n", sme_ver); 520 494 521 495 for (i = 0; i < ARRAY_SIZE(syscalls); i++) 522 496 test_one_syscall(&syscalls[i]);