vlset.c 3.3 KB

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