18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/export.h>
38c2ecf20Sopenharmony_ci#include <linux/types.h>
48c2ecf20Sopenharmony_ci#include <linux/bits.h>
58c2ecf20Sopenharmony_ci#include "probe.h"
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_cistatic umode_t
88c2ecf20Sopenharmony_cinot_visible(struct kobject *kobj, struct attribute *attr, int i)
98c2ecf20Sopenharmony_ci{
108c2ecf20Sopenharmony_ci	return 0;
118c2ecf20Sopenharmony_ci}
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/*
148c2ecf20Sopenharmony_ci * Accepts msr[] array with non populated entries as long as either
158c2ecf20Sopenharmony_ci * msr[i].msr is 0 or msr[i].grp is NULL. Note that the default sysfs
168c2ecf20Sopenharmony_ci * visibility is visible when group->is_visible callback is set.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ciunsigned long
198c2ecf20Sopenharmony_ciperf_msr_probe(struct perf_msr *msr, int cnt, bool zero, void *data)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	unsigned long avail = 0;
228c2ecf20Sopenharmony_ci	unsigned int bit;
238c2ecf20Sopenharmony_ci	u64 val;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	if (cnt >= BITS_PER_LONG)
268c2ecf20Sopenharmony_ci		return 0;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	for (bit = 0; bit < cnt; bit++) {
298c2ecf20Sopenharmony_ci		if (!msr[bit].no_check) {
308c2ecf20Sopenharmony_ci			struct attribute_group *grp = msr[bit].grp;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci			/* skip entry with no group */
338c2ecf20Sopenharmony_ci			if (!grp)
348c2ecf20Sopenharmony_ci				continue;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci			grp->is_visible = not_visible;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci			/* skip unpopulated entry */
398c2ecf20Sopenharmony_ci			if (!msr[bit].msr)
408c2ecf20Sopenharmony_ci				continue;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci			if (msr[bit].test && !msr[bit].test(bit, data))
438c2ecf20Sopenharmony_ci				continue;
448c2ecf20Sopenharmony_ci			/* Virt sucks; you cannot tell if a R/O MSR is present :/ */
458c2ecf20Sopenharmony_ci			if (rdmsrl_safe(msr[bit].msr, &val))
468c2ecf20Sopenharmony_ci				continue;
478c2ecf20Sopenharmony_ci			/* Disable zero counters if requested. */
488c2ecf20Sopenharmony_ci			if (!zero && !val)
498c2ecf20Sopenharmony_ci				continue;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci			grp->is_visible = NULL;
528c2ecf20Sopenharmony_ci		}
538c2ecf20Sopenharmony_ci		avail |= BIT(bit);
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return avail;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(perf_msr_probe);
59