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 <kselftest.h> 10 #include <signal.h> 11 #include <ucontext.h> 12 #include <sys/prctl.h> 13 14 #include "test_signals_utils.h" 15 #include "testcases.h" 16 17 struct fake_sigframe sf; 18 static unsigned int vls[SVE_VQ_MAX]; 19 unsigned int nvls = 0; 20 21 static bool sve_get_vls(struct tdescr *td) 22 { 23 int vq, vl; 24 25 /* 26 * Enumerate up to SVE_VQ_MAX vector lengths 27 */ 28 for (vq = SVE_VQ_MAX; vq > 0; --vq) { 29 vl = prctl(PR_SVE_SET_VL, vq * 16); 30 if (vl == -1) 31 return false; 32 33 vl &= PR_SVE_VL_LEN_MASK; 34 35 /* Skip missing VLs */ 36 vq = sve_vq_from_vl(vl); 37 38 vls[nvls++] = vl; 39 } 40 41 /* We need at least two VLs */ 42 if (nvls < 2) { 43 fprintf(stderr, "Only %d VL supported\n", nvls); 44 td->result = KSFT_SKIP; 45 return false; 46 } 47 48 return true; 49 } 50 51 static int fake_sigreturn_sve_change_vl(struct tdescr *td, 52 siginfo_t *si, ucontext_t *uc) 53 { 54 size_t resv_sz, offset; 55 struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf); 56 struct sve_context *sve; 57 58 /* Get a signal context with a SVE frame in it */ 59 if (!get_current_context(td, &sf.uc)) 60 return 1; 61 62 resv_sz = GET_SF_RESV_SIZE(sf); 63 head = get_header(head, SVE_MAGIC, resv_sz, &offset); 64 if (!head) { 65 fprintf(stderr, "No SVE context\n"); 66 return 1; 67 } 68 69 if (head->size != sizeof(struct sve_context)) { 70 fprintf(stderr, "SVE register state active, skipping\n"); 71 return 1; 72 } 73 74 sve = (struct sve_context *)head; 75 76 /* No changes are supported; init left us at minimum VL so go to max */ 77 fprintf(stderr, "Attempting to change VL from %d to %d\n", 78 sve->vl, vls[0]); 79 sve->vl = vls[0]; 80 81 fake_sigreturn(&sf, sizeof(sf), 0); 82 83 return 1; 84 } 85 86 struct tdescr tde = { 87 .name = "FAKE_SIGRETURN_SVE_CHANGE", 88 .descr = "Attempt to change SVE VL", 89 .feats_required = FEAT_SVE, 90 .sig_ok = SIGSEGV, 91 .timeout = 3, 92 .init = sve_get_vls, 93 .run = fake_sigreturn_sve_change_vl, 94 }; 95