1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2023 Rivos, Inc
6 #include <linux/string.h>
7 #include <linux/types.h>
8 #include <vdso/datapage.h>
9 #include <vdso/helpers.h>
11 extern int riscv_hwprobe(struct riscv_hwprobe
*pairs
, size_t pair_count
,
12 size_t cpusetsize
, unsigned long *cpus
,
15 static int riscv_vdso_get_values(struct riscv_hwprobe
*pairs
, size_t pair_count
,
16 size_t cpusetsize
, unsigned long *cpus
,
19 const struct vdso_data
*vd
= __arch_get_vdso_data();
20 const struct arch_vdso_time_data
*avd
= &vd
->arch_data
;
21 bool all_cpus
= !cpusetsize
&& !cpus
;
22 struct riscv_hwprobe
*p
= pairs
;
23 struct riscv_hwprobe
*end
= pairs
+ pair_count
;
26 * Defer to the syscall for exotic requests. The vdso has answers
27 * stashed away only for the "all cpus" case. If all CPUs are
28 * homogeneous, then this function can handle requests for arbitrary
31 if ((flags
!= 0) || (!all_cpus
&& !avd
->homogeneous_cpus
))
32 return riscv_hwprobe(pairs
, pair_count
, cpusetsize
, cpus
, flags
);
34 /* This is something we can handle, fill out the pairs. */
36 if (riscv_hwprobe_key_is_valid(p
->key
)) {
37 p
->value
= avd
->all_cpu_hwprobe_values
[p
->key
];
50 static int riscv_vdso_get_cpus(struct riscv_hwprobe
*pairs
, size_t pair_count
,
51 size_t cpusetsize
, unsigned long *cpus
,
54 const struct vdso_data
*vd
= __arch_get_vdso_data();
55 const struct arch_vdso_time_data
*avd
= &vd
->arch_data
;
56 struct riscv_hwprobe
*p
= pairs
;
57 struct riscv_hwprobe
*end
= pairs
+ pair_count
;
58 unsigned char *c
= (unsigned char *)cpus
;
59 bool empty_cpus
= true;
60 bool clear_all
= false;
63 if (!cpusetsize
|| !cpus
)
66 for (i
= 0; i
< cpusetsize
; i
++) {
73 if (empty_cpus
|| flags
!= RISCV_HWPROBE_WHICH_CPUS
|| !avd
->homogeneous_cpus
)
74 return riscv_hwprobe(pairs
, pair_count
, cpusetsize
, cpus
, flags
);
77 if (riscv_hwprobe_key_is_valid(p
->key
)) {
78 struct riscv_hwprobe t
= {
80 .value
= avd
->all_cpu_hwprobe_values
[p
->key
],
83 if (!riscv_hwprobe_pair_cmp(&t
, p
))
94 for (i
= 0; i
< cpusetsize
; i
++)
101 /* Add a prototype to avoid -Wmissing-prototypes warning. */
102 int __vdso_riscv_hwprobe(struct riscv_hwprobe
*pairs
, size_t pair_count
,
103 size_t cpusetsize
, unsigned long *cpus
,
106 int __vdso_riscv_hwprobe(struct riscv_hwprobe
*pairs
, size_t pair_count
,
107 size_t cpusetsize
, unsigned long *cpus
,
110 if (flags
& RISCV_HWPROBE_WHICH_CPUS
)
111 return riscv_vdso_get_cpus(pairs
, pair_count
, cpusetsize
,
114 return riscv_vdso_get_values(pairs
, pair_count
, cpusetsize
,