Skip to content

Commit ef7d6ab

Browse files
Andrew Jonespalmer-dabbelt
authored andcommitted
RISC-V: selftests: Add which-cpus hwprobe test
Test the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe. The test also has a command line interface in order to get the cpu list for arbitrary hwprobe pairs. Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Link: https://lore.kernel.org/r/20231122164700.127954-10-ajones@ventanamicro.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent e178bf1 commit ef7d6ab

2 files changed

Lines changed: 158 additions & 1 deletion

File tree

tools/testing/selftests/riscv/hwprobe/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
CFLAGS += -I$(top_srcdir)/tools/include
66

7-
TEST_GEN_PROGS := hwprobe cbo
7+
TEST_GEN_PROGS := hwprobe cbo which-cpus
88

99
include ../../lib.mk
1010

@@ -13,3 +13,6 @@ $(OUTPUT)/hwprobe: hwprobe.c sys_hwprobe.S
1313

1414
$(OUTPUT)/cbo: cbo.c sys_hwprobe.S
1515
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
16+
17+
$(OUTPUT)/which-cpus: which-cpus.c sys_hwprobe.S
18+
$(CC) -static -o$@ $(CFLAGS) $(LDFLAGS) $^
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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+
16+
#include "hwprobe.h"
17+
#include "../../kselftest.h"
18+
19+
static void help(void)
20+
{
21+
printf("\n"
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");
27+
}
28+
29+
static void print_cpulist(cpu_set_t *cpus)
30+
{
31+
int start = 0, end = 0;
32+
33+
if (!CPU_COUNT(cpus)) {
34+
printf("cpus: None\n");
35+
return;
36+
}
37+
38+
printf("cpus:");
39+
for (int i = 0, c = 0; i < CPU_COUNT(cpus); i++, c++) {
40+
if (start != end && !CPU_ISSET(c, cpus))
41+
printf("-%d", end);
42+
43+
while (!CPU_ISSET(c, cpus))
44+
++c;
45+
46+
if (i != 0 && c == end + 1) {
47+
end = c;
48+
continue;
49+
}
50+
51+
printf("%c%d", i == 0 ? ' ' : ',', c);
52+
start = end = c;
53+
}
54+
if (start != end)
55+
printf("-%d", end);
56+
printf("\n");
57+
}
58+
59+
static void do_which_cpus(int argc, char **argv, cpu_set_t *cpus)
60+
{
61+
struct riscv_hwprobe *pairs;
62+
int nr_pairs = argc - 1;
63+
char *start, *end;
64+
int rc;
65+
66+
pairs = malloc(nr_pairs * sizeof(struct riscv_hwprobe));
67+
assert(pairs);
68+
69+
for (int i = 0; i < nr_pairs; i++) {
70+
start = argv[i + 1];
71+
pairs[i].key = strtol(start, &end, 0);
72+
assert(end != start && *end == '=');
73+
start = end + 1;
74+
pairs[i].value = strtoul(start, &end, 0);
75+
assert(end != start && *end == '\0');
76+
}
77+
78+
rc = riscv_hwprobe(pairs, nr_pairs, sizeof(cpu_set_t), (unsigned long *)cpus, RISCV_HWPROBE_WHICH_CPUS);
79+
assert(rc == 0);
80+
print_cpulist(cpus);
81+
free(pairs);
82+
}
83+
84+
int main(int argc, char **argv)
85+
{
86+
struct riscv_hwprobe pairs[2];
87+
cpu_set_t cpus_aff, cpus;
88+
__u64 ext0_all;
89+
long rc;
90+
91+
rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff);
92+
assert(rc == 0);
93+
94+
if (argc > 1) {
95+
if (!strcmp(argv[1], "-h"))
96+
help();
97+
else
98+
do_which_cpus(argc, argv, &cpus_aff);
99+
return 0;
100+
}
101+
102+
ksft_print_header();
103+
ksft_set_plan(7);
104+
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);
109+
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;
114+
115+
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
116+
CPU_ZERO(&cpus);
117+
rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
118+
ksft_test_result(rc == -EINVAL, "no cpusetsize\n");
119+
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");
123+
124+
pairs[0] = (struct riscv_hwprobe){ .key = 0xbadc0de, };
125+
CPU_ZERO(&cpus);
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");
128+
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, };
131+
CPU_ZERO(&cpus);
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");
134+
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, };
137+
CPU_ZERO(&cpus);
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");
140+
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");
146+
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");
152+
153+
ksft_finished();
154+
}

0 commit comments

Comments
 (0)