Commit c05f3642 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Ingo Molnar:
 "The main updates in this cycle were:

   - Lots of perf tooling changes too voluminous to list (big perf trace
     and perf stat improvements, lots of libtraceevent reorganization,
     etc.), so I'll list the authors and refer to the changelog for
     details:

       Benjamin Peterson, Jérémie Galarneau, Kim Phillips, Peter
       Zijlstra, Ravi Bangoria, Sangwon Hong, Sean V Kelley, Steven
       Rostedt, Thomas Gleixner, Ding Xiang, Eduardo Habkost, Thomas
       Richter, Andi Kleen, Sanskriti Sharma, Adrian Hunter, Tzvetomir
       Stoyanov, Arnaldo Carvalho de Melo, Jiri Olsa.

     ... with the bulk of the changes written by Jiri Olsa, Tzvetomir
     Stoyanov and Arnaldo Carvalho de Melo.

   - Continued intel_rdt work with a focus on playing well with perf
     events. This also imported some non-perf RDT work due to
     dependencies. (Reinette Chatre)

   - Implement counter freezing for Arch Perfmon v4 (Skylake and newer).
     This allows to speed up the PMI handler by avoiding unnecessary MSR
     writes and make it more accurate. (Andi Kleen)

   - kprobes cleanups and simplification (Masami Hiramatsu)

   - Intel Goldmont PMU updates (Kan Liang)

   - ... plus misc other fixes and updates"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (155 commits)
  kprobes/x86: Use preempt_enable() in optimized_callback()
  x86/intel_rdt: Prevent pseudo-locking from using stale pointers
  kprobes, x86/ptrace.h: Make regs_get_kernel_stack_nth() not fault on bad stack
  perf/x86/intel: Export mem events only if there's PEBS support
  x86/cpu: Drop pointless static qualifier in punit_dev_state_show()
  x86/intel_rdt: Fix initial allocation to consider CDP
  x86/intel_rdt: CBM overlap should also check for overlap with CDP peer
  x86/intel_rdt: Introduce utility to obtain CDP peer
  tools lib traceevent, perf tools: Move struct tep_handler definition in a local header file
  tools lib traceevent: Separate out tep_strerror() for strerror_r() issues
  perf python: More portable way to make CFLAGS work with clang
  perf python: Make clang_has_option() work on Python 3
  perf tools: Free temporary 'sys' string in read_event_files()
  perf tools: Avoid double free in read_event_file()
  perf tools: Free 'printk' string in parse_ftrace_printk()
  perf tools: Cleanup trace-event-info 'tdata' leak
  perf strbuf: Match va_{add,copy} with va_end
  perf test: S390 does not support watchpoints in test 22
  perf auxtrace: Include missing asm/bitsperlong.h to get BITS_PER_LONG
  tools include: Adopt linux/bits.h
  ...
