which-cpus.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2023 Ventana Micro Systems Inc.
  4. *
  5. * Test the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe. Also provides a command
  6. * line interface to get the cpu list for arbitrary hwprobe pairs.
  7. */
  8. #define _GNU_SOURCE
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sched.h>
  13. #include <unistd.h>
  14. #include <assert.h>
  15. #include "hwprobe.h"
  16. #include "../../kselftest.h"
  17. static void help(void)
  18. {
  19. printf("\n"
  20. "which-cpus: [-h] [<key=value> [<key=value> ...]]\n\n"
  21. " Without parameters, tests the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe.\n"
  22. " With parameters, where each parameter is a hwprobe pair written as\n"
  23. " <key=value>, outputs the cpulist for cpus which all match the given set\n"
  24. " of pairs. 'key' and 'value' should be in numeric form, e.g. 4=0x3b\n");
  25. }
  26. static void print_cpulist(cpu_set_t *cpus)
  27. {
  28. int start = 0, end = 0;
  29. if (!CPU_COUNT(cpus)) {
  30. printf("cpus: None\n");
  31. return;
  32. }
  33. printf("cpus:");
  34. for (int i = 0, c = 0; i < CPU_COUNT(cpus); i++, c++) {
  35. if (start != end && !CPU_ISSET(c, cpus))
  36. printf("-%d", end);
  37. while (!CPU_ISSET(c, cpus))
  38. ++c;
  39. if (i != 0 && c == end + 1) {
  40. end = c;
  41. continue;
  42. }
  43. printf("%c%d", i == 0 ? ' ' : ',', c);
  44. start = end = c;
  45. }
  46. if (start != end)
  47. printf("-%d", end);
  48. printf("\n");
  49. }
  50. static void do_which_cpus(int argc, char **argv, cpu_set_t *cpus)
  51. {
  52. struct riscv_hwprobe *pairs;
  53. int nr_pairs = argc - 1;
  54. char *start, *end;
  55. int rc;
  56. pairs = malloc(nr_pairs * sizeof(struct riscv_hwprobe));
  57. assert(pairs);
  58. for (int i = 0; i < nr_pairs; i++) {
  59. start = argv[i + 1];
  60. pairs[i].key = strtol(start, &end, 0);
  61. assert(end != start && *end == '=');
  62. start = end + 1;
  63. pairs[i].value = strtoul(start, &end, 0);
  64. assert(end != start && *end == '\0');
  65. }
  66. rc = riscv_hwprobe(pairs, nr_pairs, sizeof(cpu_set_t), (unsigned long *)cpus, RISCV_HWPROBE_WHICH_CPUS);
  67. assert(rc == 0);
  68. print_cpulist(cpus);
  69. free(pairs);
  70. }
  71. int main(int argc, char **argv)
  72. {
  73. struct riscv_hwprobe pairs[2];
  74. cpu_set_t cpus_aff, cpus;
  75. __u64 ext0_all;
  76. long rc;
  77. rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff);
  78. assert(rc == 0);
  79. if (argc > 1) {
  80. if (!strcmp(argv[1], "-h"))
  81. help();
  82. else
  83. do_which_cpus(argc, argv, &cpus_aff);
  84. return 0;
  85. }
  86. ksft_print_header();
  87. ksft_set_plan(7);
  88. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, };
  89. rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
  90. assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_BASE_BEHAVIOR &&
  91. pairs[0].value == RISCV_HWPROBE_BASE_BEHAVIOR_IMA);
  92. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, };
  93. rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
  94. assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_0);
  95. ext0_all = pairs[0].value;
  96. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  97. CPU_ZERO(&cpus);
  98. rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  99. ksft_test_result(rc == -EINVAL, "no cpusetsize\n");
  100. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  101. rc = riscv_hwprobe(pairs, 1, sizeof(cpu_set_t), NULL, RISCV_HWPROBE_WHICH_CPUS);
  102. ksft_test_result(rc == -EINVAL, "NULL cpus\n");
  103. pairs[0] = (struct riscv_hwprobe){ .key = 0xbadc0de, };
  104. CPU_ZERO(&cpus);
  105. rc = riscv_hwprobe(pairs, 1, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  106. ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "unknown key\n");
  107. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  108. pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  109. CPU_ZERO(&cpus);
  110. rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  111. ksft_test_result(rc == 0, "duplicate keys\n");
  112. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  113. pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
  114. CPU_ZERO(&cpus);
  115. rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  116. ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == sysconf(_SC_NPROCESSORS_ONLN), "set all cpus\n");
  117. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  118. pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
  119. memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
  120. rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  121. ksft_test_result(rc == 0 && CPU_EQUAL(&cpus, &cpus_aff), "set all affinity cpus\n");
  122. pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
  123. pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ~ext0_all, };
  124. memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
  125. rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
  126. ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "clear all cpus\n");
  127. ksft_finished();
  128. }