diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4a3374e61a93..4428fd178bce 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1316,6 +1316,121 @@ static struct attribute_group x86_pmu_format_group = { | |||
1316 | .attrs = NULL, | 1316 | .attrs = NULL, |
1317 | }; | 1317 | }; |
1318 | 1318 | ||
1319 | struct perf_pmu_events_attr { | ||
1320 | struct device_attribute attr; | ||
1321 | u64 id; | ||
1322 | }; | ||
1323 | |||
1324 | /* | ||
1325 | * Remove all undefined events (x86_pmu.event_map(id) == 0) | ||
1326 | * out of events_attr attributes. | ||
1327 | */ | ||
1328 | static void __init filter_events(struct attribute **attrs) | ||
1329 | { | ||
1330 | int i, j; | ||
1331 | |||
1332 | for (i = 0; attrs[i]; i++) { | ||
1333 | if (x86_pmu.event_map(i)) | ||
1334 | continue; | ||
1335 | |||
1336 | for (j = i; attrs[j]; j++) | ||
1337 | attrs[j] = attrs[j + 1]; | ||
1338 | |||
1339 | /* Check the shifted attr. */ | ||
1340 | i--; | ||
1341 | } | ||
1342 | } | ||
1343 | |||
1344 | static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | ||
1345 | char *page) | ||
1346 | { | ||
1347 | struct perf_pmu_events_attr *pmu_attr = \ | ||
1348 | container_of(attr, struct perf_pmu_events_attr, attr); | ||
1349 | |||
1350 | u64 config = x86_pmu.event_map(pmu_attr->id); | ||
1351 | return x86_pmu.events_sysfs_show(page, config); | ||
1352 | } | ||
1353 | |||
1354 | #define EVENT_VAR(_id) event_attr_##_id | ||
1355 | #define EVENT_PTR(_id) &event_attr_##_id.attr.attr | ||
1356 | |||
1357 | #define EVENT_ATTR(_name, _id) \ | ||
1358 | static struct perf_pmu_events_attr EVENT_VAR(_id) = { \ | ||
1359 | .attr = __ATTR(_name, 0444, events_sysfs_show, NULL), \ | ||
1360 | .id = PERF_COUNT_HW_##_id, \ | ||
1361 | }; | ||
1362 | |||
1363 | EVENT_ATTR(cpu-cycles, CPU_CYCLES ); | ||
1364 | EVENT_ATTR(instructions, INSTRUCTIONS ); | ||
1365 | EVENT_ATTR(cache-references, CACHE_REFERENCES ); | ||
1366 | EVENT_ATTR(cache-misses, CACHE_MISSES ); | ||
1367 | EVENT_ATTR(branch-instructions, BRANCH_INSTRUCTIONS ); | ||
1368 | EVENT_ATTR(branch-misses, BRANCH_MISSES ); | ||
1369 | EVENT_ATTR(bus-cycles, BUS_CYCLES ); | ||
1370 | EVENT_ATTR(stalled-cycles-frontend, STALLED_CYCLES_FRONTEND ); | ||
1371 | EVENT_ATTR(stalled-cycles-backend, STALLED_CYCLES_BACKEND ); | ||
1372 | EVENT_ATTR(ref-cycles, REF_CPU_CYCLES ); | ||
1373 | |||
1374 | static struct attribute *empty_attrs; | ||
1375 | |||
1376 | static struct attribute *events_attr[] = { | ||
1377 | EVENT_PTR(CPU_CYCLES), | ||
1378 | EVENT_PTR(INSTRUCTIONS), | ||
1379 | EVENT_PTR(CACHE_REFERENCES), | ||
1380 | EVENT_PTR(CACHE_MISSES), | ||
1381 | EVENT_PTR(BRANCH_INSTRUCTIONS), | ||
1382 | EVENT_PTR(BRANCH_MISSES), | ||
1383 | EVENT_PTR(BUS_CYCLES), | ||
1384 | EVENT_PTR(STALLED_CYCLES_FRONTEND), | ||
1385 | EVENT_PTR(STALLED_CYCLES_BACKEND), | ||
1386 | EVENT_PTR(REF_CPU_CYCLES), | ||
1387 | NULL, | ||
1388 | }; | ||
1389 | |||
1390 | static struct attribute_group x86_pmu_events_group = { | ||
1391 | .name = "events", | ||
1392 | .attrs = events_attr, | ||
1393 | }; | ||
1394 | |||
1395 | ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event) | ||
1396 | { | ||
1397 | u64 umask = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8; | ||
1398 | u64 cmask = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24; | ||
1399 | bool edge = (config & ARCH_PERFMON_EVENTSEL_EDGE); | ||
1400 | bool pc = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL); | ||
1401 | bool any = (config & ARCH_PERFMON_EVENTSEL_ANY); | ||
1402 | bool inv = (config & ARCH_PERFMON_EVENTSEL_INV); | ||
1403 | ssize_t ret; | ||
1404 | |||
1405 | /* | ||
1406 | * We have whole page size to spend and just little data | ||
1407 | * to write, so we can safely use sprintf. | ||
1408 | */ | ||
1409 | ret = sprintf(page, "event=0x%02llx", event); | ||
1410 | |||
1411 | if (umask) | ||
1412 | ret += sprintf(page + ret, ",umask=0x%02llx", umask); | ||
1413 | |||
1414 | if (edge) | ||
1415 | ret += sprintf(page + ret, ",edge"); | ||
1416 | |||
1417 | if (pc) | ||
1418 | ret += sprintf(page + ret, ",pc"); | ||
1419 | |||
1420 | if (any) | ||
1421 | ret += sprintf(page + ret, ",any"); | ||
1422 | |||
1423 | if (inv) | ||
1424 | ret += sprintf(page + ret, ",inv"); | ||
1425 | |||
1426 | if (cmask) | ||
1427 | ret += sprintf(page + ret, ",cmask=0x%02llx", cmask); | ||
1428 | |||
1429 | ret += sprintf(page + ret, "\n"); | ||
1430 | |||
1431 | return ret; | ||
1432 | } | ||
1433 | |||
1319 | static int __init init_hw_perf_events(void) | 1434 | static int __init init_hw_perf_events(void) |
1320 | { | 1435 | { |
1321 | struct x86_pmu_quirk *quirk; | 1436 | struct x86_pmu_quirk *quirk; |
@@ -1362,6 +1477,11 @@ static int __init init_hw_perf_events(void) | |||
1362 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ | 1477 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ |
1363 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; | 1478 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; |
1364 | 1479 | ||
1480 | if (!x86_pmu.events_sysfs_show) | ||
1481 | x86_pmu_events_group.attrs = &empty_attrs; | ||
1482 | else | ||
1483 | filter_events(x86_pmu_events_group.attrs); | ||
1484 | |||
1365 | pr_info("... version: %d\n", x86_pmu.version); | 1485 | pr_info("... version: %d\n", x86_pmu.version); |
1366 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); | 1486 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); |
1367 | pr_info("... generic registers: %d\n", x86_pmu.num_counters); | 1487 | pr_info("... generic registers: %d\n", x86_pmu.num_counters); |
@@ -1651,6 +1771,7 @@ static struct attribute_group x86_pmu_attr_group = { | |||
1651 | static const struct attribute_group *x86_pmu_attr_groups[] = { | 1771 | static const struct attribute_group *x86_pmu_attr_groups[] = { |
1652 | &x86_pmu_attr_group, | 1772 | &x86_pmu_attr_group, |
1653 | &x86_pmu_format_group, | 1773 | &x86_pmu_format_group, |
1774 | &x86_pmu_events_group, | ||
1654 | NULL, | 1775 | NULL, |
1655 | }; | 1776 | }; |
1656 | 1777 | ||