File Index
Files and directories
Sign in
FILE

hwprobe.c

File preview with syntax highlighting.

linux-6.19.14/arch/riscv/kernel/vdso/hwprobe.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright 2023 Rivos, Inc
  4 */
  5
  6#include <linux/string.h>
  7#include <linux/types.h>
  8#include <vdso/datapage.h>
  9#include <vdso/helpers.h>
 10
 11extern int riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
 12			 size_t cpusetsize, unsigned long *cpus,
 13			 unsigned int flags);
 14
 15static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count,
 16				 size_t cpusetsize, unsigned long *cpus,
 17				 unsigned int flags)
 18{
 19	const struct vdso_arch_data *avd = &vdso_u_arch_data;
 20	bool all_cpus = !cpusetsize && !cpus;
 21	struct riscv_hwprobe *p = pairs;
 22	struct riscv_hwprobe *end = pairs + pair_count;
 23
 24	/*
 25	 * Defer to the syscall for exotic requests. The vdso has answers
 26	 * stashed away only for the "all cpus" case. If all CPUs are
 27	 * homogeneous, then this function can handle requests for arbitrary
 28	 * masks.
 29	 */
 30	if (flags != 0 || (!all_cpus && !avd->homogeneous_cpus) || unlikely(!avd->ready))
 31		return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags);
 32
 33	/* This is something we can handle, fill out the pairs. */
 34	while (p < end) {
 35		if (riscv_hwprobe_key_is_valid(p->key)) {
 36			p->value = avd->all_cpu_hwprobe_values[p->key];
 37
 38		} else {
 39			p->key = -1;
 40			p->value = 0;
 41		}
 42
 43		p++;
 44	}
 45
 46	return 0;
 47}
 48
 49static int riscv_vdso_get_cpus(struct riscv_hwprobe *pairs, size_t pair_count,
 50			       size_t cpusetsize, unsigned long *cpus,
 51			       unsigned int flags)
 52{
 53	const struct vdso_arch_data *avd = &vdso_u_arch_data;
 54	struct riscv_hwprobe *p = pairs;
 55	struct riscv_hwprobe *end = pairs + pair_count;
 56	unsigned char *c = (unsigned char *)cpus;
 57	bool empty_cpus = true;
 58	bool clear_all = false;
 59	int i;
 60
 61	if (!cpusetsize || !cpus)
 62		return -EINVAL;
 63
 64	for (i = 0; i < cpusetsize; i++) {
 65		if (c[i]) {
 66			empty_cpus = false;
 67			break;
 68		}
 69	}
 70
 71	if (empty_cpus || flags != RISCV_HWPROBE_WHICH_CPUS || !avd->homogeneous_cpus)
 72		return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags);
 73
 74	while (p < end) {
 75		if (riscv_hwprobe_key_is_valid(p->key)) {
 76			struct riscv_hwprobe t = {
 77				.key = p->key,
 78				.value = avd->all_cpu_hwprobe_values[p->key],
 79			};
 80
 81			if (!riscv_hwprobe_pair_cmp(&t, p))
 82				clear_all = true;
 83		} else {
 84			clear_all = true;
 85			p->key = -1;
 86			p->value = 0;
 87		}
 88		p++;
 89	}
 90
 91	if (clear_all) {
 92		for (i = 0; i < cpusetsize; i++)
 93			c[i] = 0;
 94	}
 95
 96	return 0;
 97}
 98
 99/* Add a prototype to avoid -Wmissing-prototypes warning. */
100int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
101			 size_t cpusetsize, unsigned long *cpus,
102			 unsigned int flags);
103
104int __vdso_riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
105			 size_t cpusetsize, unsigned long *cpus,
106			 unsigned int flags)
107{
108	if (flags & RISCV_HWPROBE_WHICH_CPUS)
109		return riscv_vdso_get_cpus(pairs, pair_count, cpusetsize,
110					   cpus, flags);
111
112	return riscv_vdso_get_values(pairs, pair_count, cpusetsize,
113				     cpus, flags);
114}
~/ Read-only file preview.