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

kselftest/arm64: Verify simultaneous SSVE and ZA context generation

Add a test that generates SSVE and ZA context in a single signal frame to
ensure that nothing is going wrong in that case for any reason.

Signed-off-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20230117-arm64-test-ssve-za-v1-2-203c00150154@kernel.org
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Brown and committed by
Catalin Marinas
bc69da5f f76cb73a

+162
+162
tools/testing/selftests/arm64/signal/testcases/ssve_za_regs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2021 ARM Limited 4 + * 5 + * Verify that both the streaming SVE and ZA register context in 6 + * signal frames is set up as expected when enabled simultaneously. 7 + */ 8 + 9 + #include <signal.h> 10 + #include <ucontext.h> 11 + #include <sys/prctl.h> 12 + 13 + #include "test_signals_utils.h" 14 + #include "testcases.h" 15 + 16 + static union { 17 + ucontext_t uc; 18 + char buf[1024 * 128]; 19 + } context; 20 + static unsigned int vls[SVE_VQ_MAX]; 21 + unsigned int nvls = 0; 22 + 23 + static bool sme_get_vls(struct tdescr *td) 24 + { 25 + int vq, vl; 26 + 27 + /* 28 + * Enumerate up to SVE_VQ_MAX vector lengths 29 + */ 30 + for (vq = SVE_VQ_MAX; vq > 0; --vq) { 31 + vl = prctl(PR_SME_SET_VL, vq * 16); 32 + if (vl == -1) 33 + return false; 34 + 35 + vl &= PR_SME_VL_LEN_MASK; 36 + 37 + /* Skip missing VLs */ 38 + vq = sve_vq_from_vl(vl); 39 + 40 + vls[nvls++] = vl; 41 + } 42 + 43 + /* We need at least one VL */ 44 + if (nvls < 1) { 45 + fprintf(stderr, "Only %d VL supported\n", nvls); 46 + return false; 47 + } 48 + 49 + return true; 50 + } 51 + 52 + static void setup_regs(void) 53 + { 54 + /* smstart sm; real data is TODO */ 55 + asm volatile(".inst 0xd503437f" : : : ); 56 + 57 + /* smstart za; real data is TODO */ 58 + asm volatile(".inst 0xd503457f" : : : ); 59 + } 60 + 61 + static char zeros[ZA_SIG_REGS_SIZE(SVE_VQ_MAX)]; 62 + 63 + static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc, 64 + unsigned int vl) 65 + { 66 + size_t offset; 67 + struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context); 68 + struct _aarch64_ctx *regs; 69 + struct sve_context *ssve; 70 + struct za_context *za; 71 + int ret; 72 + 73 + fprintf(stderr, "Testing VL %d\n", vl); 74 + 75 + ret = prctl(PR_SME_SET_VL, vl); 76 + if (ret != vl) { 77 + fprintf(stderr, "Failed to set VL, got %d\n", ret); 78 + return 1; 79 + } 80 + 81 + /* 82 + * Get a signal context which should have the SVE and ZA 83 + * frames in it. 84 + */ 85 + setup_regs(); 86 + if (!get_current_context(td, &context.uc, sizeof(context))) 87 + return 1; 88 + 89 + regs = get_header(head, SVE_MAGIC, GET_BUF_RESV_SIZE(context), 90 + &offset); 91 + if (!regs) { 92 + fprintf(stderr, "No SVE context\n"); 93 + return 1; 94 + } 95 + 96 + ssve = (struct sve_context *)regs; 97 + if (ssve->vl != vl) { 98 + fprintf(stderr, "Got SSVE VL %d, expected %d\n", ssve->vl, vl); 99 + return 1; 100 + } 101 + 102 + if (!(ssve->flags & SVE_SIG_FLAG_SM)) { 103 + fprintf(stderr, "SVE_SIG_FLAG_SM not set in SVE record\n"); 104 + return 1; 105 + } 106 + 107 + fprintf(stderr, "Got expected SSVE size %u and VL %d\n", 108 + regs->size, ssve->vl); 109 + 110 + regs = get_header(head, ZA_MAGIC, GET_BUF_RESV_SIZE(context), 111 + &offset); 112 + if (!regs) { 113 + fprintf(stderr, "No ZA context\n"); 114 + return 1; 115 + } 116 + 117 + za = (struct za_context *)regs; 118 + if (za->vl != vl) { 119 + fprintf(stderr, "Got ZA VL %d, expected %d\n", za->vl, vl); 120 + return 1; 121 + } 122 + 123 + fprintf(stderr, "Got expected ZA size %u and VL %d\n", 124 + regs->size, za->vl); 125 + 126 + /* We didn't load any data into ZA so it should be all zeros */ 127 + if (memcmp(zeros, (char *)za + ZA_SIG_REGS_OFFSET, 128 + ZA_SIG_REGS_SIZE(sve_vq_from_vl(za->vl))) != 0) { 129 + fprintf(stderr, "ZA data invalid\n"); 130 + return 1; 131 + } 132 + 133 + return 0; 134 + } 135 + 136 + static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 137 + { 138 + int i; 139 + 140 + for (i = 0; i < nvls; i++) { 141 + if (do_one_sme_vl(td, si, uc, vls[i])) 142 + return 1; 143 + } 144 + 145 + td->pass = 1; 146 + 147 + return 0; 148 + } 149 + 150 + struct tdescr tde = { 151 + .name = "Streaming SVE registers", 152 + .descr = "Check that we get the right Streaming SVE registers reported", 153 + /* 154 + * We shouldn't require FA64 but things like memset() used in the 155 + * helpers might use unsupported instructions so for now disable 156 + * the test unless we've got the full instruction set. 157 + */ 158 + .feats_required = FEAT_SME | FEAT_SME_FA64, 159 + .timeout = 3, 160 + .init = sme_get_vls, 161 + .run = sme_regs, 162 + };