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