1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 ARM Limited 4 * 5 * Verify that the ZA register context in signal frames is set up as 6 * expected. 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 struct fake_sigframe sf; 17 static unsigned int vls[SVE_VQ_MAX]; 18 unsigned int nvls = 0; 19 20 static bool sme_get_vls(struct tdescr *td) 21 { 22 int vq, vl; 23 24 /* 25 * Enumerate up to SVE_VQ_MAX vector lengths 26 */ 27 for (vq = SVE_VQ_MAX; vq > 0; --vq) { 28 vl = prctl(PR_SVE_SET_VL, vq * 16); 29 if (vl == -1) 30 return false; 31 32 vl &= PR_SME_VL_LEN_MASK; 33 34 /* Skip missing VLs */ 35 vq = sve_vq_from_vl(vl); 36 37 vls[nvls++] = vl; 38 } 39 40 /* We need at least one VL */ 41 if (nvls < 1) { 42 fprintf(stderr, "Only %d VL supported\n", nvls); 43 return false; 44 } 45 46 return true; 47 } 48 49 static void setup_za_regs(void) 50 { 51 /* smstart za; real data is TODO */ 52 asm volatile(".inst 0xd503457f" : : : ); 53 } 54 55 static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc, 56 unsigned int vl) 57 { 58 size_t resv_sz, offset; 59 struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf); 60 struct za_context *za; 61 62 fprintf(stderr, "Testing VL %d\n", vl); 63 64 if (prctl(PR_SME_SET_VL, vl) != vl) { 65 fprintf(stderr, "Failed to set VL\n"); 66 return 1; 67 } 68 69 /* 70 * Get a signal context which should have a SVE frame and registers 71 * in it. 72 */ 73 setup_za_regs(); 74 if (!get_current_context(td, &sf.uc)) 75 return 1; 76 77 resv_sz = GET_SF_RESV_SIZE(sf); 78 head = get_header(head, ZA_MAGIC, resv_sz, &offset); 79 if (!head) { 80 fprintf(stderr, "No ZA context\n"); 81 return 1; 82 } 83 84 za = (struct za_context *)head; 85 if (za->vl != vl) { 86 fprintf(stderr, "Got VL %d, expected %d\n", za->vl, vl); 87 return 1; 88 } 89 90 /* The actual size validation is done in get_current_context() */ 91 fprintf(stderr, "Got expected size %u and VL %d\n", 92 head->size, za->vl); 93 94 return 0; 95 } 96 97 static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 98 { 99 int i; 100 101 for (i = 0; i < nvls; i++) { 102 /* 103 * TODO: the signal test helpers can't currently cope 104 * with signal frames bigger than struct sigcontext, 105 * skip VLs that will trigger that. 106 */ 107 if (vls[i] > 32) { 108 printf("Skipping VL %u due to stack size\n", vls[i]); 109 continue; 110 } 111 112 if (do_one_sme_vl(td, si, uc, vls[i])) 113 return 1; 114 } 115 116 td->pass = 1; 117 118 return 0; 119 } 120 121 struct tdescr tde = { 122 .name = "ZA register", 123 .descr = "Check that we get the right ZA registers reported", 124 .feats_required = FEAT_SME, 125 .timeout = 3, 126 .init = sme_get_vls, 127 .run = sme_regs, 128 }; 129