// 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 = 0 xbadc0de, };
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();
}
Messung V0.5 in Prozent C=99 H=92 G=95
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-10-12)
¤
*© Formatika GbR, Deutschland