1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 ARM Limited 4 * 5 * Verify that the SVE 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 sve_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_SVE_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_sve_regs(void) 50 { 51 /* RDVL x16, #1 so we should have SVE regs; real data is TODO */ 52 asm volatile(".inst 0x04bf5030" : : : "x16" ); 53 } 54 55 static int do_one_sve_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 *sve; 61 62 fprintf(stderr, "Testing VL %d\n", vl); 63 64 if (prctl(PR_SVE_SET_VL, vl) == -1) { 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_sve_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, SVE_MAGIC, resv_sz, &offset); 79 if (!head) { 80 fprintf(stderr, "No SVE context\n"); 81 return 1; 82 } 83 84 sve = (struct sve_context *)head; 85 if (sve->vl != vl) { 86 fprintf(stderr, "Got VL %d, expected %d\n", sve->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, sve->vl); 93 94 return 0; 95 } 96 97 static int sve_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] > 64) 108 continue; 109 110 if (do_one_sve_vl(td, si, uc, vls[i])) 111 return 1; 112 } 113 114 td->pass = 1; 115 116 return 0; 117 } 118 119 struct tdescr tde = { 120 .name = "SVE registers", 121 .descr = "Check that we get the right SVE registers reported", 122 .feats_required = FEAT_SVE, 123 .timeout = 3, 124 .init = sve_get_vls, 125 .run = sve_regs, 126 }; 127