parents 0200fbdd dda93b45
...@@ -856,6 +856,11 @@ ...@@ -856,6 +856,11 @@
causing system reset or hang due to sending causing system reset or hang due to sending
INIT from AP to BSP. INIT from AP to BSP.
disable_counter_freezing [HW]
Disable Intel PMU counter freezing feature.
The feature only exists starting from
Arch Perfmon v4 (Skylake and newer).
disable_ddw [PPC/PSERIES] disable_ddw [PPC/PSERIES]
Disable Dynamic DMA Window support. Use this if Disable Dynamic DMA Window support. Use this if
to workaround buggy firmware. to workaround buggy firmware.
......
...@@ -520,18 +520,24 @@ the pseudo-locked region: ...@@ -520,18 +520,24 @@ the pseudo-locked region:
2) Cache hit and miss measurements using model specific precision counters if 2) Cache hit and miss measurements using model specific precision counters if
available. Depending on the levels of cache on the system the pseudo_lock_l2 available. Depending on the levels of cache on the system the pseudo_lock_l2
and pseudo_lock_l3 tracepoints are available. and pseudo_lock_l3 tracepoints are available.
WARNING: triggering this measurement uses from two (for just L2
measurements) to four (for L2 and L3 measurements) precision counters on
the system, if any other measurements are in progress the counters and
their corresponding event registers will be clobbered.
When a pseudo-locked region is created a new debugfs directory is created for When a pseudo-locked region is created a new debugfs directory is created for
it in debugfs as /sys/kernel/debug/resctrl/<newdir>. A single it in debugfs as /sys/kernel/debug/resctrl/<newdir>. A single
write-only file, pseudo_lock_measure, is present in this directory. The write-only file, pseudo_lock_measure, is present in this directory. The
measurement on the pseudo-locked region depends on the number, 1 or 2, measurement of the pseudo-locked region depends on the number written to this
written to this debugfs file. Since the measurements are recorded with the debugfs file:
tracing infrastructure the relevant tracepoints need to be enabled before the 1 - writing "1" to the pseudo_lock_measure file will trigger the latency
measurement is triggered. measurement captured in the pseudo_lock_mem_latency tracepoint. See
example below.
2 - writing "2" to the pseudo_lock_measure file will trigger the L2 cache
residency (cache hits and misses) measurement captured in the
pseudo_lock_l2 tracepoint. See example below.
3 - writing "3" to the pseudo_lock_measure file will trigger the L3 cache
residency (cache hits and misses) measurement captured in the
pseudo_lock_l3 tracepoint.
All measurements are recorded with the tracing infrastructure. This requires
the relevant tracepoints to be enabled before the measurement is triggered.
Example of latency debugging interface: Example of latency debugging interface:
In this example a pseudo-locked region named "newlock" was created. Here is In this example a pseudo-locked region named "newlock" was created. Here is
......
...@@ -1033,6 +1033,27 @@ static inline void x86_assign_hw_event(struct perf_event *event, ...@@ -1033,6 +1033,27 @@ static inline void x86_assign_hw_event(struct perf_event *event,
} }
} }
/**
* x86_perf_rdpmc_index - Return PMC counter used for event
* @event: the perf_event to which the PMC counter was assigned
*
* The counter assigned to this performance event may change if interrupts
* are enabled. This counter should thus never be used while interrupts are
* enabled. Before this function is used to obtain the assigned counter the
* event should be checked for validity using, for example,
* perf_event_read_local(), within the same interrupt disabled section in
* which this counter is planned to be used.
*
* Return: The index of the performance monitoring counter assigned to
* @perf_event.
*/
int x86_perf_rdpmc_index(struct perf_event *event)
{
lockdep_assert_irqs_disabled();
return event->hw.event_base_rdpmc;
}
static inline int match_prev_assignment(struct hw_perf_event *hwc, static inline int match_prev_assignment(struct hw_perf_event *hwc,
struct cpu_hw_events *cpuc, struct cpu_hw_events *cpuc,
int i) int i)
...@@ -1584,7 +1605,7 @@ static void __init pmu_check_apic(void) ...@@ -1584,7 +1605,7 @@ static void __init pmu_check_apic(void)
} }
static struct attribute_group x86_pmu_format_group = { static struct attribute_group x86_pmu_format_group __ro_after_init = {
.name = "format", .name = "format",
.attrs = NULL, .attrs = NULL,
}; };
...@@ -1631,9 +1652,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) ...@@ -1631,9 +1652,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
struct attribute **new; struct attribute **new;
int j, i; int j, i;
for (j = 0; a[j]; j++) for (j = 0; a && a[j]; j++)
; ;
for (i = 0; b[i]; i++) for (i = 0; b && b[i]; i++)
j++; j++;
j++; j++;
...@@ -1642,9 +1663,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) ...@@ -1642,9 +1663,9 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
return NULL; return NULL;
j = 0; j = 0;
for (i = 0; a[i]; i++) for (i = 0; a && a[i]; i++)
new[j++] = a[i]; new[j++] = a[i];
for (i = 0; b[i]; i++) for (i = 0; b && b[i]; i++)
new[j++] = b[i]; new[j++] = b[i];
new[j] = NULL; new[j] = NULL;
...@@ -1715,7 +1736,7 @@ static struct attribute *events_attr[] = { ...@@ -1715,7 +1736,7 @@ static struct attribute *events_attr[] = {
NULL, NULL,
}; };
static struct attribute_group x86_pmu_events_group = { static struct attribute_group x86_pmu_events_group __ro_after_init = {
.name = "events", .name = "events",
.attrs = events_attr, .attrs = events_attr,
}; };
...@@ -2230,7 +2251,7 @@ static struct attribute *x86_pmu_attrs[] = { ...@@ -2230,7 +2251,7 @@ static struct attribute *x86_pmu_attrs[] = {
NULL, NULL,
}; };
static struct attribute_group x86_pmu_attr_group = { static struct attribute_group x86_pmu_attr_group __ro_after_init = {
.attrs = x86_pmu_attrs, .attrs = x86_pmu_attrs,
}; };
...@@ -2248,7 +2269,7 @@ static struct attribute *x86_pmu_caps_attrs[] = { ...@@ -2248,7 +2269,7 @@ static struct attribute *x86_pmu_caps_attrs[] = {
NULL NULL
}; };
static struct attribute_group x86_pmu_caps_group = { static struct attribute_group x86_pmu_caps_group __ro_after_init = {
.name = "caps", .name = "caps",
.attrs = x86_pmu_caps_attrs, .attrs = x86_pmu_caps_attrs,
}; };
......
...@@ -242,7 +242,7 @@ EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); ...@@ -242,7 +242,7 @@ EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2");
static struct attribute *nhm_events_attrs[] = { static struct attribute *nhm_mem_events_attrs[] = {
EVENT_PTR(mem_ld_nhm), EVENT_PTR(mem_ld_nhm),
NULL, NULL,
}; };
...@@ -278,8 +278,6 @@ EVENT_ATTR_STR_HT(topdown-recovery-bubbles.scale, td_recovery_bubbles_scale, ...@@ -278,8 +278,6 @@ EVENT_ATTR_STR_HT(topdown-recovery-bubbles.scale, td_recovery_bubbles_scale,
"4", "2"); "4", "2");
static struct attribute *snb_events_attrs[] = { static struct attribute *snb_events_attrs[] = {
EVENT_PTR(mem_ld_snb),
EVENT_PTR(mem_st_snb),
EVENT_PTR(td_slots_issued), EVENT_PTR(td_slots_issued),
EVENT_PTR(td_slots_retired), EVENT_PTR(td_slots_retired),
EVENT_PTR(td_fetch_bubbles), EVENT_PTR(td_fetch_bubbles),
...@@ -290,6 +288,12 @@ static struct attribute *snb_events_attrs[] = { ...@@ -290,6 +288,12 @@ static struct attribute *snb_events_attrs[] = {
NULL, NULL,
}; };
static struct attribute *snb_mem_events_attrs[] = {
EVENT_PTR(mem_ld_snb),
EVENT_PTR(mem_st_snb),
NULL,
};
static struct event_constraint intel_hsw_event_constraints[] = { static struct event_constraint intel_hsw_event_constraints[] = {
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */ FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */ FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
...@@ -1995,6 +1999,18 @@ static void intel_pmu_nhm_enable_all(int added) ...@@ -1995,6 +1999,18 @@ static void intel_pmu_nhm_enable_all(int added)
intel_pmu_enable_all(added); intel_pmu_enable_all(added);
} }
static void enable_counter_freeze(void)
{
update_debugctlmsr(get_debugctlmsr() |
DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI);
}
static void disable_counter_freeze(void)
{
update_debugctlmsr(get_debugctlmsr() &
~DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI);
}
static inline u64 intel_pmu_get_status(void) static inline u64 intel_pmu_get_status(void)
{ {
u64 status; u64 status;
...@@ -2200,59 +2216,15 @@ static void intel_pmu_reset(void) ...@@ -2200,59 +2216,15 @@ static void intel_pmu_reset(void)
local_irq_restore(flags); local_irq_restore(flags);
} }
/* static int handle_pmi_common(struct pt_regs *regs, u64 status)
* This handler is triggered by the local APIC, so the APIC IRQ handling
* rules apply:
*/
static int intel_pmu_handle_irq(struct pt_regs *regs)
{ {
struct perf_sample_data data; struct perf_sample_data data;
struct cpu_hw_events *cpuc; struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
int bit, loops; int bit;
u64 status; int handled = 0;
int handled;
int pmu_enabled;
cpuc = this_cpu_ptr(&cpu_hw_events);
/*
* Save the PMU state.
* It needs to be restored when leaving the handler.
*/
pmu_enabled = cpuc->enabled;
/*
* No known reason to not always do late ACK,
* but just in case do it opt-in.
*/
if (!x86_pmu.late_ack)
apic_write(APIC_LVTPC, APIC_DM_NMI);
intel_bts_disable_local();
cpuc->enabled = 0;
__intel_pmu_disable_all();
handled = intel_pmu_drain_bts_buffer();
handled += intel_bts_interrupt();
status = intel_pmu_get_status();
if (!status)
goto done;
loops = 0;
again:
intel_pmu_lbr_read();
intel_pmu_ack_status(status);
if (++loops > 100) {
static bool warned = false;
if (!warned) {
WARN(1, "perfevents: irq loop stuck!\n");
perf_event_print_debug();
warned = true;
}
intel_pmu_reset();
goto done;
}
inc_irq_stat(apic_perf_irqs); inc_irq_stat(apic_perf_irqs);
/* /*
* Ignore a range of extra bits in status that do not indicate * Ignore a range of extra bits in status that do not indicate
* overflow by themselves. * overflow by themselves.
...@@ -2261,7 +2233,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) ...@@ -2261,7 +2233,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
GLOBAL_STATUS_ASIF | GLOBAL_STATUS_ASIF |
GLOBAL_STATUS_LBRS_FROZEN); GLOBAL_STATUS_LBRS_FROZEN);
if (!status) if (!status)
goto done; return 0;
/* /*
* In case multiple PEBS events are sampled at the same time, * In case multiple PEBS events are sampled at the same time,
* it is possible to have GLOBAL_STATUS bit 62 set indicating * it is possible to have GLOBAL_STATUS bit 62 set indicating
...@@ -2331,6 +2303,146 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) ...@@ -2331,6 +2303,146 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
x86_pmu_stop(event, 0); x86_pmu_stop(event, 0);
} }
return handled;
}
static bool disable_counter_freezing;
static int __init intel_perf_counter_freezing_setup(char *s)
{
disable_counter_freezing = true;
pr_info("Intel PMU Counter freezing feature disabled\n");
return 1;
}
__setup("disable_counter_freezing", intel_perf_counter_freezing_setup);
/*
* Simplified handler for Arch Perfmon v4:
* - We rely on counter freezing/unfreezing to enable/disable the PMU.
* This is done automatically on PMU ack.
* - Ack the PMU only after the APIC.
*/
static int intel_pmu_handle_irq_v4(struct pt_regs *regs)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
int handled = 0;
bool bts = false;
u64 status;
int pmu_enabled = cpuc->enabled;
int loops = 0;
/* PMU has been disabled because of counter freezing */
cpuc->enabled = 0;
if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
bts = true;
intel_bts_disable_local();
handled = intel_pmu_drain_bts_buffer();
handled += intel_bts_interrupt();
}
status = intel_pmu_get_status();
if (!status)
goto done;
again:
intel_pmu_lbr_read();
if (++loops > 100) {
static bool warned;
if (!warned) {
WARN(1, "perfevents: irq loop stuck!\n");
perf_event_print_debug();
warned = true;
}
intel_pmu_reset();
goto done;
}
handled += handle_pmi_common(regs, status);
done:
/* Ack the PMI in the APIC */
apic_write(APIC_LVTPC, APIC_DM_NMI);
/*
* The counters start counting immediately while ack the status.
* Make it as close as possible to IRET. This avoids bogus
* freezing on Skylake CPUs.
*/
if (status) {
intel_pmu_ack_status(status);
} else {
/*
* CPU may issues two PMIs very close to each other.
* When the PMI handler services the first one, the
* GLOBAL_STATUS is already updated to reflect both.
* When it IRETs, the second PMI is immediately
* handled and it sees clear status. At the meantime,
* there may be a third PMI, because the freezing bit
* isn't set since the ack in first PMI handlers.
* Double check if there is more work to be done.
*/
status = intel_pmu_get_status();
if (status)
goto again;
}
if (bts)
intel_bts_enable_local();
cpuc->enabled = pmu_enabled;
return handled;
}
/*
* This handler is triggered by the local APIC, so the APIC IRQ handling
* rules apply:
*/
static int intel_pmu_handle_irq(struct pt_regs *regs)
{
struct cpu_hw_events *cpuc;
int loops;
u64 status;
int handled;
int pmu_enabled;
cpuc = this_cpu_ptr(&cpu_hw_events);
/*
* Save the PMU state.
* It needs to be restored when leaving the handler.
*/
pmu_enabled = cpuc->enabled;
/*
* No known reason to not always do late ACK,
* but just in case do it opt-in.
*/
if (!x86_pmu.late_ack)
apic_write(APIC_LVTPC, APIC_DM_NMI);
intel_bts_disable_local();
cpuc->enabled = 0;
__intel_pmu_disable_all();
handled = intel_pmu_drain_bts_buffer();
handled += intel_bts_interrupt();
status = intel_pmu_get_status();
if (!status)
goto done;
loops = 0;
again:
intel_pmu_lbr_read();
intel_pmu_ack_status(status);
if (++loops > 100) {
static bool warned;
if (!warned) {
WARN(1, "perfevents: irq loop stuck!\n");
perf_event_print_debug();
warned = true;
}
intel_pmu_reset();
goto done;
}
handled += handle_pmi_common(regs, status);
/* /*
* Repeat if there is more work to be done: * Repeat if there is more work to be done:
*/ */
...@@ -3350,6 +3462,9 @@ static void intel_pmu_cpu_starting(int cpu) ...@@ -3350,6 +3462,9 @@ static void intel_pmu_cpu_starting(int cpu)
if (x86_pmu.version > 1) if (x86_pmu.version > 1)
flip_smm_bit(&x86_pmu.attr_freeze_on_smi); flip_smm_bit(&x86_pmu.attr_freeze_on_smi);
if (x86_pmu.counter_freezing)
enable_counter_freeze();
if (!cpuc->shared_regs) if (!cpuc->shared_regs)
return; return;
...@@ -3421,6 +3536,9 @@ static void intel_pmu_cpu_dying(int cpu) ...@@ -3421,6 +3536,9 @@ static void intel_pmu_cpu_dying(int cpu)
free_excl_cntrs(cpu); free_excl_cntrs(cpu);
fini_debug_store_on_cpu(cpu); fini_debug_store_on_cpu(cpu);
if (x86_pmu.counter_freezing)
disable_counter_freeze();
} }
static void intel_pmu_sched_task(struct perf_event_context *ctx, static void intel_pmu_sched_task(struct perf_event_context *ctx,
...@@ -3725,6 +3843,40 @@ static __init void intel_nehalem_quirk(void) ...@@ -3725,6 +3843,40 @@ static __init void intel_nehalem_quirk(void)
} }
} }
static bool intel_glp_counter_freezing_broken(int cpu)
{
u32 rev = UINT_MAX; /* default to broken for unknown stepping */
switch (cpu_data(cpu).x86_stepping) {
case 1:
rev = 0x28;
break;
case 8:
rev = 0x6;
break;
}
return (cpu_data(cpu).microcode < rev);
}
static __init void intel_glp_counter_freezing_quirk(void)
{
/* Check if it's already disabled */
if (disable_counter_freezing)
return;
/*
* If the system starts with the wrong ucode, leave the
* counter-freezing feature permanently disabled.
*/
if (intel_glp_counter_freezing_broken(raw_smp_processor_id())) {
pr_info("PMU counter freezing disabled due to CPU errata,"
"please upgrade microcode\n");
x86_pmu.counter_freezing = false;
x86_pmu.handle_irq = intel_pmu_handle_irq;
}
}
/* /*
* enable software workaround for errata: * enable software workaround for errata:
* SNB: BJ122 * SNB: BJ122
...@@ -3764,8 +3916,6 @@ EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1"); ...@@ -3764,8 +3916,6 @@ EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1");
EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1"); EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1");
static struct attribute *hsw_events_attrs[] = { static struct attribute *hsw_events_attrs[] = {
EVENT_PTR(mem_ld_hsw),
EVENT_PTR(mem_st_hsw),
EVENT_PTR(td_slots_issued), EVENT_PTR(td_slots_issued),
EVENT_PTR(td_slots_retired), EVENT_PTR(td_slots_retired),
EVENT_PTR(td_fetch_bubbles), EVENT_PTR(td_fetch_bubbles),
...@@ -3776,6 +3926,12 @@ static struct attribute *hsw_events_attrs[] = { ...@@ -3776,6 +3926,12 @@ static struct attribute *hsw_events_attrs[] = {
NULL NULL
}; };
static struct attribute *hsw_mem_events_attrs[] = {
EVENT_PTR(mem_ld_hsw),
EVENT_PTR(mem_st_hsw),
NULL,
};
static struct attribute *hsw_tsx_events_attrs[] = { static struct attribute *hsw_tsx_events_attrs[] = {
EVENT_PTR(tx_start), EVENT_PTR(tx_start),
EVENT_PTR(tx_commit), EVENT_PTR(tx_commit),
...@@ -3792,13 +3948,6 @@ static struct attribute *hsw_tsx_events_attrs[] = { ...@@ -3792,13 +3948,6 @@ static struct attribute *hsw_tsx_events_attrs[] = {
NULL NULL
}; };
static __init struct attribute **get_hsw_events_attrs(void)
{
return boot_cpu_has(X86_FEATURE_RTM) ?
merge_attr(hsw_events_attrs, hsw_tsx_events_attrs) :
hsw_events_attrs;
}
static ssize_t freeze_on_smi_show(struct device *cdev, static ssize_t freeze_on_smi_show(struct device *cdev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
...@@ -3875,9 +4024,32 @@ static struct attribute *intel_pmu_attrs[] = { ...@@ -3875,9 +4024,32 @@ static struct attribute *intel_pmu_attrs[] = {
NULL, NULL,
}; };
static __init struct attribute **
get_events_attrs(struct attribute **base,
struct attribute **mem,
struct attribute **tsx)
{
struct attribute **attrs = base;
struct attribute **old;
if (mem && x86_pmu.pebs)
attrs = merge_attr(attrs, mem);
if (tsx && boot_cpu_has(X86_FEATURE_RTM)) {
old = attrs;
attrs = merge_attr(attrs, tsx);
if (old != base)
kfree(old);
}
return attrs;
}
__init int intel_pmu_init(void) __init int intel_pmu_init(void)
{ {
struct attribute **extra_attr = NULL; struct attribute **extra_attr = NULL;
struct attribute **mem_attr = NULL;
struct attribute **tsx_attr = NULL;
struct attribute **to_free = NULL; struct attribute **to_free = NULL;
union cpuid10_edx edx; union cpuid10_edx edx;
union cpuid10_eax eax; union cpuid10_eax eax;
...@@ -3935,6 +4107,9 @@ __init int intel_pmu_init(void) ...@@ -3935,6 +4107,9 @@ __init int intel_pmu_init(void)
max((int)edx.split.num_counters_fixed, assume); max((int)edx.split.num_counters_fixed, assume);
} }
if (version >= 4)
x86_pmu.counter_freezing = !disable_counter_freezing;
if (boot_cpu_has(X86_FEATURE_PDCM)) { if (boot_cpu_has(X86_FEATURE_PDCM)) {
u64 capabilities; u64 capabilities;
...@@ -3986,7 +4161,7 @@ __init int intel_pmu_init(void) ...@@ -3986,7 +4161,7 @@ __init int intel_pmu_init(void)
x86_pmu.enable_all = intel_pmu_nhm_enable_all; x86_pmu.enable_all = intel_pmu_nhm_enable_all;
x86_pmu.extra_regs = intel_nehalem_extra_regs; x86_pmu.extra_regs = intel_nehalem_extra_regs;
x86_pmu.cpu_events = nhm_events_attrs; mem_attr = nhm_mem_events_attrs;
/* UOPS_ISSUED.STALLED_CYCLES */ /* UOPS_ISSUED.STALLED_CYCLES */
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
...@@ -4004,11 +4179,11 @@ __init int intel_pmu_init(void) ...@@ -4004,11 +4179,11 @@ __init int intel_pmu_init(void)
name = "nehalem"; name = "nehalem";
break; break;
case INTEL_FAM6_ATOM_PINEVIEW: case INTEL_FAM6_ATOM_BONNELL:
case INTEL_FAM6_ATOM_LINCROFT: case INTEL_FAM6_ATOM_BONNELL_MID:
case INTEL_FAM6_ATOM_PENWELL: case INTEL_FAM6_ATOM_SALTWELL:
case INTEL_FAM6_ATOM_CLOVERVIEW: case INTEL_FAM6_ATOM_SALTWELL_MID:
case INTEL_FAM6_ATOM_CEDARVIEW: