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