File Index
Files and directories
Sign in
FILE

which-cpus.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/riscv/hwprobe/which-cpus.c C
  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
 19static 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
 29static 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
 59static 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
 84int 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}
~/ Read-only file preview.