0001
0002
0003
0004
0005
0006 #include <assert.h>
0007 #include <errno.h>
0008 #include <fcntl.h>
0009 #include <stddef.h>
0010 #include <stdio.h>
0011 #include <stdlib.h>
0012 #include <string.h>
0013 #include <unistd.h>
0014 #include <sys/auxv.h>
0015 #include <sys/prctl.h>
0016 #include <sys/types.h>
0017 #include <sys/wait.h>
0018 #include <asm/sigcontext.h>
0019 #include <asm/hwcap.h>
0020
0021 #include "../../kselftest.h"
0022 #include "rdvl.h"
0023
0024 #define ARCH_MIN_VL SVE_VL_MIN
0025
0026 struct vec_data {
0027 const char *name;
0028 unsigned long hwcap_type;
0029 unsigned long hwcap;
0030 const char *rdvl_binary;
0031 int (*rdvl)(void);
0032
0033 int prctl_get;
0034 int prctl_set;
0035 const char *default_vl_file;
0036
0037 int default_vl;
0038 int min_vl;
0039 int max_vl;
0040 };
0041
0042
0043 static struct vec_data vec_data[] = {
0044 {
0045 .name = "SVE",
0046 .hwcap_type = AT_HWCAP,
0047 .hwcap = HWCAP_SVE,
0048 .rdvl = rdvl_sve,
0049 .rdvl_binary = "./rdvl-sve",
0050 .prctl_get = PR_SVE_GET_VL,
0051 .prctl_set = PR_SVE_SET_VL,
0052 .default_vl_file = "/proc/sys/abi/sve_default_vector_length",
0053 },
0054 {
0055 .name = "SME",
0056 .hwcap_type = AT_HWCAP2,
0057 .hwcap = HWCAP2_SME,
0058 .rdvl = rdvl_sme,
0059 .rdvl_binary = "./rdvl-sme",
0060 .prctl_get = PR_SME_GET_VL,
0061 .prctl_set = PR_SME_SET_VL,
0062 .default_vl_file = "/proc/sys/abi/sme_default_vector_length",
0063 },
0064 };
0065
0066 static int stdio_read_integer(FILE *f, const char *what, int *val)
0067 {
0068 int n = 0;
0069 int ret;
0070
0071 ret = fscanf(f, "%d%*1[\n]%n", val, &n);
0072 if (ret < 1 || n < 1) {
0073 ksft_print_msg("failed to parse integer from %s\n", what);
0074 return -1;
0075 }
0076
0077 return 0;
0078 }
0079
0080
0081 static int get_child_rdvl(struct vec_data *data)
0082 {
0083 FILE *out;
0084 int pipefd[2];
0085 pid_t pid, child;
0086 int read_vl, ret;
0087
0088 ret = pipe(pipefd);
0089 if (ret == -1) {
0090 ksft_print_msg("pipe() failed: %d (%s)\n",
0091 errno, strerror(errno));
0092 return -1;
0093 }
0094
0095 fflush(stdout);
0096
0097 child = fork();
0098 if (child == -1) {
0099 ksft_print_msg("fork() failed: %d (%s)\n",
0100 errno, strerror(errno));
0101 close(pipefd[0]);
0102 close(pipefd[1]);
0103 return -1;
0104 }
0105
0106
0107 if (child == 0) {
0108
0109
0110
0111
0112 ret = dup2(pipefd[1], 1);
0113 if (ret == -1) {
0114 fprintf(stderr, "dup2() %d\n", errno);
0115 exit(EXIT_FAILURE);
0116 }
0117
0118
0119 ret = execl(data->rdvl_binary, data->rdvl_binary, NULL);
0120 fprintf(stderr, "execl(%s) failed: %d (%s)\n",
0121 data->rdvl_binary, errno, strerror(errno));
0122
0123 exit(EXIT_FAILURE);
0124 }
0125
0126 close(pipefd[1]);
0127
0128
0129 do {
0130 pid = wait(&ret);
0131 if (pid == -1) {
0132 ksft_print_msg("wait() failed: %d (%s)\n",
0133 errno, strerror(errno));
0134 close(pipefd[0]);
0135 return -1;
0136 }
0137 } while (pid != child);
0138
0139 assert(pid == child);
0140
0141 if (!WIFEXITED(ret)) {
0142 ksft_print_msg("child exited abnormally\n");
0143 close(pipefd[0]);
0144 return -1;
0145 }
0146
0147 if (WEXITSTATUS(ret) != 0) {
0148 ksft_print_msg("child returned error %d\n",
0149 WEXITSTATUS(ret));
0150 close(pipefd[0]);
0151 return -1;
0152 }
0153
0154 out = fdopen(pipefd[0], "r");
0155 if (!out) {
0156 ksft_print_msg("failed to open child stdout\n");
0157 close(pipefd[0]);
0158 return -1;
0159 }
0160
0161 ret = stdio_read_integer(out, "child", &read_vl);
0162 fclose(out);
0163 if (ret != 0)
0164 return ret;
0165
0166 return read_vl;
0167 }
0168
0169 static int file_read_integer(const char *name, int *val)
0170 {
0171 FILE *f;
0172 int ret;
0173
0174 f = fopen(name, "r");
0175 if (!f) {
0176 ksft_test_result_fail("Unable to open %s: %d (%s)\n",
0177 name, errno,
0178 strerror(errno));
0179 return -1;
0180 }
0181
0182 ret = stdio_read_integer(f, name, val);
0183 fclose(f);
0184
0185 return ret;
0186 }
0187
0188 static int file_write_integer(const char *name, int val)
0189 {
0190 FILE *f;
0191
0192 f = fopen(name, "w");
0193 if (!f) {
0194 ksft_test_result_fail("Unable to open %s: %d (%s)\n",
0195 name, errno,
0196 strerror(errno));
0197 return -1;
0198 }
0199
0200 fprintf(f, "%d", val);
0201 fclose(f);
0202
0203 return 0;
0204 }
0205
0206
0207
0208
0209
0210 static void proc_read_default(struct vec_data *data)
0211 {
0212 int default_vl, child_vl, ret;
0213
0214 ret = file_read_integer(data->default_vl_file, &default_vl);
0215 if (ret != 0)
0216 return;
0217
0218
0219 child_vl = get_child_rdvl(data);
0220 if (child_vl != default_vl) {
0221 ksft_test_result_fail("%s is %d but child VL is %d\n",
0222 data->default_vl_file,
0223 default_vl, child_vl);
0224 return;
0225 }
0226
0227 ksft_test_result_pass("%s default vector length %d\n", data->name,
0228 default_vl);
0229 data->default_vl = default_vl;
0230 }
0231
0232
0233 static void proc_write_min(struct vec_data *data)
0234 {
0235 int ret, new_default, child_vl;
0236
0237 if (geteuid() != 0) {
0238 ksft_test_result_skip("Need to be root to write to /proc\n");
0239 return;
0240 }
0241
0242 ret = file_write_integer(data->default_vl_file, ARCH_MIN_VL);
0243 if (ret != 0)
0244 return;
0245
0246
0247 ret = file_read_integer(data->default_vl_file, &new_default);
0248 if (ret != 0)
0249 return;
0250
0251
0252 child_vl = get_child_rdvl(data);
0253 if (child_vl != new_default) {
0254 ksft_test_result_fail("%s is %d but child VL is %d\n",
0255 data->default_vl_file,
0256 new_default, child_vl);
0257 return;
0258 }
0259
0260 ksft_test_result_pass("%s minimum vector length %d\n", data->name,
0261 new_default);
0262 data->min_vl = new_default;
0263
0264 file_write_integer(data->default_vl_file, data->default_vl);
0265 }
0266
0267
0268 static void proc_write_max(struct vec_data *data)
0269 {
0270 int ret, new_default, child_vl;
0271
0272 if (geteuid() != 0) {
0273 ksft_test_result_skip("Need to be root to write to /proc\n");
0274 return;
0275 }
0276
0277
0278 ret = file_write_integer(data->default_vl_file, -1);
0279 if (ret != 0)
0280 return;
0281
0282
0283 ret = file_read_integer(data->default_vl_file, &new_default);
0284 if (ret != 0)
0285 return;
0286
0287
0288 child_vl = get_child_rdvl(data);
0289 if (child_vl != new_default) {
0290 ksft_test_result_fail("%s is %d but child VL is %d\n",
0291 data->default_vl_file,
0292 new_default, child_vl);
0293 return;
0294 }
0295
0296 ksft_test_result_pass("%s maximum vector length %d\n", data->name,
0297 new_default);
0298 data->max_vl = new_default;
0299
0300 file_write_integer(data->default_vl_file, data->default_vl);
0301 }
0302
0303
0304 static void prctl_get(struct vec_data *data)
0305 {
0306 int ret;
0307
0308 ret = prctl(data->prctl_get);
0309 if (ret == -1) {
0310 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
0311 data->name, errno, strerror(errno));
0312 return;
0313 }
0314
0315
0316 ret &= PR_SVE_VL_LEN_MASK;
0317
0318
0319 if (ret == data->rdvl())
0320 ksft_test_result_pass("%s current VL is %d\n",
0321 data->name, ret);
0322 else
0323 ksft_test_result_fail("%s prctl() VL %d but RDVL is %d\n",
0324 data->name, ret, data->rdvl());
0325 }
0326
0327
0328 static void prctl_set_same(struct vec_data *data)
0329 {
0330 int cur_vl = data->rdvl();
0331 int ret;
0332
0333 ret = prctl(data->prctl_set, cur_vl);
0334 if (ret < 0) {
0335 ksft_test_result_fail("%s prctl set failed: %d (%s)\n",
0336 data->name, errno, strerror(errno));
0337 return;
0338 }
0339
0340 ksft_test_result(cur_vl == data->rdvl(),
0341 "%s set VL %d and have VL %d\n",
0342 data->name, cur_vl, data->rdvl());
0343 }
0344
0345
0346 static void prctl_set(struct vec_data *data)
0347 {
0348 int ret;
0349
0350 if (data->min_vl == data->max_vl) {
0351 ksft_test_result_skip("%s only one VL supported\n",
0352 data->name);
0353 return;
0354 }
0355
0356
0357 ret = prctl(data->prctl_set, data->min_vl);
0358 if (ret < 0) {
0359 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0360 data->name, data->min_vl,
0361 errno, strerror(errno));
0362 return;
0363 }
0364
0365 if ((ret & PR_SVE_VL_LEN_MASK) != data->min_vl) {
0366 ksft_test_result_fail("%s prctl set %d but return value is %d\n",
0367 data->name, data->min_vl, data->rdvl());
0368 return;
0369 }
0370
0371 if (data->rdvl() != data->min_vl) {
0372 ksft_test_result_fail("%s set %d but RDVL is %d\n",
0373 data->name, data->min_vl, data->rdvl());
0374 return;
0375 }
0376
0377
0378 ret = prctl(data->prctl_set, data->max_vl);
0379 if (ret < 0) {
0380 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0381 data->name, data->max_vl,
0382 errno, strerror(errno));
0383 return;
0384 }
0385
0386 if ((ret & PR_SVE_VL_LEN_MASK) != data->max_vl) {
0387 ksft_test_result_fail("%s prctl() set %d but return value is %d\n",
0388 data->name, data->max_vl, data->rdvl());
0389 return;
0390 }
0391
0392
0393 ret = prctl(data->prctl_get);
0394 if (ret == -1) {
0395 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
0396 data->name, errno, strerror(errno));
0397 return;
0398 }
0399
0400 if (ret & PR_SVE_VL_INHERIT) {
0401 ksft_test_result_fail("%s prctl() reports _INHERIT\n",
0402 data->name);
0403 return;
0404 }
0405
0406 ksft_test_result_pass("%s prctl() set min/max\n", data->name);
0407 }
0408
0409
0410 static void prctl_set_no_child(struct vec_data *data)
0411 {
0412 int ret, child_vl;
0413
0414 if (data->min_vl == data->max_vl) {
0415 ksft_test_result_skip("%s only one VL supported\n",
0416 data->name);
0417 return;
0418 }
0419
0420 ret = prctl(data->prctl_set, data->min_vl);
0421 if (ret < 0) {
0422 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0423 data->name, data->min_vl,
0424 errno, strerror(errno));
0425 return;
0426 }
0427
0428
0429 ret = file_write_integer(data->default_vl_file, data->max_vl);
0430 if (ret != 0)
0431 return;
0432
0433
0434 child_vl = get_child_rdvl(data);
0435 if (child_vl != data->max_vl) {
0436 ksft_test_result_fail("%s is %d but child VL is %d\n",
0437 data->default_vl_file,
0438 data->max_vl, child_vl);
0439 return;
0440 }
0441
0442 ksft_test_result_pass("%s vector length used default\n", data->name);
0443
0444 file_write_integer(data->default_vl_file, data->default_vl);
0445 }
0446
0447
0448 static void prctl_set_for_child(struct vec_data *data)
0449 {
0450 int ret, child_vl;
0451
0452 if (data->min_vl == data->max_vl) {
0453 ksft_test_result_skip("%s only one VL supported\n",
0454 data->name);
0455 return;
0456 }
0457
0458 ret = prctl(data->prctl_set, data->min_vl | PR_SVE_VL_INHERIT);
0459 if (ret < 0) {
0460 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0461 data->name, data->min_vl,
0462 errno, strerror(errno));
0463 return;
0464 }
0465
0466
0467 ret = prctl(data->prctl_get);
0468 if (ret == -1) {
0469 ksft_test_result_fail("%s prctl() read failed: %d (%s)\n",
0470 data->name, errno, strerror(errno));
0471 return;
0472 }
0473 if (!(ret & PR_SVE_VL_INHERIT)) {
0474 ksft_test_result_fail("%s prctl() does not report _INHERIT\n",
0475 data->name);
0476 return;
0477 }
0478
0479
0480 ret = file_write_integer(data->default_vl_file, data->max_vl);
0481 if (ret != 0)
0482 return;
0483
0484
0485 child_vl = get_child_rdvl(data);
0486 if (child_vl != data->min_vl) {
0487 ksft_test_result_fail("%s is %d but child VL is %d\n",
0488 data->default_vl_file,
0489 data->min_vl, child_vl);
0490 return;
0491 }
0492
0493 ksft_test_result_pass("%s vector length was inherited\n", data->name);
0494
0495 file_write_integer(data->default_vl_file, data->default_vl);
0496 }
0497
0498
0499 static void prctl_set_onexec(struct vec_data *data)
0500 {
0501 int ret, child_vl;
0502
0503 if (data->min_vl == data->max_vl) {
0504 ksft_test_result_skip("%s only one VL supported\n",
0505 data->name);
0506 return;
0507 }
0508
0509
0510 ret = file_write_integer(data->default_vl_file, data->max_vl);
0511 if (ret != 0)
0512 return;
0513
0514 ret = prctl(data->prctl_set, data->max_vl);
0515 if (ret < 0) {
0516 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0517 data->name, data->min_vl,
0518 errno, strerror(errno));
0519 return;
0520 }
0521
0522
0523 ret = prctl(data->prctl_set, data->min_vl | PR_SVE_SET_VL_ONEXEC);
0524 if (ret < 0) {
0525 ksft_test_result_fail("%s prctl set failed for %d: %d (%s)\n",
0526 data->name, data->min_vl,
0527 errno, strerror(errno));
0528 return;
0529 }
0530
0531
0532 if (data->rdvl() != data->max_vl) {
0533 ksft_test_result_fail("%s VL changed by _ONEXEC prctl()\n",
0534 data->name);
0535 return;
0536 }
0537
0538
0539 child_vl = get_child_rdvl(data);
0540 if (child_vl != data->min_vl) {
0541 ksft_test_result_fail("Set %d _ONEXEC but child VL is %d\n",
0542 data->min_vl, child_vl);
0543 return;
0544 }
0545
0546 ksft_test_result_pass("%s vector length set on exec\n", data->name);
0547
0548 file_write_integer(data->default_vl_file, data->default_vl);
0549 }
0550
0551
0552 static void prctl_set_all_vqs(struct vec_data *data)
0553 {
0554 int ret, vq, vl, new_vl;
0555 int errors = 0;
0556
0557 if (!data->min_vl || !data->max_vl) {
0558 ksft_test_result_skip("%s Failed to enumerate VLs, not testing VL setting\n",
0559 data->name);
0560 return;
0561 }
0562
0563 for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
0564 vl = sve_vl_from_vq(vq);
0565
0566
0567 ret = prctl(data->prctl_set, vl);
0568 if (ret < 0) {
0569 errors++;
0570 ksft_print_msg("%s prctl set failed for %d: %d (%s)\n",
0571 data->name, vl,
0572 errno, strerror(errno));
0573 continue;
0574 }
0575
0576 new_vl = ret & PR_SVE_VL_LEN_MASK;
0577
0578
0579 if (data->rdvl() != new_vl) {
0580 ksft_print_msg("Set %s VL %d but RDVL reports %d\n",
0581 data->name, new_vl, data->rdvl());
0582 errors++;
0583 }
0584
0585
0586 if (new_vl == vl)
0587 continue;
0588
0589
0590 if (vl < data->min_vl) {
0591 if (new_vl != data->min_vl) {
0592 ksft_print_msg("%s VL %d returned %d not minimum %d\n",
0593 data->name, vl, new_vl,
0594 data->min_vl);
0595 errors++;
0596 }
0597
0598 continue;
0599 }
0600
0601
0602 if (vl > data->max_vl) {
0603 if (new_vl != data->max_vl) {
0604 ksft_print_msg("%s VL %d returned %d not maximum %d\n",
0605 data->name, vl, new_vl,
0606 data->max_vl);
0607 errors++;
0608 }
0609
0610 continue;
0611 }
0612
0613
0614 if (!(new_vl < vl)) {
0615 ksft_print_msg("%s VL %d returned %d, did not round down\n",
0616 data->name, vl, new_vl);
0617 errors++;
0618
0619 continue;
0620 }
0621 }
0622
0623 ksft_test_result(errors == 0, "%s prctl() set all VLs, %d errors\n",
0624 data->name, errors);
0625 }
0626
0627 typedef void (*test_type)(struct vec_data *);
0628
0629 static const test_type tests[] = {
0630
0631
0632
0633
0634 proc_read_default,
0635 proc_write_min,
0636 proc_write_max,
0637
0638 prctl_get,
0639 prctl_set_same,
0640 prctl_set,
0641 prctl_set_no_child,
0642 prctl_set_for_child,
0643 prctl_set_onexec,
0644 prctl_set_all_vqs,
0645 };
0646
0647 int main(void)
0648 {
0649 int i, j;
0650
0651 ksft_print_header();
0652 ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
0653
0654 for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
0655 struct vec_data *data = &vec_data[i];
0656 unsigned long supported;
0657
0658 supported = getauxval(data->hwcap_type) & data->hwcap;
0659
0660 for (j = 0; j < ARRAY_SIZE(tests); j++) {
0661 if (supported)
0662 tests[j](data);
0663 else
0664 ksft_test_result_skip("%s not supported\n",
0665 data->name);
0666 }
0667 }
0668
0669 ksft_exit_pass();
0670 }