1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 ARM Limited 4 * 5 * Verify that the streaming SVE register context in signal frames is 6 * set up as 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_SME_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_ssve_regs(void) 50 { 51 /* smstart sm; real data is TODO */ 52 asm volatile(".inst 0xd503437f" : : : ); 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 sve_context *ssve; 61 int ret; 62 63 fprintf(stderr, "Testing VL %d\n", vl); 64 65 ret = prctl(PR_SME_SET_VL, vl); 66 if (ret != vl) { 67 fprintf(stderr, "Failed to set VL, got %d\n", ret); 68 return 1; 69 } 70 71 /* 72 * Get a signal context which should have a SVE frame and registers 73 * in it. 74 */ 75 setup_ssve_regs(); 76 if (!get_current_context(td, &sf.uc)) 77 return 1; 78 79 resv_sz = GET_SF_RESV_SIZE(sf); 80 head = get_header(head, SVE_MAGIC, resv_sz, &offset); 81 if (!head) { 82 fprintf(stderr, "No SVE context\n"); 83 return 1; 84 } 85 86 ssve = (struct sve_context *)head; 87 if (ssve->vl != vl) { 88 fprintf(stderr, "Got VL %d, expected %d\n", ssve->vl, vl); 89 return 1; 90 } 91 92 /* The actual size validation is done in get_current_context() */ 93 fprintf(stderr, "Got expected size %u and VL %d\n", 94 head->size, ssve->vl); 95 96 return 0; 97 } 98 99 static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 100 { 101 int i; 102 103 for (i = 0; i < nvls; i++) { 104 /* 105 * TODO: the signal test helpers can't currently cope 106 * with signal frames bigger than struct sigcontext, 107 * skip VLs that will trigger that. 108 */ 109 if (vls[i] > 64) { 110 printf("Skipping VL %u due to stack size\n", vls[i]); 111 continue; 112 } 113 114 if (do_one_sme_vl(td, si, uc, vls[i])) 115 return 1; 116 } 117 118 td->pass = 1; 119 120 return 0; 121 } 122 123 struct tdescr tde = { 124 .name = "Streaming SVE registers", 125 .descr = "Check that we get the right Streaming SVE registers reported", 126 /* 127 * We shouldn't require FA64 but things like memset() used in the 128 * helpers might use unsupported instructions so for now disable 129 * the test unless we've got the full instruction set. 130 */ 131 .feats_required = FEAT_SME | FEAT_SME_FA64, 132 .timeout = 3, 133 .init = sme_get_vls, 134 .run = sme_regs, 135 }; 136