mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-23 14:24:25 +08:00
ef7d6abb2c
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>
155 lines
5.2 KiB
C
155 lines
5.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2023 Ventana Micro Systems Inc.
|
|
*
|
|
* Test the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe. Also provides a command
|
|
* line interface to get the cpu list for arbitrary hwprobe pairs.
|
|
*/
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sched.h>
|
|
#include <unistd.h>
|
|
#include <assert.h>
|
|
|
|
#include "hwprobe.h"
|
|
#include "../../kselftest.h"
|
|
|
|
static void help(void)
|
|
{
|
|
printf("\n"
|
|
"which-cpus: [-h] [<key=value> [<key=value> ...]]\n\n"
|
|
" Without parameters, tests the RISCV_HWPROBE_WHICH_CPUS flag of hwprobe.\n"
|
|
" With parameters, where each parameter is a hwprobe pair written as\n"
|
|
" <key=value>, outputs the cpulist for cpus which all match the given set\n"
|
|
" of pairs. 'key' and 'value' should be in numeric form, e.g. 4=0x3b\n");
|
|
}
|
|
|
|
static void print_cpulist(cpu_set_t *cpus)
|
|
{
|
|
int start = 0, end = 0;
|
|
|
|
if (!CPU_COUNT(cpus)) {
|
|
printf("cpus: None\n");
|
|
return;
|
|
}
|
|
|
|
printf("cpus:");
|
|
for (int i = 0, c = 0; i < CPU_COUNT(cpus); i++, c++) {
|
|
if (start != end && !CPU_ISSET(c, cpus))
|
|
printf("-%d", end);
|
|
|
|
while (!CPU_ISSET(c, cpus))
|
|
++c;
|
|
|
|
if (i != 0 && c == end + 1) {
|
|
end = c;
|
|
continue;
|
|
}
|
|
|
|
printf("%c%d", i == 0 ? ' ' : ',', c);
|
|
start = end = c;
|
|
}
|
|
if (start != end)
|
|
printf("-%d", end);
|
|
printf("\n");
|
|
}
|
|
|
|
static void do_which_cpus(int argc, char **argv, cpu_set_t *cpus)
|
|
{
|
|
struct riscv_hwprobe *pairs;
|
|
int nr_pairs = argc - 1;
|
|
char *start, *end;
|
|
int rc;
|
|
|
|
pairs = malloc(nr_pairs * sizeof(struct riscv_hwprobe));
|
|
assert(pairs);
|
|
|
|
for (int i = 0; i < nr_pairs; i++) {
|
|
start = argv[i + 1];
|
|
pairs[i].key = strtol(start, &end, 0);
|
|
assert(end != start && *end == '=');
|
|
start = end + 1;
|
|
pairs[i].value = strtoul(start, &end, 0);
|
|
assert(end != start && *end == '\0');
|
|
}
|
|
|
|
rc = riscv_hwprobe(pairs, nr_pairs, sizeof(cpu_set_t), (unsigned long *)cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
assert(rc == 0);
|
|
print_cpulist(cpus);
|
|
free(pairs);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct riscv_hwprobe pairs[2];
|
|
cpu_set_t cpus_aff, cpus;
|
|
__u64 ext0_all;
|
|
long rc;
|
|
|
|
rc = sched_getaffinity(0, sizeof(cpu_set_t), &cpus_aff);
|
|
assert(rc == 0);
|
|
|
|
if (argc > 1) {
|
|
if (!strcmp(argv[1], "-h"))
|
|
help();
|
|
else
|
|
do_which_cpus(argc, argv, &cpus_aff);
|
|
return 0;
|
|
}
|
|
|
|
ksft_print_header();
|
|
ksft_set_plan(7);
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, };
|
|
rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
|
|
assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_BASE_BEHAVIOR &&
|
|
pairs[0].value == RISCV_HWPROBE_BASE_BEHAVIOR_IMA);
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, };
|
|
rc = riscv_hwprobe(pairs, 1, 0, NULL, 0);
|
|
assert(rc == 0 && pairs[0].key == RISCV_HWPROBE_KEY_IMA_EXT_0);
|
|
ext0_all = pairs[0].value;
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
CPU_ZERO(&cpus);
|
|
rc = riscv_hwprobe(pairs, 1, 0, (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == -EINVAL, "no cpusetsize\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
rc = riscv_hwprobe(pairs, 1, sizeof(cpu_set_t), NULL, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == -EINVAL, "NULL cpus\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = 0xbadc0de, };
|
|
CPU_ZERO(&cpus);
|
|
rc = riscv_hwprobe(pairs, 1, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "unknown key\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
CPU_ZERO(&cpus);
|
|
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == 0, "duplicate keys\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
|
|
CPU_ZERO(&cpus);
|
|
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == sysconf(_SC_NPROCESSORS_ONLN), "set all cpus\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ext0_all, };
|
|
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
|
|
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == 0 && CPU_EQUAL(&cpus, &cpus_aff), "set all affinity cpus\n");
|
|
|
|
pairs[0] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_BASE_BEHAVIOR, .value = RISCV_HWPROBE_BASE_BEHAVIOR_IMA, };
|
|
pairs[1] = (struct riscv_hwprobe){ .key = RISCV_HWPROBE_KEY_IMA_EXT_0, .value = ~ext0_all, };
|
|
memcpy(&cpus, &cpus_aff, sizeof(cpu_set_t));
|
|
rc = riscv_hwprobe(pairs, 2, sizeof(cpu_set_t), (unsigned long *)&cpus, RISCV_HWPROBE_WHICH_CPUS);
|
|
ksft_test_result(rc == 0 && CPU_COUNT(&cpus) == 0, "clear all cpus\n");
|
|
|
|
ksft_finished();
|
|
}
|