1 | // SPDX-License-Identifier: GPL-2.0 |
---|---|
2 | #include <linux/export.h> |
3 | #include <linux/types.h> |
4 | #include <linux/bits.h> |
5 | #include "probe.h" |
6 | |
7 | static umode_t |
8 | not_visible(struct kobject *kobj, struct attribute *attr, int i) |
9 | { |
10 | return 0; |
11 | } |
12 | |
13 | /* |
14 | * Accepts msr[] array with non populated entries as long as either |
15 | * msr[i].msr is 0 or msr[i].grp is NULL. Note that the default sysfs |
16 | * visibility is visible when group->is_visible callback is set. |
17 | */ |
18 | unsigned long |
19 | perf_msr_probe(struct perf_msr *msr, int cnt, bool zero, void *data) |
20 | { |
21 | unsigned long avail = 0; |
22 | unsigned int bit; |
23 | u64 val; |
24 | |
25 | if (cnt >= BITS_PER_LONG) |
26 | return 0; |
27 | |
28 | for (bit = 0; bit < cnt; bit++) { |
29 | if (!msr[bit].no_check) { |
30 | struct attribute_group *grp = msr[bit].grp; |
31 | u64 mask; |
32 | |
33 | /* skip entry with no group */ |
34 | if (!grp) |
35 | continue; |
36 | |
37 | grp->is_visible = not_visible; |
38 | |
39 | /* skip unpopulated entry */ |
40 | if (!msr[bit].msr) |
41 | continue; |
42 | |
43 | if (msr[bit].test && !msr[bit].test(bit, data)) |
44 | continue; |
45 | /* Virt sucks; you cannot tell if a R/O MSR is present :/ */ |
46 | if (rdmsrl_safe(msr: msr[bit].msr, p: &val)) |
47 | continue; |
48 | |
49 | mask = msr[bit].mask; |
50 | if (!mask) |
51 | mask = ~0ULL; |
52 | /* Disable zero counters if requested. */ |
53 | if (!zero && !(val & mask)) |
54 | continue; |
55 | |
56 | grp->is_visible = NULL; |
57 | } |
58 | avail |= BIT(bit); |
59 | } |
60 | |
61 | return avail; |
62 | } |
63 | EXPORT_SYMBOL_GPL(perf_msr_probe); |
64 |