1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 ARM Limited 4 * 5 * Attempt to change the SVE vector length in a signal hander, this is not 6 * supported and is expected to segfault. 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 two VLs */ 41 if (nvls < 2) { 42 fprintf(stderr, "Only %d VL supported\n", nvls); 43 return false; 44 } 45 46 return true; 47 } 48 49 static int fake_sigreturn_sve_change_vl(struct tdescr *td, 50 siginfo_t *si, ucontext_t *uc) 51 { 52 size_t resv_sz, offset; 53 struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf); 54 struct sve_context *sve; 55 56 /* Get a signal context with a SVE frame in it */ 57 if (!get_current_context(td, &sf.uc)) 58 return 1; 59 60 resv_sz = GET_SF_RESV_SIZE(sf); 61 head = get_header(head, SVE_MAGIC, resv_sz, &offset); 62 if (!head) { 63 fprintf(stderr, "No SVE context\n"); 64 return 1; 65 } 66 67 if (head->size != sizeof(struct sve_context)) { 68 fprintf(stderr, "SVE register state active, skipping\n"); 69 return 1; 70 } 71 72 sve = (struct sve_context *)head; 73 74 /* No changes are supported; init left us at minimum VL so go to max */ 75 fprintf(stderr, "Attempting to change VL from %d to %d\n", 76 sve->vl, vls[0]); 77 sve->vl = vls[0]; 78 79 fake_sigreturn(&sf, sizeof(sf), 0); 80 81 return 1; 82 } 83 84 struct tdescr tde = { 85 .name = "FAKE_SIGRETURN_SVE_CHANGE", 86 .descr = "Attempt to change SVE VL", 87 .feats_required = FEAT_SVE, 88 .sig_ok = SIGSEGV, 89 .timeout = 3, 90 .init = sve_get_vls, 91 .run = fake_sigreturn_sve_change_vl, 92 }; 93