0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <signal.h>
0010 #include <ucontext.h>
0011 #include <sys/prctl.h>
0012
0013 #include "test_signals_utils.h"
0014 #include "testcases.h"
0015
0016 struct fake_sigframe sf;
0017 static unsigned int vls[SVE_VQ_MAX];
0018 unsigned int nvls = 0;
0019
0020 static bool sme_get_vls(struct tdescr *td)
0021 {
0022 int vq, vl;
0023
0024
0025
0026
0027 for (vq = SVE_VQ_MAX; vq > 0; --vq) {
0028 vl = prctl(PR_SME_SET_VL, vq * 16);
0029 if (vl == -1)
0030 return false;
0031
0032 vl &= PR_SME_VL_LEN_MASK;
0033
0034
0035 vq = sve_vq_from_vl(vl);
0036
0037 vls[nvls++] = vl;
0038 }
0039
0040
0041 if (nvls < 1) {
0042 fprintf(stderr, "Only %d VL supported\n", nvls);
0043 return false;
0044 }
0045
0046 return true;
0047 }
0048
0049 static void setup_ssve_regs(void)
0050 {
0051
0052 asm volatile(".inst 0xd503437f" : : : );
0053 }
0054
0055 static int do_one_sme_vl(struct tdescr *td, siginfo_t *si, ucontext_t *uc,
0056 unsigned int vl)
0057 {
0058 size_t resv_sz, offset;
0059 struct _aarch64_ctx *head = GET_SF_RESV_HEAD(sf);
0060 struct sve_context *ssve;
0061 int ret;
0062
0063 fprintf(stderr, "Testing VL %d\n", vl);
0064
0065 ret = prctl(PR_SME_SET_VL, vl);
0066 if (ret != vl) {
0067 fprintf(stderr, "Failed to set VL, got %d\n", ret);
0068 return 1;
0069 }
0070
0071
0072
0073
0074
0075 setup_ssve_regs();
0076 if (!get_current_context(td, &sf.uc))
0077 return 1;
0078
0079 resv_sz = GET_SF_RESV_SIZE(sf);
0080 head = get_header(head, SVE_MAGIC, resv_sz, &offset);
0081 if (!head) {
0082 fprintf(stderr, "No SVE context\n");
0083 return 1;
0084 }
0085
0086 ssve = (struct sve_context *)head;
0087 if (ssve->vl != vl) {
0088 fprintf(stderr, "Got VL %d, expected %d\n", ssve->vl, vl);
0089 return 1;
0090 }
0091
0092
0093 fprintf(stderr, "Got expected size %u and VL %d\n",
0094 head->size, ssve->vl);
0095
0096 return 0;
0097 }
0098
0099 static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
0100 {
0101 int i;
0102
0103 for (i = 0; i < nvls; i++) {
0104
0105
0106
0107
0108
0109 if (vls[i] > 64) {
0110 printf("Skipping VL %u due to stack size\n", vls[i]);
0111 continue;
0112 }
0113
0114 if (do_one_sme_vl(td, si, uc, vls[i]))
0115 return 1;
0116 }
0117
0118 td->pass = 1;
0119
0120 return 0;
0121 }
0122
0123 struct tdescr tde = {
0124 .name = "Streaming SVE registers",
0125 .descr = "Check that we get the right Streaming SVE registers reported",
0126
0127
0128
0129
0130
0131 .feats_required = FEAT_SME | FEAT_SME_FA64,
0132 .timeout = 3,
0133 .init = sme_get_vls,
0134 .run = sme_regs,
0135 };