142 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2021 ARM Limited4 *5 * Verify that both the streaming SVE and ZA register context in6 * signal frames is set up as expected when enabled simultaneously.7 */8 9#include <kselftest.h>10#include <signal.h>11#include <ucontext.h>12#include <sys/prctl.h>13 14#include "test_signals_utils.h"15#include "sve_helpers.h"16#include "testcases.h"17 18static union {19 ucontext_t uc;20 char buf[1024 * 128];21} context;22 23static bool sme_get_vls(struct tdescr *td)24{25 int res = sve_fill_vls(VLS_USE_SME, 1);26 27 if (!res)28 return true;29 30 if (res == KSFT_SKIP)31 td->result = KSFT_SKIP;32 33 return false;34}35 36static void setup_regs(void)37{38 /* smstart sm; real data is TODO */39 asm volatile(".inst 0xd503437f" : : : );40 41 /* smstart za; real data is TODO */42 asm volatile(".inst 0xd503457f" : : : );43}44 45static char zeros[ZA_SIG_REGS_SIZE(SVE_VQ_MAX)];46 47static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,48 unsigned int vl)49{50 size_t offset;51 struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context);52 struct _aarch64_ctx *regs;53 struct sve_context *ssve;54 struct za_context *za;55 int ret;56 57 fprintf(stderr, "Testing VL %d\n", vl);58 59 ret = prctl(PR_SME_SET_VL, vl);60 if (ret != vl) {61 fprintf(stderr, "Failed to set VL, got %d\n", ret);62 return 1;63 }64 65 /*66 * Get a signal context which should have the SVE and ZA67 * frames in it.68 */69 setup_regs();70 if (!get_current_context(td, &context.uc, sizeof(context)))71 return 1;72 73 regs = get_header(head, SVE_MAGIC, GET_BUF_RESV_SIZE(context),74 &offset);75 if (!regs) {76 fprintf(stderr, "No SVE context\n");77 return 1;78 }79 80 ssve = (struct sve_context *)regs;81 if (ssve->vl != vl) {82 fprintf(stderr, "Got SSVE VL %d, expected %d\n", ssve->vl, vl);83 return 1;84 }85 86 if (!(ssve->flags & SVE_SIG_FLAG_SM)) {87 fprintf(stderr, "SVE_SIG_FLAG_SM not set in SVE record\n");88 return 1;89 }90 91 fprintf(stderr, "Got expected SSVE size %u and VL %d\n",92 regs->size, ssve->vl);93 94 regs = get_header(head, ZA_MAGIC, GET_BUF_RESV_SIZE(context),95 &offset);96 if (!regs) {97 fprintf(stderr, "No ZA context\n");98 return 1;99 }100 101 za = (struct za_context *)regs;102 if (za->vl != vl) {103 fprintf(stderr, "Got ZA VL %d, expected %d\n", za->vl, vl);104 return 1;105 }106 107 fprintf(stderr, "Got expected ZA size %u and VL %d\n",108 regs->size, za->vl);109 110 /* We didn't load any data into ZA so it should be all zeros */111 if (memcmp(zeros, (char *)za + ZA_SIG_REGS_OFFSET,112 ZA_SIG_REGS_SIZE(sve_vq_from_vl(za->vl))) != 0) {113 fprintf(stderr, "ZA data invalid\n");114 return 1;115 }116 117 return 0;118}119 120static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)121{122 int i;123 124 for (i = 0; i < nvls; i++) {125 if (do_one_sme_vl(td, si, uc, vls[i]))126 return 1;127 }128 129 td->pass = 1;130 131 return 0;132}133 134struct tdescr tde = {135 .name = "Streaming SVE registers",136 .descr = "Check that we get the right Streaming SVE registers reported",137 .feats_required = FEAT_SME,138 .timeout = 3,139 .init = sme_get_vls,140 .run = sme_regs,141};142