Path: blob/master/tools/testing/selftests/arm64/fp/vlset.c
26288 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2015-2019 ARM Limited.3* Original author: Dave Martin <[email protected]>4*/5#define _GNU_SOURCE6#include <assert.h>7#include <errno.h>8#include <limits.h>9#include <stddef.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13#include <getopt.h>14#include <unistd.h>15#include <sys/auxv.h>16#include <sys/prctl.h>17#include <asm/hwcap.h>18#include <asm/sigcontext.h>1920static int inherit = 0;21static int no_inherit = 0;22static int force = 0;23static unsigned long vl;24static int set_ctl = PR_SVE_SET_VL;25static int get_ctl = PR_SVE_GET_VL;2627static const struct option options[] = {28{ "force", no_argument, NULL, 'f' },29{ "inherit", no_argument, NULL, 'i' },30{ "max", no_argument, NULL, 'M' },31{ "no-inherit", no_argument, &no_inherit, 1 },32{ "sme", no_argument, NULL, 's' },33{ "help", no_argument, NULL, '?' },34{}35};3637static char const *program_name;3839static int parse_options(int argc, char **argv)40{41int c;42char *rest;4344program_name = strrchr(argv[0], '/');45if (program_name)46++program_name;47else48program_name = argv[0];4950while ((c = getopt_long(argc, argv, "Mfhi", options, NULL)) != -1)51switch (c) {52case 'M': vl = SVE_VL_MAX; break;53case 'f': force = 1; break;54case 'i': inherit = 1; break;55case 's': set_ctl = PR_SME_SET_VL;56get_ctl = PR_SME_GET_VL;57break;58case 0: break;59default: goto error;60}6162if (inherit && no_inherit)63goto error;6465if (!vl) {66/* vector length */67if (optind >= argc)68goto error;6970errno = 0;71vl = strtoul(argv[optind], &rest, 0);72if (*rest) {73vl = ULONG_MAX;74errno = EINVAL;75}76if (vl == ULONG_MAX && errno) {77fprintf(stderr, "%s: %s: %s\n",78program_name, argv[optind], strerror(errno));79goto error;80}8182++optind;83}8485/* command */86if (optind >= argc)87goto error;8889return 0;9091error:92fprintf(stderr,93"Usage: %s [-f | --force] "94"[-i | --inherit | --no-inherit] "95"{-M | --max | <vector length>} "96"<command> [<arguments> ...]\n",97program_name);98return -1;99}100101int main(int argc, char **argv)102{103int ret = 126; /* same as sh(1) command-not-executable error */104long flags;105char *path;106int t, e;107108if (parse_options(argc, argv))109return 2; /* same as sh(1) builtin incorrect-usage */110111if (vl & ~(vl & PR_SVE_VL_LEN_MASK)) {112fprintf(stderr, "%s: Invalid vector length %lu\n",113program_name, vl);114return 2; /* same as sh(1) builtin incorrect-usage */115}116117if (!(getauxval(AT_HWCAP) & HWCAP_SVE)) {118fprintf(stderr, "%s: Scalable Vector Extension not present\n",119program_name);120121if (!force)122goto error;123124fputs("Going ahead anyway (--force): "125"This is a debug option. Don't rely on it.\n",126stderr);127}128129flags = PR_SVE_SET_VL_ONEXEC;130if (inherit)131flags |= PR_SVE_VL_INHERIT;132133t = prctl(set_ctl, vl | flags);134if (t < 0) {135fprintf(stderr, "%s: PR_SVE_SET_VL: %s\n",136program_name, strerror(errno));137goto error;138}139140t = prctl(get_ctl);141if (t == -1) {142fprintf(stderr, "%s: PR_SVE_GET_VL: %s\n",143program_name, strerror(errno));144goto error;145}146flags = PR_SVE_VL_LEN_MASK;147flags = t & ~flags;148149assert(optind < argc);150path = argv[optind];151152execvp(path, &argv[optind]);153e = errno;154if (errno == ENOENT)155ret = 127; /* same as sh(1) not-found error */156fprintf(stderr, "%s: %s: %s\n", program_name, path, strerror(e));157158error:159return ret; /* same as sh(1) not-executable error */160}161162163