cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ssve_regs.c (2844B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2021 ARM Limited
      4 *
      5 * Verify that the streaming SVE register context in signal frames is
      6 * set up as 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
     16struct fake_sigframe sf;
     17static unsigned int vls[SVE_VQ_MAX];
     18unsigned int nvls = 0;
     19
     20static bool sme_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_SME_SET_VL, vq * 16);
     29		if (vl == -1)
     30			return false;
     31
     32		vl &= PR_SME_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
     49static void setup_ssve_regs(void)
     50{
     51	/* smstart sm; real data is TODO */
     52	asm volatile(".inst 0xd503437f" : : : );
     53}
     54
     55static int do_one_sme_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 *ssve;
     61	int ret;
     62
     63	fprintf(stderr, "Testing VL %d\n", vl);
     64
     65	ret = prctl(PR_SME_SET_VL, vl);
     66	if (ret != vl) {
     67		fprintf(stderr, "Failed to set VL, got %d\n", ret);
     68		return 1;
     69	}
     70
     71	/*
     72	 * Get a signal context which should have a SVE frame and registers
     73	 * in it.
     74	 */
     75	setup_ssve_regs();
     76	if (!get_current_context(td, &sf.uc))
     77		return 1;
     78
     79	resv_sz = GET_SF_RESV_SIZE(sf);
     80	head = get_header(head, SVE_MAGIC, resv_sz, &offset);
     81	if (!head) {
     82		fprintf(stderr, "No SVE context\n");
     83		return 1;
     84	}
     85
     86	ssve = (struct sve_context *)head;
     87	if (ssve->vl != vl) {
     88		fprintf(stderr, "Got VL %d, expected %d\n", ssve->vl, vl);
     89		return 1;
     90	}
     91
     92	/* The actual size validation is done in get_current_context() */
     93	fprintf(stderr, "Got expected size %u and VL %d\n",
     94		head->size, ssve->vl);
     95
     96	return 0;
     97}
     98
     99static int sme_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
    100{
    101	int i;
    102
    103	for (i = 0; i < nvls; i++) {
    104		/*
    105		 * TODO: the signal test helpers can't currently cope
    106		 * with signal frames bigger than struct sigcontext,
    107		 * skip VLs that will trigger that.
    108		 */
    109		if (vls[i] > 64) {
    110			printf("Skipping VL %u due to stack size\n", vls[i]);
    111			continue;
    112		}
    113
    114		if (do_one_sme_vl(td, si, uc, vls[i]))
    115			return 1;
    116	}
    117
    118	td->pass = 1;
    119
    120	return 0;
    121}
    122
    123struct tdescr tde = {
    124	.name = "Streaming SVE registers",
    125	.descr = "Check that we get the right Streaming SVE registers reported",
    126	/*
    127	 * We shouldn't require FA64 but things like memset() used in the
    128	 * helpers might use unsupported instructions so for now disable
    129	 * the test unless we've got the full instruction set.
    130	 */
    131	.feats_required = FEAT_SME | FEAT_SME_FA64,
    132	.timeout = 3,
    133	.init = sme_get_vls,
    134	.run = sme_regs,
    135};