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

vlset.c (3423B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015-2019 ARM Limited.
      4 * Original author: Dave Martin <Dave.Martin@arm.com>
      5 */
      6#define _GNU_SOURCE
      7#include <assert.h>
      8#include <errno.h>
      9#include <limits.h>
     10#include <stddef.h>
     11#include <stdio.h>
     12#include <stdlib.h>
     13#include <string.h>
     14#include <getopt.h>
     15#include <unistd.h>
     16#include <sys/auxv.h>
     17#include <sys/prctl.h>
     18#include <asm/hwcap.h>
     19#include <asm/sigcontext.h>
     20
     21static int inherit = 0;
     22static int no_inherit = 0;
     23static int force = 0;
     24static unsigned long vl;
     25static int set_ctl = PR_SVE_SET_VL;
     26static int get_ctl = PR_SVE_GET_VL;
     27
     28static const struct option options[] = {
     29	{ "force",	no_argument, NULL, 'f' },
     30	{ "inherit",	no_argument, NULL, 'i' },
     31	{ "max",	no_argument, NULL, 'M' },
     32	{ "no-inherit",	no_argument, &no_inherit, 1 },
     33	{ "sme",	no_argument, NULL, 's' },
     34	{ "help",	no_argument, NULL, '?' },
     35	{}
     36};
     37
     38static char const *program_name;
     39
     40static int parse_options(int argc, char **argv)
     41{
     42	int c;
     43	char *rest;
     44
     45	program_name = strrchr(argv[0], '/');
     46	if (program_name)
     47		++program_name;
     48	else
     49		program_name = argv[0];
     50
     51	while ((c = getopt_long(argc, argv, "Mfhi", options, NULL)) != -1)
     52		switch (c) {
     53		case 'M':	vl = SVE_VL_MAX; break;
     54		case 'f':	force = 1; break;
     55		case 'i':	inherit = 1; break;
     56		case 's':	set_ctl = PR_SME_SET_VL;
     57				get_ctl = PR_SME_GET_VL;
     58				break;
     59		case 0:		break;
     60		default:	goto error;
     61		}
     62
     63	if (inherit && no_inherit)
     64		goto error;
     65
     66	if (!vl) {
     67		/* vector length */
     68		if (optind >= argc)
     69			goto error;
     70
     71		errno = 0;
     72		vl = strtoul(argv[optind], &rest, 0);
     73		if (*rest) {
     74			vl = ULONG_MAX;
     75			errno = EINVAL;
     76		}
     77		if (vl == ULONG_MAX && errno) {
     78			fprintf(stderr, "%s: %s: %s\n",
     79				program_name, argv[optind], strerror(errno));
     80			goto error;
     81		}
     82
     83		++optind;
     84	}
     85
     86	/* command */
     87	if (optind >= argc)
     88		goto error;
     89
     90	return 0;
     91
     92error:
     93	fprintf(stderr,
     94		"Usage: %s [-f | --force] "
     95		"[-i | --inherit | --no-inherit] "
     96		"{-M | --max | <vector length>} "
     97		"<command> [<arguments> ...]\n",
     98		program_name);
     99	return -1;
    100}
    101
    102int main(int argc, char **argv)
    103{
    104	int ret = 126;	/* same as sh(1) command-not-executable error */
    105	long flags;
    106	char *path;
    107	int t, e;
    108
    109	if (parse_options(argc, argv))
    110		return 2;	/* same as sh(1) builtin incorrect-usage */
    111
    112	if (vl & ~(vl & PR_SVE_VL_LEN_MASK)) {
    113		fprintf(stderr, "%s: Invalid vector length %lu\n",
    114			program_name, vl);
    115		return 2;	/* same as sh(1) builtin incorrect-usage */
    116	}
    117
    118	if (!(getauxval(AT_HWCAP) & HWCAP_SVE)) {
    119		fprintf(stderr, "%s: Scalable Vector Extension not present\n",
    120			program_name);
    121
    122		if (!force)
    123			goto error;
    124
    125		fputs("Going ahead anyway (--force):  "
    126		      "This is a debug option.  Don't rely on it.\n",
    127		      stderr);
    128	}
    129
    130	flags = PR_SVE_SET_VL_ONEXEC;
    131	if (inherit)
    132		flags |= PR_SVE_VL_INHERIT;
    133
    134	t = prctl(set_ctl, vl | flags);
    135	if (t < 0) {
    136		fprintf(stderr, "%s: PR_SVE_SET_VL: %s\n",
    137			program_name, strerror(errno));
    138		goto error;
    139	}
    140
    141	t = prctl(get_ctl);
    142	if (t == -1) {
    143		fprintf(stderr, "%s: PR_SVE_GET_VL: %s\n",
    144			program_name, strerror(errno));
    145		goto error;
    146	}
    147	flags = PR_SVE_VL_LEN_MASK;
    148	flags = t & ~flags;
    149
    150	assert(optind < argc);
    151	path = argv[optind];
    152
    153	execvp(path, &argv[optind]);
    154	e = errno;
    155	if (errno == ENOENT)
    156		ret = 127;	/* same as sh(1) not-found error */
    157	fprintf(stderr, "%s: %s: %s\n", program_name, path, strerror(e));
    158
    159error:
    160	return ret;		/* same as sh(1) not-executable error */
    161}