2012-09-27 02:12:52 +08:00
|
|
|
/* Driver for Intel Xeon Phi "Knights Corner" PMU */
|
|
|
|
|
|
|
|
#include <linux/perf_event.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
|
2012-10-18 01:05:45 +08:00
|
|
|
#include <asm/hardirq.h>
|
|
|
|
|
2016-02-10 17:55:23 +08:00
|
|
|
#include "../perf_event.h"
|
2012-09-27 02:12:52 +08:00
|
|
|
|
|
|
|
static const u64 knc_perfmon_event_map[] =
|
|
|
|
{
|
|
|
|
[PERF_COUNT_HW_CPU_CYCLES] = 0x002a,
|
|
|
|
[PERF_COUNT_HW_INSTRUCTIONS] = 0x0016,
|
|
|
|
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x0028,
|
|
|
|
[PERF_COUNT_HW_CACHE_MISSES] = 0x0029,
|
|
|
|
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0012,
|
|
|
|
[PERF_COUNT_HW_BRANCH_MISSES] = 0x002b,
|
|
|
|
};
|
|
|
|
|
2013-03-11 17:56:05 +08:00
|
|
|
static const u64 __initconst knc_hw_cache_event_ids
|
2012-09-27 02:12:52 +08:00
|
|
|
[PERF_COUNT_HW_CACHE_MAX]
|
|
|
|
[PERF_COUNT_HW_CACHE_OP_MAX]
|
|
|
|
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
|
|
|
|
{
|
|
|
|
[ C(L1D) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
/* On Xeon Phi event "0" is a valid DATA_READ */
|
|
|
|
/* (L1 Data Cache Reads) Instruction. */
|
|
|
|
/* We code this as ARCH_PERFMON_EVENTSEL_INT as this */
|
|
|
|
/* bit will always be set in x86_pmu_hw_config(). */
|
|
|
|
[ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
|
|
|
|
/* DATA_READ */
|
|
|
|
[ C(RESULT_MISS) ] = 0x0003, /* DATA_READ_MISS */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0001, /* DATA_WRITE */
|
|
|
|
[ C(RESULT_MISS) ] = 0x0004, /* DATA_WRITE_MISS */
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0011, /* L1_DATA_PF1 */
|
|
|
|
[ C(RESULT_MISS) ] = 0x001c, /* L1_DATA_PF1_MISS */
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[ C(L1I ) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x000c, /* CODE_READ */
|
|
|
|
[ C(RESULT_MISS) ] = 0x000e, /* CODE_CACHE_MISS */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = -1,
|
|
|
|
[ C(RESULT_MISS) ] = -1,
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0,
|
|
|
|
[ C(RESULT_MISS) ] = 0x0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[ C(LL ) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0,
|
|
|
|
[ C(RESULT_MISS) ] = 0x10cb, /* L2_READ_MISS */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x10cc, /* L2_WRITE_HIT */
|
|
|
|
[ C(RESULT_MISS) ] = 0,
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x10fc, /* L2_DATA_PF2 */
|
|
|
|
[ C(RESULT_MISS) ] = 0x10fe, /* L2_DATA_PF2_MISS */
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[ C(DTLB) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
|
|
|
|
/* DATA_READ */
|
|
|
|
/* see note on L1 OP_READ */
|
|
|
|
[ C(RESULT_MISS) ] = 0x0002, /* DATA_PAGE_WALK */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0001, /* DATA_WRITE */
|
|
|
|
[ C(RESULT_MISS) ] = 0x0002, /* DATA_PAGE_WALK */
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0,
|
|
|
|
[ C(RESULT_MISS) ] = 0x0,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[ C(ITLB) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x000c, /* CODE_READ */
|
|
|
|
[ C(RESULT_MISS) ] = 0x000d, /* CODE_PAGE_WALK */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = -1,
|
|
|
|
[ C(RESULT_MISS) ] = -1,
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = -1,
|
|
|
|
[ C(RESULT_MISS) ] = -1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
[ C(BPU ) ] = {
|
|
|
|
[ C(OP_READ) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = 0x0012, /* BRANCHES */
|
|
|
|
[ C(RESULT_MISS) ] = 0x002b, /* BRANCHES_MISPREDICTED */
|
|
|
|
},
|
|
|
|
[ C(OP_WRITE) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = -1,
|
|
|
|
[ C(RESULT_MISS) ] = -1,
|
|
|
|
},
|
|
|
|
[ C(OP_PREFETCH) ] = {
|
|
|
|
[ C(RESULT_ACCESS) ] = -1,
|
|
|
|
[ C(RESULT_MISS) ] = -1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static u64 knc_pmu_event_map(int hw_event)
|
|
|
|
{
|
|
|
|
return knc_perfmon_event_map[hw_event];
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct event_constraint knc_event_constraints[] =
|
|
|
|
{
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xc3, 0x1), /* HWP_L2HIT */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xc4, 0x1), /* HWP_L2MISS */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xc8, 0x1), /* L2_READ_HIT_E */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* L2_READ_HIT_M */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xca, 0x1), /* L2_READ_HIT_S */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* L2_READ_MISS */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xcc, 0x1), /* L2_WRITE_HIT */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xce, 0x1), /* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xcf, 0x1), /* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xd7, 0x1), /* L2_VICTIM_REQ_WITH_DATA */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xe3, 0x1), /* SNP_HITM_BUNIT */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xe6, 0x1), /* SNP_HIT_L2 */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xe7, 0x1), /* SNP_HITM_L2 */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xf1, 0x1), /* L2_DATA_READ_MISS_CACHE_FILL */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xf2, 0x1), /* L2_DATA_WRITE_MISS_CACHE_FILL */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xf6, 0x1), /* L2_DATA_READ_MISS_MEM_FILL */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xf7, 0x1), /* L2_DATA_WRITE_MISS_MEM_FILL */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xfc, 0x1), /* L2_DATA_PF2 */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xfd, 0x1), /* L2_DATA_PF2_DROP */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xfe, 0x1), /* L2_DATA_PF2_MISS */
|
|
|
|
INTEL_EVENT_CONSTRAINT(0xff, 0x1), /* L2_DATA_HIT_INFLIGHT_PF2 */
|
|
|
|
EVENT_CONSTRAINT_END
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MSR_KNC_IA32_PERF_GLOBAL_STATUS 0x0000002d
|
|
|
|
#define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL 0x0000002e
|
|
|
|
#define MSR_KNC_IA32_PERF_GLOBAL_CTRL 0x0000002f
|
|
|
|
|
|
|
|
#define KNC_ENABLE_COUNTER0 0x00000001
|
|
|
|
#define KNC_ENABLE_COUNTER1 0x00000002
|
|
|
|
|
|
|
|
static void knc_pmu_disable_all(void)
|
|
|
|
{
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
|
|
|
|
val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
|
|
|
|
wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void knc_pmu_enable_all(int added)
|
|
|
|
{
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
|
|
|
|
val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
|
|
|
|
wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
knc_pmu_disable_event(struct perf_event *event)
|
|
|
|
{
|
|
|
|
struct hw_perf_event *hwc = &event->hw;
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
val = hwc->config;
|
2012-10-18 01:04:33 +08:00
|
|
|
val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
|
2012-09-27 02:12:52 +08:00
|
|
|
|
|
|
|
(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void knc_pmu_enable_event(struct perf_event *event)
|
|
|
|
{
|
|
|
|
struct hw_perf_event *hwc = &event->hw;
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
val = hwc->config;
|
2012-10-18 01:04:33 +08:00
|
|
|
val |= ARCH_PERFMON_EVENTSEL_ENABLE;
|
2012-09-27 02:12:52 +08:00
|
|
|
|
|
|
|
(void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
|
|
|
|
}
|
|
|
|
|
2012-10-18 01:05:45 +08:00
|
|
|
static inline u64 knc_pmu_get_status(void)
|
|
|
|
{
|
|
|
|
u64 status;
|
|
|
|
|
|
|
|
rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void knc_pmu_ack_status(u64 ack)
|
|
|
|
{
|
|
|
|
wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int knc_pmu_handle_irq(struct pt_regs *regs)
|
|
|
|
{
|
|
|
|
struct perf_sample_data data;
|
|
|
|
struct cpu_hw_events *cpuc;
|
|
|
|
int handled = 0;
|
|
|
|
int bit, loops;
|
|
|
|
u64 status;
|
|
|
|
|
x86: Replace __get_cpu_var uses
__get_cpu_var() is used for multiple purposes in the kernel source. One of
them is address calculation via the form &__get_cpu_var(x). This calculates
the address for the instance of the percpu variable of the current processor
based on an offset.
Other use cases are for storing and retrieving data from the current
processors percpu area. __get_cpu_var() can be used as an lvalue when
writing data or on the right side of an assignment.
__get_cpu_var() is defined as :
#define __get_cpu_var(var) (*this_cpu_ptr(&(var)))
__get_cpu_var() always only does an address determination. However, store
and retrieve operations could use a segment prefix (or global register on
other platforms) to avoid the address calculation.
this_cpu_write() and this_cpu_read() can directly take an offset into a
percpu area and use optimized assembly code to read and write per cpu
variables.
This patch converts __get_cpu_var into either an explicit address
calculation using this_cpu_ptr() or into a use of this_cpu operations that
use the offset. Thereby address calculations are avoided and less registers
are used when code is generated.
Transformations done to __get_cpu_var()
1. Determine the address of the percpu instance of the current processor.
DEFINE_PER_CPU(int, y);
int *x = &__get_cpu_var(y);
Converts to
int *x = this_cpu_ptr(&y);
2. Same as #1 but this time an array structure is involved.
DEFINE_PER_CPU(int, y[20]);
int *x = __get_cpu_var(y);
Converts to
int *x = this_cpu_ptr(y);
3. Retrieve the content of the current processors instance of a per cpu
variable.
DEFINE_PER_CPU(int, y);
int x = __get_cpu_var(y)
Converts to
int x = __this_cpu_read(y);
4. Retrieve the content of a percpu struct
DEFINE_PER_CPU(struct mystruct, y);
struct mystruct x = __get_cpu_var(y);
Converts to
memcpy(&x, this_cpu_ptr(&y), sizeof(x));
5. Assignment to a per cpu variable
DEFINE_PER_CPU(int, y)
__get_cpu_var(y) = x;
Converts to
__this_cpu_write(y, x);
6. Increment/Decrement etc of a per cpu variable
DEFINE_PER_CPU(int, y);
__get_cpu_var(y)++
Converts to
__this_cpu_inc(y)
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org
Acked-by: H. Peter Anvin <hpa@linux.intel.com>
Acked-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Christoph Lameter <cl@linux.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
2014-08-18 01:30:40 +08:00
|
|
|
cpuc = this_cpu_ptr(&cpu_hw_events);
|
2012-10-18 01:05:45 +08:00
|
|
|
|
|
|
|
knc_pmu_disable_all();
|
|
|
|
|
|
|
|
status = knc_pmu_get_status();
|
|
|
|
if (!status) {
|
|
|
|
knc_pmu_enable_all(0);
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
loops = 0;
|
|
|
|
again:
|
|
|
|
knc_pmu_ack_status(status);
|
|
|
|
if (++loops > 100) {
|
|
|
|
WARN_ONCE(1, "perf: irq loop stuck!\n");
|
|
|
|
perf_event_print_debug();
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
inc_irq_stat(apic_perf_irqs);
|
|
|
|
|
|
|
|
for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
|
|
|
|
struct perf_event *event = cpuc->events[bit];
|
|
|
|
|
|
|
|
handled++;
|
|
|
|
|
|
|
|
if (!test_bit(bit, cpuc->active_mask))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!intel_pmu_save_and_restart(event))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
perf_sample_data_init(&data, 0, event->hw.last_period);
|
|
|
|
|
|
|
|
if (perf_event_overflow(event, &data, regs))
|
|
|
|
x86_pmu_stop(event, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Repeat if there is more work to be done:
|
|
|
|
*/
|
|
|
|
status = knc_pmu_get_status();
|
|
|
|
if (status)
|
|
|
|
goto again;
|
|
|
|
|
|
|
|
done:
|
perf/x86/intel: Fix PEBS warning by only restoring active PMU in pmi
This patch tries to fix a PEBS warning found in my stress test. The
following perf command can easily trigger the pebs warning or spurious
NMI error on Skylake/Broadwell/Haswell platforms:
sudo perf record -e 'cpu/umask=0x04,event=0xc4/pp,cycles,branches,ref-cycles,cache-misses,cache-references' --call-graph fp -b -c1000 -a
Also the NMI watchdog must be enabled.
For this case, the events number is larger than counter number. So
perf has to do multiplexing.
In perf_mux_hrtimer_handler, it does perf_pmu_disable(), schedule out
old events, rotate_ctx, schedule in new events and finally
perf_pmu_enable().
If the old events include precise event, the MSR_IA32_PEBS_ENABLE
should be cleared when perf_pmu_disable(). The MSR_IA32_PEBS_ENABLE
should keep 0 until the perf_pmu_enable() is called and the new event is
precise event.
However, there is a corner case which could restore PEBS_ENABLE to
stale value during the above period. In perf_pmu_disable(), GLOBAL_CTRL
will be set to 0 to stop overflow and followed PMI. But there may be
pending PMI from an earlier overflow, which cannot be stopped. So even
GLOBAL_CTRL is cleared, the kernel still be possible to get PMI. At
the end of the PMI handler, __intel_pmu_enable_all() will be called,
which will restore the stale values if old events haven't scheduled
out.
Once the stale pebs value is set, it's impossible to be corrected if
the new events are non-precise. Because the pebs_enabled will be set
to 0. x86_pmu.enable_all() will ignore the MSR_IA32_PEBS_ENABLE
setting. As a result, the following NMI with stale PEBS_ENABLE
trigger pebs warning.
The pending PMI after enabled=0 will become harmless if the NMI handler
does not change the state. This patch checks cpuc->enabled in pmi and
only restore the state when PMU is active.
Here is the dump:
Call Trace:
<NMI> [<ffffffff813c3a2e>] dump_stack+0x63/0x85
[<ffffffff810a46f2>] warn_slowpath_common+0x82/0xc0
[<ffffffff810a483a>] warn_slowpath_null+0x1a/0x20
[<ffffffff8100fe2e>] intel_pmu_drain_pebs_nhm+0x2be/0x320
[<ffffffff8100caa9>] intel_pmu_handle_irq+0x279/0x460
[<ffffffff810639b6>] ? native_write_msr_safe+0x6/0x40
[<ffffffff811f290d>] ? vunmap_page_range+0x20d/0x330
[<ffffffff811f2f11>] ? unmap_kernel_range_noflush+0x11/0x20
[<ffffffff8148379f>] ? ghes_copy_tofrom_phys+0x10f/0x2a0
[<ffffffff814839c8>] ? ghes_read_estatus+0x98/0x170
[<ffffffff81005a7d>] perf_event_nmi_handler+0x2d/0x50
[<ffffffff810310b9>] nmi_handle+0x69/0x120
[<ffffffff810316f6>] default_do_nmi+0xe6/0x100
[<ffffffff810317f2>] do_nmi+0xe2/0x130
[<ffffffff817aea71>] end_repeat_nmi+0x1a/0x1e
[<ffffffff810639b6>] ? native_write_msr_safe+0x6/0x40
[<ffffffff810639b6>] ? native_write_msr_safe+0x6/0x40
[<ffffffff810639b6>] ? native_write_msr_safe+0x6/0x40
<<EOE>> <IRQ> [<ffffffff81006df8>] ? x86_perf_event_set_period+0xd8/0x180
[<ffffffff81006eec>] x86_pmu_start+0x4c/0x100
[<ffffffff8100722d>] x86_pmu_enable+0x28d/0x300
[<ffffffff811994d7>] perf_pmu_enable.part.81+0x7/0x10
[<ffffffff8119cb70>] perf_mux_hrtimer_handler+0x200/0x280
[<ffffffff8119c970>] ? __perf_install_in_context+0xc0/0xc0
[<ffffffff8110f92d>] __hrtimer_run_queues+0xfd/0x280
[<ffffffff811100d8>] hrtimer_interrupt+0xa8/0x190
[<ffffffff81199080>] ? __perf_read_group_add.part.61+0x1a0/0x1a0
[<ffffffff81051bd8>] local_apic_timer_interrupt+0x38/0x60
[<ffffffff817af01d>] smp_apic_timer_interrupt+0x3d/0x50
[<ffffffff817ad15c>] apic_timer_interrupt+0x8c/0xa0
<EOI> [<ffffffff81199080>] ? __perf_read_group_add.part.61+0x1a0/0x1a0
[<ffffffff81123de5>] ? smp_call_function_single+0xd5/0x130
[<ffffffff81123ddb>] ? smp_call_function_single+0xcb/0x130
[<ffffffff81199080>] ? __perf_read_group_add.part.61+0x1a0/0x1a0
[<ffffffff8119765a>] event_function_call+0x10a/0x120
[<ffffffff8119c660>] ? ctx_resched+0x90/0x90
[<ffffffff811971e0>] ? cpu_clock_event_read+0x30/0x30
[<ffffffff811976d0>] ? _perf_event_disable+0x60/0x60
[<ffffffff8119772b>] _perf_event_enable+0x5b/0x70
[<ffffffff81197388>] perf_event_for_each_child+0x38/0xa0
[<ffffffff811976d0>] ? _perf_event_disable+0x60/0x60
[<ffffffff811a0ffd>] perf_ioctl+0x12d/0x3c0
[<ffffffff8134d855>] ? selinux_file_ioctl+0x95/0x1e0
[<ffffffff8124a3a1>] do_vfs_ioctl+0xa1/0x5a0
[<ffffffff81036d29>] ? sched_clock+0x9/0x10
[<ffffffff8124a919>] SyS_ioctl+0x79/0x90
[<ffffffff817ac4b2>] entry_SYSCALL_64_fastpath+0x1a/0xa4
---[ end trace aef202839fe9a71d ]---
Uhhuh. NMI received for unknown reason 2d on CPU 2.
Do you have a strange power saving mode enabled?
Signed-off-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: <stable@vger.kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: http://lkml.kernel.org/r/1457046448-6184-1-git-send-email-kan.liang@intel.com
[ Fixed various typos and other small details. ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-03-04 07:07:28 +08:00
|
|
|
/* Only restore PMU state when it's active. See x86_pmu_disable(). */
|
|
|
|
if (cpuc->enabled)
|
|
|
|
knc_pmu_enable_all(0);
|
2012-10-18 01:05:45 +08:00
|
|
|
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-27 02:12:52 +08:00
|
|
|
PMU_FORMAT_ATTR(event, "config:0-7" );
|
|
|
|
PMU_FORMAT_ATTR(umask, "config:8-15" );
|
|
|
|
PMU_FORMAT_ATTR(edge, "config:18" );
|
|
|
|
PMU_FORMAT_ATTR(inv, "config:23" );
|
|
|
|
PMU_FORMAT_ATTR(cmask, "config:24-31" );
|
|
|
|
|
|
|
|
static struct attribute *intel_knc_formats_attr[] = {
|
|
|
|
&format_attr_event.attr,
|
|
|
|
&format_attr_umask.attr,
|
|
|
|
&format_attr_edge.attr,
|
|
|
|
&format_attr_inv.attr,
|
|
|
|
&format_attr_cmask.attr,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
2013-03-11 17:56:05 +08:00
|
|
|
static const struct x86_pmu knc_pmu __initconst = {
|
2012-09-27 02:12:52 +08:00
|
|
|
.name = "knc",
|
2012-10-18 01:05:45 +08:00
|
|
|
.handle_irq = knc_pmu_handle_irq,
|
2012-09-27 02:12:52 +08:00
|
|
|
.disable_all = knc_pmu_disable_all,
|
|
|
|
.enable_all = knc_pmu_enable_all,
|
|
|
|
.enable = knc_pmu_enable_event,
|
|
|
|
.disable = knc_pmu_disable_event,
|
|
|
|
.hw_config = x86_pmu_hw_config,
|
|
|
|
.schedule_events = x86_schedule_events,
|
|
|
|
.eventsel = MSR_KNC_EVNTSEL0,
|
|
|
|
.perfctr = MSR_KNC_PERFCTR0,
|
|
|
|
.event_map = knc_pmu_event_map,
|
|
|
|
.max_events = ARRAY_SIZE(knc_perfmon_event_map),
|
|
|
|
.apic = 1,
|
2012-10-18 01:03:21 +08:00
|
|
|
.max_period = (1ULL << 39) - 1,
|
2012-09-27 02:12:52 +08:00
|
|
|
.version = 0,
|
|
|
|
.num_counters = 2,
|
2012-10-18 01:03:21 +08:00
|
|
|
.cntval_bits = 40,
|
|
|
|
.cntval_mask = (1ULL << 40) - 1,
|
2012-09-27 02:12:52 +08:00
|
|
|
.get_event_constraints = x86_get_event_constraints,
|
|
|
|
.event_constraints = knc_event_constraints,
|
|
|
|
.format_attrs = intel_knc_formats_attr,
|
|
|
|
};
|
|
|
|
|
|
|
|
__init int knc_pmu_init(void)
|
|
|
|
{
|
|
|
|
x86_pmu = knc_pmu;
|
|
|
|
|
|
|
|
memcpy(hw_cache_event_ids, knc_hw_cache_event_ids,
|
|
|
|
sizeof(hw_cache_event_ids));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|