Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/perf: Add support for caps under sysfs in powerpc

Add caps support under "/sys/bus/event_source/devices/<pmu>/"
for powerpc. This directory can be used to expose some of the
specific features that powerpc PMU supports to the user.
Example: pmu_name. The name of PMU registered will depend on
platform, say power9 or power10 or it could be Generic Compat
PMU.

Currently the only way to know which is the registered
PMU is from the dmesg logs. But clearing the dmesg will make it
difficult to know exact PMU backend used. And even extracting
from dmesg will be complicated, as we need to parse the dmesg
logs and add filters for pmu name. Whereas by exposing it via
caps will make it easy as we just need to directly read it from
the sysfs.

Add a caps directory to /sys/bus/event_source/devices/cpu/
for power8, power9, power10 and generic compat PMU in respective
PMU driver code. Update the pmu_name file under caps folder
in core-book3s using "attr_update".

The information exposed currently:
- pmu_name : Underlying PMU name from the driver

Example result with power9 pmu:

# ls /sys/bus/event_source/devices/cpu/caps
pmu_name

# cat /sys/bus/event_source/devices/cpu/caps/pmu_name
POWER9

Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220520084630.15181-1-atrajeev@linux.vnet.ibm.com

authored by

Athira Rajeev and committed by
Michael Ellerman
6320e693 78988b27

+71
+31
arch/powerpc/perf/core-book3s.c
··· 2483 2483 return 0; 2484 2484 } 2485 2485 2486 + static ssize_t pmu_name_show(struct device *cdev, 2487 + struct device_attribute *attr, 2488 + char *buf) 2489 + { 2490 + if (ppmu) 2491 + return sysfs_emit(buf, "%s", ppmu->name); 2492 + 2493 + return 0; 2494 + } 2495 + 2496 + static DEVICE_ATTR_RO(pmu_name); 2497 + 2498 + static struct attribute *pmu_caps_attrs[] = { 2499 + &dev_attr_pmu_name.attr, 2500 + NULL 2501 + }; 2502 + 2503 + static const struct attribute_group pmu_caps_group = { 2504 + .name = "caps", 2505 + .attrs = pmu_caps_attrs, 2506 + }; 2507 + 2508 + static const struct attribute_group *pmu_caps_groups[] = { 2509 + &pmu_caps_group, 2510 + NULL, 2511 + }; 2512 + 2486 2513 int __init register_power_pmu(struct power_pmu *pmu) 2487 2514 { 2488 2515 if (ppmu) ··· 2520 2493 pmu->name); 2521 2494 2522 2495 power_pmu.attr_groups = ppmu->attr_groups; 2496 + 2497 + if (ppmu->flags & PPMU_ARCH_207S) 2498 + power_pmu.attr_update = pmu_caps_groups; 2499 + 2523 2500 power_pmu.capabilities |= (ppmu->capabilities & PERF_PMU_CAP_EXTENDED_REGS); 2524 2501 2525 2502 #ifdef MSR_HV
+10
arch/powerpc/perf/generic-compat-pmu.c
··· 151 151 .attrs = generic_compat_pmu_format_attr, 152 152 }; 153 153 154 + static struct attribute *generic_compat_pmu_caps_attrs[] = { 155 + NULL 156 + }; 157 + 158 + static struct attribute_group generic_compat_pmu_caps_group = { 159 + .name = "caps", 160 + .attrs = generic_compat_pmu_caps_attrs, 161 + }; 162 + 154 163 static const struct attribute_group *generic_compat_pmu_attr_groups[] = { 155 164 &generic_compat_pmu_format_group, 156 165 &generic_compat_pmu_events_group, 166 + &generic_compat_pmu_caps_group, 157 167 NULL, 158 168 }; 159 169
+10
arch/powerpc/perf/power10-pmu.c
··· 258 258 .attrs = power10_pmu_format_attr, 259 259 }; 260 260 261 + static struct attribute *power10_pmu_caps_attrs[] = { 262 + NULL 263 + }; 264 + 265 + static struct attribute_group power10_pmu_caps_group = { 266 + .name = "caps", 267 + .attrs = power10_pmu_caps_attrs, 268 + }; 269 + 261 270 static const struct attribute_group *power10_pmu_attr_groups_dd1[] = { 262 271 &power10_pmu_format_group, 263 272 &power10_pmu_events_group_dd1, ··· 276 267 static const struct attribute_group *power10_pmu_attr_groups[] = { 277 268 &power10_pmu_format_group, 278 269 &power10_pmu_events_group, 270 + &power10_pmu_caps_group, 279 271 NULL, 280 272 }; 281 273
+10
arch/powerpc/perf/power8-pmu.c
··· 187 187 .attrs = power8_events_attr, 188 188 }; 189 189 190 + static struct attribute *power8_pmu_caps_attrs[] = { 191 + NULL 192 + }; 193 + 194 + static struct attribute_group power8_pmu_caps_group = { 195 + .name = "caps", 196 + .attrs = power8_pmu_caps_attrs, 197 + }; 198 + 190 199 static const struct attribute_group *power8_pmu_attr_groups[] = { 191 200 &isa207_pmu_format_group, 192 201 &power8_pmu_events_group, 202 + &power8_pmu_caps_group, 193 203 NULL, 194 204 }; 195 205
+10
arch/powerpc/perf/power9-pmu.c
··· 258 258 .attrs = power9_pmu_format_attr, 259 259 }; 260 260 261 + static struct attribute *power9_pmu_caps_attrs[] = { 262 + NULL 263 + }; 264 + 265 + static struct attribute_group power9_pmu_caps_group = { 266 + .name = "caps", 267 + .attrs = power9_pmu_caps_attrs, 268 + }; 269 + 261 270 static const struct attribute_group *power9_pmu_attr_groups[] = { 262 271 &power9_pmu_format_group, 263 272 &power9_pmu_events_group, 273 + &power9_pmu_caps_group, 264 274 NULL, 265 275 }; 266 276