1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2023 Ventana Micro Systems Inc.
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.
17 #include "../../kselftest.h"
19 static void help(void)
22 "which-cpus: [-h] [<key=value> [<key=value> ...]]\n\n"
23 " Without parameters, tests the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe.\n"
24 " With parameters, where each parameter is a hwprobe pair written as\n"
25 " <key=value>, outputs the cpulist for cpus which all match the given set\n"
26 " of pairs. 'key' and 'value' should be in numeric form, e.g. 4=0x3b\n");
29 static void print_cpulist(cpu_set_t
*cpus
)
31 int start
= 0, end
= 0;
33 if (!CPU_COUNT(cpus
)) {
34 printf("cpus: None\n");
39 for (int i
= 0, c
= 0; i
< CPU_COUNT(cpus
); i
++, c
++) {
40 if (start
!= end
&& !CPU_ISSET(c
, cpus
))
43 while (!CPU_ISSET(c
, cpus
))
46 if (i
!= 0 && c
== end
+ 1) {
51 printf("%c%d", i
== 0 ? ' ' : ',', c
);
59 static void do_which_cpus(int argc
, char **argv
, cpu_set_t
*cpus
)
61 struct riscv_hwprobe
*pairs
;
62 int nr_pairs
= argc
- 1;
66 pairs
= malloc(nr_pairs
* sizeof(struct riscv_hwprobe
));
69 for (int i
= 0; i
< nr_pairs
; i
++) {
71 pairs
[i
].key
= strtol(start
, &end
, 0);
72 assert(end
!= start
&& *end
== '=');
74 pairs
[i
].value
= strtoul(start
, &end
, 0);
75 assert(end
!= start
&& *end
== '\0');
78 rc
= riscv_hwprobe(pairs
, nr_pairs
, sizeof(cpu_set_t
), (unsigned long *)cpus
, RISCV_HWPROBE_WHICH_CPUS
);
84 int main(int argc
, char **argv
)
86 struct riscv_hwprobe pairs
[2];
87 cpu_set_t cpus_aff
, cpus
;
91 rc
= sched_getaffinity(0, sizeof(cpu_set_t
), &cpus_aff
);
95 if (!strcmp(argv
[1], "-h"))
98 do_which_cpus(argc
, argv
, &cpus_aff
);
105 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, };
106 rc
= riscv_hwprobe(pairs
, 1, 0, NULL
, 0);
107 assert(rc
== 0 && pairs
[0].key
== RISCV_HWPROBE_KEY_BASE_BEHAVIOR
&&
108 pairs
[0].value
== RISCV_HWPROBE_BASE_BEHAVIOR_IMA
);
110 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_IMA_EXT_0
, };
111 rc
= riscv_hwprobe(pairs
, 1, 0, NULL
, 0);
112 assert(rc
== 0 && pairs
[0].key
== RISCV_HWPROBE_KEY_IMA_EXT_0
);
113 ext0_all
= pairs
[0].value
;
115 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
117 rc
= riscv_hwprobe(pairs
, 1, 0, (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
118 ksft_test_result(rc
== -EINVAL
, "no cpusetsize\n");
120 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
121 rc
= riscv_hwprobe(pairs
, 1, sizeof(cpu_set_t
), NULL
, RISCV_HWPROBE_WHICH_CPUS
);
122 ksft_test_result(rc
== -EINVAL
, "NULL cpus\n");
124 pairs
[0] = (struct riscv_hwprobe
){ .key
= 0xbadc0de, };
126 rc
= riscv_hwprobe(pairs
, 1, sizeof(cpu_set_t
), (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
127 ksft_test_result(rc
== 0 && CPU_COUNT(&cpus
) == 0, "unknown key\n");
129 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
130 pairs
[1] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
132 rc
= riscv_hwprobe(pairs
, 2, sizeof(cpu_set_t
), (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
133 ksft_test_result(rc
== 0, "duplicate keys\n");
135 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
136 pairs
[1] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_IMA_EXT_0
, .value
= ext0_all
, };
138 rc
= riscv_hwprobe(pairs
, 2, sizeof(cpu_set_t
), (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
139 ksft_test_result(rc
== 0 && CPU_COUNT(&cpus
) == sysconf(_SC_NPROCESSORS_ONLN
), "set all cpus\n");
141 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
142 pairs
[1] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_IMA_EXT_0
, .value
= ext0_all
, };
143 memcpy(&cpus
, &cpus_aff
, sizeof(cpu_set_t
));
144 rc
= riscv_hwprobe(pairs
, 2, sizeof(cpu_set_t
), (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
145 ksft_test_result(rc
== 0 && CPU_EQUAL(&cpus
, &cpus_aff
), "set all affinity cpus\n");
147 pairs
[0] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_BASE_BEHAVIOR
, .value
= RISCV_HWPROBE_BASE_BEHAVIOR_IMA
, };
148 pairs
[1] = (struct riscv_hwprobe
){ .key
= RISCV_HWPROBE_KEY_IMA_EXT_0
, .value
= ~ext0_all
, };
149 memcpy(&cpus
, &cpus_aff
, sizeof(cpu_set_t
));
150 rc
= riscv_hwprobe(pairs
, 2, sizeof(cpu_set_t
), (unsigned long *)&cpus
, RISCV_HWPROBE_WHICH_CPUS
);
151 ksft_test_result(rc
== 0 && CPU_COUNT(&cpus
) == 0, "clear all cpus\n");