diff options
Diffstat (limited to 'arch/x86/kernel/cpu')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 36 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_p6.c | 19 |
5 files changed, 90 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 40883ffe2da9..bb8e03407e18 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1313,6 +1313,11 @@ static void __init pmu_check_apic(void) | |||
1313 | pr_info("no hardware sampling interrupt available.\n"); | 1313 | pr_info("no hardware sampling interrupt available.\n"); |
1314 | } | 1314 | } |
1315 | 1315 | ||
1316 | static struct attribute_group x86_pmu_format_group = { | ||
1317 | .name = "format", | ||
1318 | .attrs = NULL, | ||
1319 | }; | ||
1320 | |||
1316 | static int __init init_hw_perf_events(void) | 1321 | static int __init init_hw_perf_events(void) |
1317 | { | 1322 | { |
1318 | struct x86_pmu_quirk *quirk; | 1323 | struct x86_pmu_quirk *quirk; |
@@ -1387,6 +1392,7 @@ static int __init init_hw_perf_events(void) | |||
1387 | } | 1392 | } |
1388 | 1393 | ||
1389 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ | 1394 | x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ |
1395 | x86_pmu_format_group.attrs = x86_pmu.format_attrs; | ||
1390 | 1396 | ||
1391 | pr_info("... version: %d\n", x86_pmu.version); | 1397 | pr_info("... version: %d\n", x86_pmu.version); |
1392 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); | 1398 | pr_info("... bit width: %d\n", x86_pmu.cntval_bits); |
@@ -1615,6 +1621,9 @@ static int x86_pmu_event_idx(struct perf_event *event) | |||
1615 | { | 1621 | { |
1616 | int idx = event->hw.idx; | 1622 | int idx = event->hw.idx; |
1617 | 1623 | ||
1624 | if (!x86_pmu.attr_rdpmc) | ||
1625 | return 0; | ||
1626 | |||
1618 | if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) { | 1627 | if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) { |
1619 | idx -= X86_PMC_IDX_FIXED; | 1628 | idx -= X86_PMC_IDX_FIXED; |
1620 | idx |= 1 << 30; | 1629 | idx |= 1 << 30; |
@@ -1667,6 +1676,7 @@ static struct attribute_group x86_pmu_attr_group = { | |||
1667 | 1676 | ||
1668 | static const struct attribute_group *x86_pmu_attr_groups[] = { | 1677 | static const struct attribute_group *x86_pmu_attr_groups[] = { |
1669 | &x86_pmu_attr_group, | 1678 | &x86_pmu_attr_group, |
1679 | &x86_pmu_format_group, | ||
1670 | NULL, | 1680 | NULL, |
1671 | }; | 1681 | }; |
1672 | 1682 | ||
@@ -1698,14 +1708,19 @@ static struct pmu pmu = { | |||
1698 | .flush_branch_stack = x86_pmu_flush_branch_stack, | 1708 | .flush_branch_stack = x86_pmu_flush_branch_stack, |
1699 | }; | 1709 | }; |
1700 | 1710 | ||
1701 | void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now) | 1711 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) |
1702 | { | 1712 | { |
1713 | userpg->cap_usr_time = 0; | ||
1714 | userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc; | ||
1715 | userpg->pmc_width = x86_pmu.cntval_bits; | ||
1716 | |||
1703 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 1717 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
1704 | return; | 1718 | return; |
1705 | 1719 | ||
1706 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 1720 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
1707 | return; | 1721 | return; |
1708 | 1722 | ||
1723 | userpg->cap_usr_time = 1; | ||
1709 | userpg->time_mult = this_cpu_read(cyc2ns); | 1724 | userpg->time_mult = this_cpu_read(cyc2ns); |
1710 | userpg->time_shift = CYC2NS_SCALE_FACTOR; | 1725 | userpg->time_shift = CYC2NS_SCALE_FACTOR; |
1711 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; | 1726 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 8484e77c211e..6638aaf54493 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
@@ -339,6 +339,7 @@ struct x86_pmu { | |||
339 | * sysfs attrs | 339 | * sysfs attrs |
340 | */ | 340 | */ |
341 | int attr_rdpmc; | 341 | int attr_rdpmc; |
342 | struct attribute **format_attrs; | ||
342 | 343 | ||
343 | /* | 344 | /* |
344 | * CPU Hotplug hooks | 345 | * CPU Hotplug hooks |
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index dd002faff7a6..95e7fe1c5f0b 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c | |||
@@ -404,6 +404,21 @@ static void amd_pmu_cpu_dead(int cpu) | |||
404 | } | 404 | } |
405 | } | 405 | } |
406 | 406 | ||
407 | PMU_FORMAT_ATTR(event, "config:0-7,32-35"); | ||
408 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
409 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
410 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
411 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
412 | |||
413 | static struct attribute *amd_format_attr[] = { | ||
414 | &format_attr_event.attr, | ||
415 | &format_attr_umask.attr, | ||
416 | &format_attr_edge.attr, | ||
417 | &format_attr_inv.attr, | ||
418 | &format_attr_cmask.attr, | ||
419 | NULL, | ||
420 | }; | ||
421 | |||
407 | static __initconst const struct x86_pmu amd_pmu = { | 422 | static __initconst const struct x86_pmu amd_pmu = { |
408 | .name = "AMD", | 423 | .name = "AMD", |
409 | .handle_irq = x86_pmu_handle_irq, | 424 | .handle_irq = x86_pmu_handle_irq, |
@@ -426,6 +441,8 @@ static __initconst const struct x86_pmu amd_pmu = { | |||
426 | .get_event_constraints = amd_get_event_constraints, | 441 | .get_event_constraints = amd_get_event_constraints, |
427 | .put_event_constraints = amd_put_event_constraints, | 442 | .put_event_constraints = amd_put_event_constraints, |
428 | 443 | ||
444 | .format_attrs = amd_format_attr, | ||
445 | |||
429 | .cpu_prepare = amd_pmu_cpu_prepare, | 446 | .cpu_prepare = amd_pmu_cpu_prepare, |
430 | .cpu_starting = amd_pmu_cpu_starting, | 447 | .cpu_starting = amd_pmu_cpu_starting, |
431 | .cpu_dead = amd_pmu_cpu_dead, | 448 | .cpu_dead = amd_pmu_cpu_dead, |
@@ -596,6 +613,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = { | |||
596 | .cpu_dead = amd_pmu_cpu_dead, | 613 | .cpu_dead = amd_pmu_cpu_dead, |
597 | #endif | 614 | #endif |
598 | .cpu_starting = amd_pmu_cpu_starting, | 615 | .cpu_starting = amd_pmu_cpu_starting, |
616 | .format_attrs = amd_format_attr, | ||
599 | }; | 617 | }; |
600 | 618 | ||
601 | __init int amd_pmu_init(void) | 619 | __init int amd_pmu_init(void) |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 6a84e7f28f05..26b3e2fef104 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1431,6 +1431,24 @@ static void core_pmu_enable_all(int added) | |||
1431 | } | 1431 | } |
1432 | } | 1432 | } |
1433 | 1433 | ||
1434 | PMU_FORMAT_ATTR(event, "config:0-7" ); | ||
1435 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
1436 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
1437 | PMU_FORMAT_ATTR(pc, "config:19" ); | ||
1438 | PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */ | ||
1439 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
1440 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
1441 | |||
1442 | static struct attribute *intel_arch_formats_attr[] = { | ||
1443 | &format_attr_event.attr, | ||
1444 | &format_attr_umask.attr, | ||
1445 | &format_attr_edge.attr, | ||
1446 | &format_attr_pc.attr, | ||
1447 | &format_attr_inv.attr, | ||
1448 | &format_attr_cmask.attr, | ||
1449 | NULL, | ||
1450 | }; | ||
1451 | |||
1434 | static __initconst const struct x86_pmu core_pmu = { | 1452 | static __initconst const struct x86_pmu core_pmu = { |
1435 | .name = "core", | 1453 | .name = "core", |
1436 | .handle_irq = x86_pmu_handle_irq, | 1454 | .handle_irq = x86_pmu_handle_irq, |
@@ -1455,6 +1473,7 @@ static __initconst const struct x86_pmu core_pmu = { | |||
1455 | .put_event_constraints = intel_put_event_constraints, | 1473 | .put_event_constraints = intel_put_event_constraints, |
1456 | .event_constraints = intel_core_event_constraints, | 1474 | .event_constraints = intel_core_event_constraints, |
1457 | .guest_get_msrs = core_guest_get_msrs, | 1475 | .guest_get_msrs = core_guest_get_msrs, |
1476 | .format_attrs = intel_arch_formats_attr, | ||
1458 | }; | 1477 | }; |
1459 | 1478 | ||
1460 | struct intel_shared_regs *allocate_shared_regs(int cpu) | 1479 | struct intel_shared_regs *allocate_shared_regs(int cpu) |
@@ -1553,6 +1572,21 @@ static void intel_pmu_flush_branch_stack(void) | |||
1553 | intel_pmu_lbr_reset(); | 1572 | intel_pmu_lbr_reset(); |
1554 | } | 1573 | } |
1555 | 1574 | ||
1575 | PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63"); | ||
1576 | |||
1577 | static struct attribute *intel_arch3_formats_attr[] = { | ||
1578 | &format_attr_event.attr, | ||
1579 | &format_attr_umask.attr, | ||
1580 | &format_attr_edge.attr, | ||
1581 | &format_attr_pc.attr, | ||
1582 | &format_attr_any.attr, | ||
1583 | &format_attr_inv.attr, | ||
1584 | &format_attr_cmask.attr, | ||
1585 | |||
1586 | &format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */ | ||
1587 | NULL, | ||
1588 | }; | ||
1589 | |||
1556 | static __initconst const struct x86_pmu intel_pmu = { | 1590 | static __initconst const struct x86_pmu intel_pmu = { |
1557 | .name = "Intel", | 1591 | .name = "Intel", |
1558 | .handle_irq = intel_pmu_handle_irq, | 1592 | .handle_irq = intel_pmu_handle_irq, |
@@ -1576,6 +1610,8 @@ static __initconst const struct x86_pmu intel_pmu = { | |||
1576 | .get_event_constraints = intel_get_event_constraints, | 1610 | .get_event_constraints = intel_get_event_constraints, |
1577 | .put_event_constraints = intel_put_event_constraints, | 1611 | .put_event_constraints = intel_put_event_constraints, |
1578 | 1612 | ||
1613 | .format_attrs = intel_arch3_formats_attr, | ||
1614 | |||
1579 | .cpu_prepare = intel_pmu_cpu_prepare, | 1615 | .cpu_prepare = intel_pmu_cpu_prepare, |
1580 | .cpu_starting = intel_pmu_cpu_starting, | 1616 | .cpu_starting = intel_pmu_cpu_starting, |
1581 | .cpu_dying = intel_pmu_cpu_dying, | 1617 | .cpu_dying = intel_pmu_cpu_dying, |
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index c7181befecde..32bcfc7dd230 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c | |||
@@ -87,6 +87,23 @@ static void p6_pmu_enable_event(struct perf_event *event) | |||
87 | (void)checking_wrmsrl(hwc->config_base, val); | 87 | (void)checking_wrmsrl(hwc->config_base, val); |
88 | } | 88 | } |
89 | 89 | ||
90 | PMU_FORMAT_ATTR(event, "config:0-7" ); | ||
91 | PMU_FORMAT_ATTR(umask, "config:8-15" ); | ||
92 | PMU_FORMAT_ATTR(edge, "config:18" ); | ||
93 | PMU_FORMAT_ATTR(pc, "config:19" ); | ||
94 | PMU_FORMAT_ATTR(inv, "config:23" ); | ||
95 | PMU_FORMAT_ATTR(cmask, "config:24-31" ); | ||
96 | |||
97 | static struct attribute *intel_p6_formats_attr[] = { | ||
98 | &format_attr_event.attr, | ||
99 | &format_attr_umask.attr, | ||
100 | &format_attr_edge.attr, | ||
101 | &format_attr_pc.attr, | ||
102 | &format_attr_inv.attr, | ||
103 | &format_attr_cmask.attr, | ||
104 | NULL, | ||
105 | }; | ||
106 | |||
90 | static __initconst const struct x86_pmu p6_pmu = { | 107 | static __initconst const struct x86_pmu p6_pmu = { |
91 | .name = "p6", | 108 | .name = "p6", |
92 | .handle_irq = x86_pmu_handle_irq, | 109 | .handle_irq = x86_pmu_handle_irq, |
@@ -115,6 +132,8 @@ static __initconst const struct x86_pmu p6_pmu = { | |||
115 | .cntval_mask = (1ULL << 32) - 1, | 132 | .cntval_mask = (1ULL << 32) - 1, |
116 | .get_event_constraints = x86_get_event_constraints, | 133 | .get_event_constraints = x86_get_event_constraints, |
117 | .event_constraints = p6_event_constraints, | 134 | .event_constraints = p6_event_constraints, |
135 | |||
136 | .format_attrs = intel_p6_formats_attr, | ||
118 | }; | 137 | }; |
119 | 138 | ||
120 | __init int p6_pmu_init(void) | 139 | __init int p6_pmu_init(void) |