Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2021 ARM Limited
0004  *
0005  * Verify that the streaming SVE register context in signal frames is
0006  * set up as expected.
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      * Enumerate up to SVE_VQ_MAX vector lengths
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         /* Skip missing VLs */
0035         vq = sve_vq_from_vl(vl);
0036 
0037         vls[nvls++] = vl;
0038     }
0039 
0040     /* We need at least one VL */
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     /* smstart sm; real data is TODO */
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      * Get a signal context which should have a SVE frame and registers
0073      * in it.
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     /* The actual size validation is done in get_current_context() */
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          * TODO: the signal test helpers can't currently cope
0106          * with signal frames bigger than struct sigcontext,
0107          * skip VLs that will trigger that.
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      * We shouldn't require FA64 but things like memset() used in the
0128      * helpers might use unsupported instructions so for now disable
0129      * the test unless we've got the full instruction set.
0130      */
0131     .feats_required = FEAT_SME | FEAT_SME_FA64,
0132     .timeout = 3,
0133     .init = sme_get_vls,
0134     .run = sme_regs,
0135 };