diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_p6.c')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p6.c | 127 | 
1 files changed, 112 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index e4dd0f7a045..7d0270bd793 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -8,13 +8,106 @@   */  static const u64 p6_perfmon_event_map[] =  { -  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079, -  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0, -  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e, -  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e, -  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4, -  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5, -  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062, +  [PERF_COUNT_HW_CPU_CYCLES]		= 0x0079,	/* CPU_CLK_UNHALTED */ +  [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,	/* INST_RETIRED     */ +  [PERF_COUNT_HW_CACHE_REFERENCES]	= 0x0f2e,	/* L2_RQSTS:M:E:S:I */ +  [PERF_COUNT_HW_CACHE_MISSES]		= 0x012e,	/* L2_RQSTS:I       */ +  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c4,	/* BR_INST_RETIRED  */ +  [PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c5,	/* BR_MISS_PRED_RETIRED */ +  [PERF_COUNT_HW_BUS_CYCLES]		= 0x0062,	/* BUS_DRDY_CLOCKS  */ +  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,	/* RESOURCE_STALLS  */ + +}; + +static __initconst u64 p6_hw_cache_event_ids +				[PERF_COUNT_HW_CACHE_MAX] +				[PERF_COUNT_HW_CACHE_OP_MAX] +				[PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS       */ +                [ C(RESULT_MISS)   ] = 0x0045,	/* DCU_LINES_IN        */ +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0x0f29,	/* L2_LD:M:E:S:I       */ +	}, +        [ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +        }, + }, + [ C(L1I ) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */ +		[ C(RESULT_MISS)   ] = 0x0f28,	/* L2_IFETCH:M:E:S:I  */ +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(LL  ) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0x0025,	/* L2_M_LINES_INM     */ +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(DTLB) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0043,	/* DATA_MEM_REFS      */ +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = 0, +		[ C(RESULT_MISS)   ] = 0, +	}, + }, + [ C(ITLB) ] = { +	[ C(OP_READ) ] = { +		[ C(RESULT_ACCESS) ] = 0x0080,	/* IFU_IFETCH         */ +		[ C(RESULT_MISS)   ] = 0x0085,	/* ITLB_MISS          */ +	}, +	[ 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) ] = 0x00c4,	/* BR_INST_RETIRED      */ +		[ C(RESULT_MISS)   ] = 0x00c5,	/* BR_MISS_PRED_RETIRED */ +        }, +	[ C(OP_WRITE) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, +	[ C(OP_PREFETCH) ] = { +		[ C(RESULT_ACCESS) ] = -1, +		[ C(RESULT_MISS)   ] = -1, +	}, + },  };  static u64 p6_pmu_event_map(int hw_event) @@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =  {  	INTEL_EVENT_CONSTRAINT(0xc1, 0x1),	/* FLOPS */  	INTEL_EVENT_CONSTRAINT(0x10, 0x1),	/* FP_COMP_OPS_EXE */ -	INTEL_EVENT_CONSTRAINT(0x11, 0x1),	/* FP_ASSIST */ +	INTEL_EVENT_CONSTRAINT(0x11, 0x2),	/* FP_ASSIST */  	INTEL_EVENT_CONSTRAINT(0x12, 0x2),	/* MUL */  	INTEL_EVENT_CONSTRAINT(0x13, 0x2),	/* DIV */  	INTEL_EVENT_CONSTRAINT(0x14, 0x1),	/* CYCLES_DIV_BUSY */ @@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)  static inline void  p6_pmu_disable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val = P6_NOP_EVENT; -	if (cpuc->enabled) -		val |= ARCH_PERFMON_EVENTSEL_ENABLE; -  	(void)wrmsrl_safe(hwc->config_base, val);  }  static void p6_pmu_enable_event(struct perf_event *event)  { -	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);  	struct hw_perf_event *hwc = &event->hw;  	u64 val;  	val = hwc->config; -	if (cpuc->enabled) -		val |= ARCH_PERFMON_EVENTSEL_ENABLE; + +	/* +	 * p6 only has a global event enable, set on PerfEvtSel0 +	 * We "disable" events by programming P6_NOP_EVENT +	 * and we rely on p6_pmu_enable_all() being called +	 * to actually enable the events. +	 */  	(void)wrmsrl_safe(hwc->config_base, val);  } @@ -158,5 +251,9 @@ __init int p6_pmu_init(void)  	x86_pmu = p6_pmu; +	memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, +		sizeof(hw_cache_event_ids)); + +  	return 0;  }  |