2011-03-03 10:34:47 +08:00
/*
2011-06-06 16:57:03 +02:00
* Per core / cpu state
*
* Used to coordinate shared registers between HT threads or
* among events on a single PMU .
2011-03-03 10:34:47 +08:00
*/
2011-08-30 20:41:05 -03:00
# include <linux/stddef.h>
# include <linux/types.h>
# include <linux/init.h>
# include <linux/slab.h>
2011-05-26 12:22:53 -04:00
# include <linux/export.h>
2011-08-30 20:41:05 -03:00
# include <asm/hardirq.h>
# include <asm/apic.h>
# include "perf_event.h"
2011-03-03 10:34:47 +08:00
2010-02-26 12:05:05 +01:00
/*
2010-02-01 15:36:30 +01:00
* Intel PerfMon , used on Core and later .
2010-02-26 12:05:05 +01:00
*/
2011-04-27 11:51:41 +02:00
static u64 intel_perfmon_event_map [ PERF_COUNT_HW_MAX ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
[ PERF_COUNT_HW_CPU_CYCLES ] = 0x003c ,
[ PERF_COUNT_HW_INSTRUCTIONS ] = 0x00c0 ,
[ PERF_COUNT_HW_CACHE_REFERENCES ] = 0x4f2e ,
[ PERF_COUNT_HW_CACHE_MISSES ] = 0x412e ,
[ PERF_COUNT_HW_BRANCH_INSTRUCTIONS ] = 0x00c4 ,
[ PERF_COUNT_HW_BRANCH_MISSES ] = 0x00c5 ,
[ PERF_COUNT_HW_BUS_CYCLES ] = 0x013c ,
2011-12-11 00:28:53 +01:00
[ PERF_COUNT_HW_REF_CPU_CYCLES ] = 0x0300 , /* pseudo-encoding */
2010-02-26 12:05:05 +01:00
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_core_event_constraints [ ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
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 */
INTEL_EVENT_CONSTRAINT ( 0x19 , 0x2 ) , /* DELAYED_BYPASS */
INTEL_EVENT_CONSTRAINT ( 0xc1 , 0x1 ) , /* FP_COMP_INSTR_RET */
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_core2_event_constraints [ ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
2010-02-01 15:36:30 +01:00
FIXED_EVENT_CONSTRAINT ( 0x00c0 , 0 ) , /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT ( 0x003c , 1 ) , /* CPU_CLK_UNHALTED.CORE */
2011-12-11 00:28:51 +01:00
FIXED_EVENT_CONSTRAINT ( 0x0300 , 2 ) , /* CPU_CLK_UNHALTED.REF */
2010-02-26 12:05:05 +01:00
INTEL_EVENT_CONSTRAINT ( 0x10 , 0x1 ) , /* FP_COMP_OPS_EXE */
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 */
INTEL_EVENT_CONSTRAINT ( 0x18 , 0x1 ) , /* IDLE_DURING_DIV */
INTEL_EVENT_CONSTRAINT ( 0x19 , 0x2 ) , /* DELAYED_BYPASS */
INTEL_EVENT_CONSTRAINT ( 0xa1 , 0x1 ) , /* RS_UOPS_DISPATCH_CYCLES */
2010-02-01 15:36:30 +01:00
INTEL_EVENT_CONSTRAINT ( 0xc9 , 0x1 ) , /* ITLB_MISS_RETIRED (T30-9) */
2010-02-26 12:05:05 +01:00
INTEL_EVENT_CONSTRAINT ( 0xcb , 0x1 ) , /* MEM_LOAD_RETIRED */
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_nehalem_event_constraints [ ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
2010-02-01 15:36:30 +01:00
FIXED_EVENT_CONSTRAINT ( 0x00c0 , 0 ) , /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT ( 0x003c , 1 ) , /* CPU_CLK_UNHALTED.CORE */
2011-12-11 00:28:51 +01:00
FIXED_EVENT_CONSTRAINT ( 0x0300 , 2 ) , /* CPU_CLK_UNHALTED.REF */
2010-02-26 12:05:05 +01:00
INTEL_EVENT_CONSTRAINT ( 0x40 , 0x3 ) , /* L1D_CACHE_LD */
INTEL_EVENT_CONSTRAINT ( 0x41 , 0x3 ) , /* L1D_CACHE_ST */
INTEL_EVENT_CONSTRAINT ( 0x42 , 0x3 ) , /* L1D_CACHE_LOCK */
INTEL_EVENT_CONSTRAINT ( 0x43 , 0x3 ) , /* L1D_ALL_REF */
INTEL_EVENT_CONSTRAINT ( 0x48 , 0x3 ) , /* L1D_PEND_MISS */
INTEL_EVENT_CONSTRAINT ( 0x4e , 0x3 ) , /* L1D_PREFETCH */
INTEL_EVENT_CONSTRAINT ( 0x51 , 0x3 ) , /* L1D */
INTEL_EVENT_CONSTRAINT ( 0x63 , 0x3 ) , /* CACHE_LOCK_CYCLES */
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct extra_reg intel_nehalem_extra_regs [ ] __read_mostly =
2011-03-03 10:34:47 +08:00
{
2011-06-06 16:57:03 +02:00
INTEL_EVENT_EXTRA_REG ( 0xb7 , MSR_OFFCORE_RSP_0 , 0xffff , RSP_0 ) ,
2011-03-03 10:34:47 +08:00
EVENT_EXTRA_END
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_westmere_event_constraints [ ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
2010-02-01 15:36:30 +01:00
FIXED_EVENT_CONSTRAINT ( 0x00c0 , 0 ) , /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT ( 0x003c , 1 ) , /* CPU_CLK_UNHALTED.CORE */
2011-12-11 00:28:51 +01:00
FIXED_EVENT_CONSTRAINT ( 0x0300 , 2 ) , /* CPU_CLK_UNHALTED.REF */
2010-02-26 12:05:05 +01:00
INTEL_EVENT_CONSTRAINT ( 0x51 , 0x3 ) , /* L1D */
INTEL_EVENT_CONSTRAINT ( 0x60 , 0x1 ) , /* OFFCORE_REQUESTS_OUTSTANDING */
INTEL_EVENT_CONSTRAINT ( 0x63 , 0x3 ) , /* CACHE_LOCK_CYCLES */
2010-06-10 13:25:01 +02:00
INTEL_EVENT_CONSTRAINT ( 0xb3 , 0x1 ) , /* SNOOPQ_REQUEST_OUTSTANDING */
2010-02-26 12:05:05 +01:00
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_snb_event_constraints [ ] __read_mostly =
2011-03-02 21:27:04 +08:00
{
FIXED_EVENT_CONSTRAINT ( 0x00c0 , 0 ) , /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT ( 0x003c , 1 ) , /* CPU_CLK_UNHALTED.CORE */
2011-12-11 00:28:51 +01:00
FIXED_EVENT_CONSTRAINT ( 0x0300 , 2 ) , /* CPU_CLK_UNHALTED.REF */
2011-03-02 21:27:04 +08:00
INTEL_EVENT_CONSTRAINT ( 0x48 , 0x4 ) , /* L1D_PEND_MISS.PENDING */
INTEL_UEVENT_CONSTRAINT ( 0x01c0 , 0x2 ) , /* INST_RETIRED.PREC_DIST */
INTEL_EVENT_CONSTRAINT ( 0xcd , 0x8 ) , /* MEM_TRANS_RETIRED.LOAD_LATENCY */
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct extra_reg intel_westmere_extra_regs [ ] __read_mostly =
2011-03-03 10:34:47 +08:00
{
2011-06-06 16:57:03 +02:00
INTEL_EVENT_EXTRA_REG ( 0xb7 , MSR_OFFCORE_RSP_0 , 0xffff , RSP_0 ) ,
INTEL_EVENT_EXTRA_REG ( 0xbb , MSR_OFFCORE_RSP_1 , 0xffff , RSP_1 ) ,
2011-03-03 10:34:47 +08:00
EVENT_EXTRA_END
} ;
2011-06-29 18:42:36 +03:00
static struct event_constraint intel_v1_event_constraints [ ] __read_mostly =
{
EVENT_CONSTRAINT_END
} ;
2011-04-27 12:02:04 +02:00
static struct event_constraint intel_gen_event_constraints [ ] __read_mostly =
2010-02-26 12:05:05 +01:00
{
2010-02-01 15:36:30 +01:00
FIXED_EVENT_CONSTRAINT ( 0x00c0 , 0 ) , /* INST_RETIRED.ANY */
FIXED_EVENT_CONSTRAINT ( 0x003c , 1 ) , /* CPU_CLK_UNHALTED.CORE */
2011-12-11 00:28:51 +01:00
FIXED_EVENT_CONSTRAINT ( 0x0300 , 2 ) , /* CPU_CLK_UNHALTED.REF */
2010-02-26 12:05:05 +01:00
EVENT_CONSTRAINT_END
} ;
2011-06-06 16:57:12 +02:00
static struct extra_reg intel_snb_extra_regs [ ] __read_mostly = {
INTEL_EVENT_EXTRA_REG ( 0xb7 , MSR_OFFCORE_RSP_0 , 0x3fffffffffull , RSP_0 ) ,
INTEL_EVENT_EXTRA_REG ( 0xbb , MSR_OFFCORE_RSP_1 , 0x3fffffffffull , RSP_1 ) ,
EVENT_EXTRA_END
} ;
2010-02-26 12:05:05 +01:00
static u64 intel_pmu_event_map ( int hw_event )
{
return intel_perfmon_event_map [ hw_event ] ;
}
2011-03-02 21:27:04 +08:00
static __initconst const u64 snb_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 ) ] = 0xf1d0 , /* MEM_UOP_RETIRED.LOADS */
[ C ( RESULT_MISS ) ] = 0x0151 , /* L1D.REPLACEMENT */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0xf2d0 , /* MEM_UOP_RETIRED.STORES */
[ C ( RESULT_MISS ) ] = 0x0851 , /* L1D.ALL_M_REPLACEMENT */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0x024e , /* HW_PRE_REQ.DL1_MISS */
} ,
} ,
[ C ( L1I ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0x0280 , /* ICACHE.MISSES */
} ,
[ 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 ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
2011-03-02 21:27:04 +08:00
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2011-03-02 21:27:04 +08:00
} ,
[ C ( OP_WRITE ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
2011-03-02 21:27:04 +08:00
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2011-03-02 21:27:04 +08:00
} ,
[ C ( OP_PREFETCH ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
2011-03-02 21:27:04 +08:00
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2011-03-02 21:27:04 +08:00
} ,
} ,
[ C ( DTLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x81d0 , /* MEM_UOP_RETIRED.ALL_LOADS */
[ C ( RESULT_MISS ) ] = 0x0108 , /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x82d0 , /* MEM_UOP_RETIRED.ALL_STORES */
[ C ( RESULT_MISS ) ] = 0x0149 , /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0x0 ,
} ,
} ,
[ C ( ITLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x1085 , /* ITLB_MISSES.STLB_HIT */
[ C ( RESULT_MISS ) ] = 0x0185 , /* ITLB_MISSES.CAUSES_A_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 ) ] = 0x00c4 , /* BR_INST_RETIRED.ALL_BRANCHES */
[ C ( RESULT_MISS ) ] = 0x00c5 , /* BR_MISP_RETIRED.ALL_BRANCHES */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
2011-04-22 23:37:06 +02:00
[ C ( NODE ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
2011-03-02 21:27:04 +08:00
} ;
2010-03-29 13:09:53 +02:00
static __initconst const u64 westmere_hw_cache_event_ids
2010-02-26 12:05:05 +01:00
[ 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 ) ] = 0x010b , /* MEM_INST_RETIRED.LOADS */
[ C ( RESULT_MISS ) ] = 0x0151 , /* L1D.REPL */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x020b , /* MEM_INST_RETURED.STORES */
[ C ( RESULT_MISS ) ] = 0x0251 , /* L1D.M_REPL */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x014e , /* L1D_PREFETCH.REQUESTS */
[ C ( RESULT_MISS ) ] = 0x024e , /* L1D_PREFETCH.MISS */
} ,
} ,
[ C ( L1I ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0380 , /* L1I.READS */
[ C ( RESULT_MISS ) ] = 0x0280 , /* L1I.MISSES */
} ,
[ 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 ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
2011-03-03 10:34:48 +08:00
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
2011-03-03 10:34:48 +08:00
/*
* Use RFO , not WRITEBACK , because a write miss would typically occur
* on RFO .
*/
2010-02-26 12:05:05 +01:00
[ C ( OP_WRITE ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
2011-03-03 10:34:48 +08:00
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
[ C ( OP_PREFETCH ) ] = {
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
2011-03-03 10:34:48 +08:00
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
2011-04-23 00:57:42 +02:00
/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
} ,
[ C ( DTLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x010b , /* MEM_INST_RETIRED.LOADS */
[ C ( RESULT_MISS ) ] = 0x0108 , /* DTLB_LOAD_MISSES.ANY */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x020b , /* MEM_INST_RETURED.STORES */
[ C ( RESULT_MISS ) ] = 0x010c , /* MEM_STORE_RETIRED.DTLB_MISS */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0x0 ,
} ,
} ,
[ C ( ITLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01c0 , /* INST_RETIRED.ANY_P */
[ C ( RESULT_MISS ) ] = 0x0185 , /* ITLB_MISSES.ANY */
} ,
[ 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.ALL_BRANCHES */
[ C ( RESULT_MISS ) ] = 0x03e8 , /* BPU_CLEARS.ANY */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
2011-04-22 23:37:06 +02:00
[ C ( NODE ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
} ,
2010-02-26 12:05:05 +01:00
} ;
2011-03-03 10:34:48 +08:00
/*
2011-04-23 00:57:42 +02:00
* Nehalem / Westmere MSR_OFFCORE_RESPONSE bits ;
* See IA32 SDM Vol 3 B 30.6 .1 .3
2011-03-03 10:34:48 +08:00
*/
2011-04-23 00:57:42 +02:00
# define NHM_DMND_DATA_RD (1 << 0)
# define NHM_DMND_RFO (1 << 1)
# define NHM_DMND_IFETCH (1 << 2)
# define NHM_DMND_WB (1 << 3)
# define NHM_PF_DATA_RD (1 << 4)
# define NHM_PF_DATA_RFO (1 << 5)
# define NHM_PF_IFETCH (1 << 6)
# define NHM_OFFCORE_OTHER (1 << 7)
# define NHM_UNCORE_HIT (1 << 8)
# define NHM_OTHER_CORE_HIT_SNP (1 << 9)
# define NHM_OTHER_CORE_HITM (1 << 10)
/* reserved */
# define NHM_REMOTE_CACHE_FWD (1 << 12)
# define NHM_REMOTE_DRAM (1 << 13)
# define NHM_LOCAL_DRAM (1 << 14)
# define NHM_NON_DRAM (1 << 15)
perf/x86: Fix local vs remote memory events for NHM/WSM
Verified using the below proglet.. before:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,101,554 node-stores
2,096,931 node-store-misses
5.021546079 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
501,137 node-stores
199 node-store-misses
5.124451068 seconds time elapsed
After:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,107,516 node-stores
2,097,187 node-store-misses
5.012755149 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
2,063,355 node-stores
165 node-store-misses
5.082091494 seconds time elapsed
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <numaif.h>
#include <stdlib.h>
#define SIZE (32*1024*1024)
volatile int done;
void sig_done(int sig)
{
done = 1;
}
int main(int argc, char **argv)
{
cpu_set_t *mask, *mask2;
size_t size;
int i, err, t;
int nrcpus = 1024;
char *mem;
unsigned long nodemask = 0x01; /* node 0 */
DIR *node;
struct dirent *de;
int read = 0;
int local = 0;
if (argc < 2) {
printf("usage: %s [0-3]\n", argv[0]);
printf(" bit0 - local/remote\n");
printf(" bit1 - read/write\n");
exit(0);
}
switch (atoi(argv[1])) {
case 0:
printf("remote write\n");
break;
case 1:
printf("local write\n");
local = 1;
break;
case 2:
printf("remote read\n");
read = 1;
break;
case 3:
printf("local read\n");
local = 1;
read = 1;
break;
}
mask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, mask);
node = opendir("/sys/devices/system/node/node0/");
if (!node)
perror("opendir");
while ((de = readdir(node))) {
int cpu;
if (sscanf(de->d_name, "cpu%d", &cpu) == 1)
CPU_SET_S(cpu, size, mask);
}
closedir(node);
mask2 = CPU_ALLOC(nrcpus);
CPU_ZERO_S(size, mask2);
for (i = 0; i < size; i++)
CPU_SET_S(i, size, mask2);
CPU_XOR_S(size, mask2, mask2, mask); // invert
if (!local)
mask = mask2;
err = sched_setaffinity(0, size, mask);
if (err)
perror("sched_setaffinity");
mem = mmap(0, SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
err = mbind(mem, SIZE, MPOL_BIND, &nodemask, 8*sizeof(nodemask), MPOL_MF_MOVE);
if (err)
perror("mbind");
signal(SIGALRM, sig_done);
alarm(5);
if (!read) {
while (!done) {
for (i = 0; i < SIZE; i++)
mem[i] = 0x01;
}
} else {
while (!done) {
for (i = 0; i < SIZE; i++)
t += *(volatile char *)(mem + i);
}
}
return 0;
}
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/n/tip-tq73sxus35xmqpojf7ootxgs@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-03-05 23:59:25 +01:00
# define NHM_LOCAL (NHM_LOCAL_DRAM|NHM_REMOTE_CACHE_FWD)
# define NHM_REMOTE (NHM_REMOTE_DRAM)
2011-04-23 00:57:42 +02:00
# define NHM_DMND_READ (NHM_DMND_DATA_RD)
# define NHM_DMND_WRITE (NHM_DMND_RFO|NHM_DMND_WB)
# define NHM_DMND_PREFETCH (NHM_PF_DATA_RD|NHM_PF_DATA_RFO)
# define NHM_L3_HIT (NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM)
perf/x86: Fix local vs remote memory events for NHM/WSM
Verified using the below proglet.. before:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,101,554 node-stores
2,096,931 node-store-misses
5.021546079 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
501,137 node-stores
199 node-store-misses
5.124451068 seconds time elapsed
After:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,107,516 node-stores
2,097,187 node-store-misses
5.012755149 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
2,063,355 node-stores
165 node-store-misses
5.082091494 seconds time elapsed
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <numaif.h>
#include <stdlib.h>
#define SIZE (32*1024*1024)
volatile int done;
void sig_done(int sig)
{
done = 1;
}
int main(int argc, char **argv)
{
cpu_set_t *mask, *mask2;
size_t size;
int i, err, t;
int nrcpus = 1024;
char *mem;
unsigned long nodemask = 0x01; /* node 0 */
DIR *node;
struct dirent *de;
int read = 0;
int local = 0;
if (argc < 2) {
printf("usage: %s [0-3]\n", argv[0]);
printf(" bit0 - local/remote\n");
printf(" bit1 - read/write\n");
exit(0);
}
switch (atoi(argv[1])) {
case 0:
printf("remote write\n");
break;
case 1:
printf("local write\n");
local = 1;
break;
case 2:
printf("remote read\n");
read = 1;
break;
case 3:
printf("local read\n");
local = 1;
read = 1;
break;
}
mask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, mask);
node = opendir("/sys/devices/system/node/node0/");
if (!node)
perror("opendir");
while ((de = readdir(node))) {
int cpu;
if (sscanf(de->d_name, "cpu%d", &cpu) == 1)
CPU_SET_S(cpu, size, mask);
}
closedir(node);
mask2 = CPU_ALLOC(nrcpus);
CPU_ZERO_S(size, mask2);
for (i = 0; i < size; i++)
CPU_SET_S(i, size, mask2);
CPU_XOR_S(size, mask2, mask2, mask); // invert
if (!local)
mask = mask2;
err = sched_setaffinity(0, size, mask);
if (err)
perror("sched_setaffinity");
mem = mmap(0, SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
err = mbind(mem, SIZE, MPOL_BIND, &nodemask, 8*sizeof(nodemask), MPOL_MF_MOVE);
if (err)
perror("mbind");
signal(SIGALRM, sig_done);
alarm(5);
if (!read) {
while (!done) {
for (i = 0; i < SIZE; i++)
mem[i] = 0x01;
}
} else {
while (!done) {
for (i = 0; i < SIZE; i++)
t += *(volatile char *)(mem + i);
}
}
return 0;
}
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/n/tip-tq73sxus35xmqpojf7ootxgs@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-03-05 23:59:25 +01:00
# define NHM_L3_MISS (NHM_NON_DRAM|NHM_LOCAL_DRAM|NHM_REMOTE_DRAM|NHM_REMOTE_CACHE_FWD)
2011-04-23 00:57:42 +02:00
# define NHM_L3_ACCESS (NHM_L3_HIT|NHM_L3_MISS)
2011-03-03 10:34:48 +08:00
static __initconst const u64 nehalem_hw_cache_extra_regs
[ PERF_COUNT_HW_CACHE_MAX ]
[ PERF_COUNT_HW_CACHE_OP_MAX ]
[ PERF_COUNT_HW_CACHE_RESULT_MAX ] =
{
[ C ( LL ) ] = {
[ C ( OP_READ ) ] = {
2011-04-23 00:57:42 +02:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_READ | NHM_L3_ACCESS ,
[ C ( RESULT_MISS ) ] = NHM_DMND_READ | NHM_L3_MISS ,
2011-03-03 10:34:48 +08:00
} ,
[ C ( OP_WRITE ) ] = {
2011-04-23 00:57:42 +02:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_WRITE | NHM_L3_ACCESS ,
[ C ( RESULT_MISS ) ] = NHM_DMND_WRITE | NHM_L3_MISS ,
2011-03-03 10:34:48 +08:00
} ,
[ C ( OP_PREFETCH ) ] = {
2011-04-23 00:57:42 +02:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_PREFETCH | NHM_L3_ACCESS ,
[ C ( RESULT_MISS ) ] = NHM_DMND_PREFETCH | NHM_L3_MISS ,
2011-03-03 10:34:48 +08:00
} ,
2011-04-22 23:37:06 +02:00
} ,
[ C ( NODE ) ] = {
[ C ( OP_READ ) ] = {
perf/x86: Fix local vs remote memory events for NHM/WSM
Verified using the below proglet.. before:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,101,554 node-stores
2,096,931 node-store-misses
5.021546079 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
501,137 node-stores
199 node-store-misses
5.124451068 seconds time elapsed
After:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,107,516 node-stores
2,097,187 node-store-misses
5.012755149 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
2,063,355 node-stores
165 node-store-misses
5.082091494 seconds time elapsed
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <numaif.h>
#include <stdlib.h>
#define SIZE (32*1024*1024)
volatile int done;
void sig_done(int sig)
{
done = 1;
}
int main(int argc, char **argv)
{
cpu_set_t *mask, *mask2;
size_t size;
int i, err, t;
int nrcpus = 1024;
char *mem;
unsigned long nodemask = 0x01; /* node 0 */
DIR *node;
struct dirent *de;
int read = 0;
int local = 0;
if (argc < 2) {
printf("usage: %s [0-3]\n", argv[0]);
printf(" bit0 - local/remote\n");
printf(" bit1 - read/write\n");
exit(0);
}
switch (atoi(argv[1])) {
case 0:
printf("remote write\n");
break;
case 1:
printf("local write\n");
local = 1;
break;
case 2:
printf("remote read\n");
read = 1;
break;
case 3:
printf("local read\n");
local = 1;
read = 1;
break;
}
mask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, mask);
node = opendir("/sys/devices/system/node/node0/");
if (!node)
perror("opendir");
while ((de = readdir(node))) {
int cpu;
if (sscanf(de->d_name, "cpu%d", &cpu) == 1)
CPU_SET_S(cpu, size, mask);
}
closedir(node);
mask2 = CPU_ALLOC(nrcpus);
CPU_ZERO_S(size, mask2);
for (i = 0; i < size; i++)
CPU_SET_S(i, size, mask2);
CPU_XOR_S(size, mask2, mask2, mask); // invert
if (!local)
mask = mask2;
err = sched_setaffinity(0, size, mask);
if (err)
perror("sched_setaffinity");
mem = mmap(0, SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
err = mbind(mem, SIZE, MPOL_BIND, &nodemask, 8*sizeof(nodemask), MPOL_MF_MOVE);
if (err)
perror("mbind");
signal(SIGALRM, sig_done);
alarm(5);
if (!read) {
while (!done) {
for (i = 0; i < SIZE; i++)
mem[i] = 0x01;
}
} else {
while (!done) {
for (i = 0; i < SIZE; i++)
t += *(volatile char *)(mem + i);
}
}
return 0;
}
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/n/tip-tq73sxus35xmqpojf7ootxgs@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-03-05 23:59:25 +01:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_READ | NHM_LOCAL | NHM_REMOTE ,
[ C ( RESULT_MISS ) ] = NHM_DMND_READ | NHM_REMOTE ,
2011-04-22 23:37:06 +02:00
} ,
[ C ( OP_WRITE ) ] = {
perf/x86: Fix local vs remote memory events for NHM/WSM
Verified using the below proglet.. before:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,101,554 node-stores
2,096,931 node-store-misses
5.021546079 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
501,137 node-stores
199 node-store-misses
5.124451068 seconds time elapsed
After:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,107,516 node-stores
2,097,187 node-store-misses
5.012755149 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
2,063,355 node-stores
165 node-store-misses
5.082091494 seconds time elapsed
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <numaif.h>
#include <stdlib.h>
#define SIZE (32*1024*1024)
volatile int done;
void sig_done(int sig)
{
done = 1;
}
int main(int argc, char **argv)
{
cpu_set_t *mask, *mask2;
size_t size;
int i, err, t;
int nrcpus = 1024;
char *mem;
unsigned long nodemask = 0x01; /* node 0 */
DIR *node;
struct dirent *de;
int read = 0;
int local = 0;
if (argc < 2) {
printf("usage: %s [0-3]\n", argv[0]);
printf(" bit0 - local/remote\n");
printf(" bit1 - read/write\n");
exit(0);
}
switch (atoi(argv[1])) {
case 0:
printf("remote write\n");
break;
case 1:
printf("local write\n");
local = 1;
break;
case 2:
printf("remote read\n");
read = 1;
break;
case 3:
printf("local read\n");
local = 1;
read = 1;
break;
}
mask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, mask);
node = opendir("/sys/devices/system/node/node0/");
if (!node)
perror("opendir");
while ((de = readdir(node))) {
int cpu;
if (sscanf(de->d_name, "cpu%d", &cpu) == 1)
CPU_SET_S(cpu, size, mask);
}
closedir(node);
mask2 = CPU_ALLOC(nrcpus);
CPU_ZERO_S(size, mask2);
for (i = 0; i < size; i++)
CPU_SET_S(i, size, mask2);
CPU_XOR_S(size, mask2, mask2, mask); // invert
if (!local)
mask = mask2;
err = sched_setaffinity(0, size, mask);
if (err)
perror("sched_setaffinity");
mem = mmap(0, SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
err = mbind(mem, SIZE, MPOL_BIND, &nodemask, 8*sizeof(nodemask), MPOL_MF_MOVE);
if (err)
perror("mbind");
signal(SIGALRM, sig_done);
alarm(5);
if (!read) {
while (!done) {
for (i = 0; i < SIZE; i++)
mem[i] = 0x01;
}
} else {
while (!done) {
for (i = 0; i < SIZE; i++)
t += *(volatile char *)(mem + i);
}
}
return 0;
}
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/n/tip-tq73sxus35xmqpojf7ootxgs@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-03-05 23:59:25 +01:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_WRITE | NHM_LOCAL | NHM_REMOTE ,
[ C ( RESULT_MISS ) ] = NHM_DMND_WRITE | NHM_REMOTE ,
2011-04-22 23:37:06 +02:00
} ,
[ C ( OP_PREFETCH ) ] = {
perf/x86: Fix local vs remote memory events for NHM/WSM
Verified using the below proglet.. before:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,101,554 node-stores
2,096,931 node-store-misses
5.021546079 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
501,137 node-stores
199 node-store-misses
5.124451068 seconds time elapsed
After:
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 0
remote write
Performance counter stats for './numa 0':
2,107,516 node-stores
2,097,187 node-store-misses
5.012755149 seconds time elapsed
[root@westmere ~]# perf stat -e node-stores -e node-store-misses ./numa 1
local write
Performance counter stats for './numa 1':
2,063,355 node-stores
165 node-store-misses
5.082091494 seconds time elapsed
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <numaif.h>
#include <stdlib.h>
#define SIZE (32*1024*1024)
volatile int done;
void sig_done(int sig)
{
done = 1;
}
int main(int argc, char **argv)
{
cpu_set_t *mask, *mask2;
size_t size;
int i, err, t;
int nrcpus = 1024;
char *mem;
unsigned long nodemask = 0x01; /* node 0 */
DIR *node;
struct dirent *de;
int read = 0;
int local = 0;
if (argc < 2) {
printf("usage: %s [0-3]\n", argv[0]);
printf(" bit0 - local/remote\n");
printf(" bit1 - read/write\n");
exit(0);
}
switch (atoi(argv[1])) {
case 0:
printf("remote write\n");
break;
case 1:
printf("local write\n");
local = 1;
break;
case 2:
printf("remote read\n");
read = 1;
break;
case 3:
printf("local read\n");
local = 1;
read = 1;
break;
}
mask = CPU_ALLOC(nrcpus);
size = CPU_ALLOC_SIZE(nrcpus);
CPU_ZERO_S(size, mask);
node = opendir("/sys/devices/system/node/node0/");
if (!node)
perror("opendir");
while ((de = readdir(node))) {
int cpu;
if (sscanf(de->d_name, "cpu%d", &cpu) == 1)
CPU_SET_S(cpu, size, mask);
}
closedir(node);
mask2 = CPU_ALLOC(nrcpus);
CPU_ZERO_S(size, mask2);
for (i = 0; i < size; i++)
CPU_SET_S(i, size, mask2);
CPU_XOR_S(size, mask2, mask2, mask); // invert
if (!local)
mask = mask2;
err = sched_setaffinity(0, size, mask);
if (err)
perror("sched_setaffinity");
mem = mmap(0, SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
err = mbind(mem, SIZE, MPOL_BIND, &nodemask, 8*sizeof(nodemask), MPOL_MF_MOVE);
if (err)
perror("mbind");
signal(SIGALRM, sig_done);
alarm(5);
if (!read) {
while (!done) {
for (i = 0; i < SIZE; i++)
mem[i] = 0x01;
}
} else {
while (!done) {
for (i = 0; i < SIZE; i++)
t += *(volatile char *)(mem + i);
}
}
return 0;
}
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Cc: <stable@kernel.org>
Link: http://lkml.kernel.org/n/tip-tq73sxus35xmqpojf7ootxgs@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2012-03-05 23:59:25 +01:00
[ C ( RESULT_ACCESS ) ] = NHM_DMND_PREFETCH | NHM_LOCAL | NHM_REMOTE ,
[ C ( RESULT_MISS ) ] = NHM_DMND_PREFETCH | NHM_REMOTE ,
2011-04-22 23:37:06 +02:00
} ,
} ,
2011-03-03 10:34:48 +08:00
} ;
2010-03-29 13:09:53 +02:00
static __initconst const u64 nehalem_hw_cache_event_ids
2010-02-26 12:05:05 +01:00
[ PERF_COUNT_HW_CACHE_MAX ]
[ PERF_COUNT_HW_CACHE_OP_MAX ]
[ PERF_COUNT_HW_CACHE_RESULT_MAX ] =
{
[ C ( L1D ) ] = {
[ C ( OP_READ ) ] = {
perf, x86: Update/fix Intel Nehalem cache events
Change the Nehalem cache events to use retired memory instruction counters
(similar to Westmere), this greatly improves the provided stats.
Using:
main ()
{
int i;
for (i = 0; i < 1000000000; i++) {
asm("mov (%%rsp), %%rbx;"
"mov %%rbx, (%%rsp);" : : : "rbx");
}
}
We find:
$ perf stat --repeat 10 -e instructions:u -e l1-dcache-loads:u -e l1-dcache-stores:u ./loop_1b_loads+stores
Performance counter stats for './loop_1b_loads+stores' (10 runs):
4,000,081,056 instructions:u # 0.000 IPC ( +- 0.000% )
4,999,502,846 l1-dcache-loads:u ( +- 0.008% )
1,000,034,832 l1-dcache-stores:u ( +- 0.000% )
1.565184942 seconds time elapsed ( +- 0.005% )
The 5b is surprising - we'd expect 1b:
$ perf stat --repeat 10 -e instructions:u -e r10b:u -e l1-dcache-stores:u ./loop_1b_loads+stores
Performance counter stats for './loop_1b_loads+stores' (10 runs):
4,000,081,054 instructions:u # 0.000 IPC ( +- 0.000% )
1,000,021,961 r10b:u ( +- 0.000% )
1,000,030,951 l1-dcache-stores:u ( +- 0.000% )
1.565055422 seconds time elapsed ( +- 0.003% )
Which this patch thus fixes.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Lin Ming <ming.m.lin@intel.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Link: http://lkml.kernel.org/n/tip-q9rtru7b7840tws75xzboapv@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2011-04-22 13:39:56 +02:00
[ C ( RESULT_ACCESS ) ] = 0x010b , /* MEM_INST_RETIRED.LOADS */
[ C ( RESULT_MISS ) ] = 0x0151 , /* L1D.REPL */
2010-02-26 12:05:05 +01:00
} ,
[ C ( OP_WRITE ) ] = {
perf, x86: Update/fix Intel Nehalem cache events
Change the Nehalem cache events to use retired memory instruction counters
(similar to Westmere), this greatly improves the provided stats.
Using:
main ()
{
int i;
for (i = 0; i < 1000000000; i++) {
asm("mov (%%rsp), %%rbx;"
"mov %%rbx, (%%rsp);" : : : "rbx");
}
}
We find:
$ perf stat --repeat 10 -e instructions:u -e l1-dcache-loads:u -e l1-dcache-stores:u ./loop_1b_loads+stores
Performance counter stats for './loop_1b_loads+stores' (10 runs):
4,000,081,056 instructions:u # 0.000 IPC ( +- 0.000% )
4,999,502,846 l1-dcache-loads:u ( +- 0.008% )
1,000,034,832 l1-dcache-stores:u ( +- 0.000% )
1.565184942 seconds time elapsed ( +- 0.005% )
The 5b is surprising - we'd expect 1b:
$ perf stat --repeat 10 -e instructions:u -e r10b:u -e l1-dcache-stores:u ./loop_1b_loads+stores
Performance counter stats for './loop_1b_loads+stores' (10 runs):
4,000,081,054 instructions:u # 0.000 IPC ( +- 0.000% )
1,000,021,961 r10b:u ( +- 0.000% )
1,000,030,951 l1-dcache-stores:u ( +- 0.000% )
1.565055422 seconds time elapsed ( +- 0.003% )
Which this patch thus fixes.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Lin Ming <ming.m.lin@intel.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Link: http://lkml.kernel.org/n/tip-q9rtru7b7840tws75xzboapv@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2011-04-22 13:39:56 +02:00
[ C ( RESULT_ACCESS ) ] = 0x020b , /* MEM_INST_RETURED.STORES */
[ C ( RESULT_MISS ) ] = 0x0251 , /* L1D.M_REPL */
2010-02-26 12:05:05 +01:00
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x014e , /* L1D_PREFETCH.REQUESTS */
[ C ( RESULT_MISS ) ] = 0x024e , /* L1D_PREFETCH.MISS */
} ,
} ,
[ C ( L1I ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0380 , /* L1I.READS */
[ C ( RESULT_MISS ) ] = 0x0280 , /* L1I.MISSES */
} ,
[ 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 ) ] = {
2011-03-03 10:34:48 +08:00
/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
2011-03-03 10:34:48 +08:00
/*
* Use RFO , not WRITEBACK , because a write miss would typically occur
* on RFO .
*/
2010-02-26 12:05:05 +01:00
[ C ( OP_WRITE ) ] = {
2011-03-03 10:34:48 +08:00
/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
[ C ( OP_PREFETCH ) ] = {
2011-03-03 10:34:48 +08:00
/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
[ C ( RESULT_MISS ) ] = 0x01b7 ,
2010-02-26 12:05:05 +01:00
} ,
} ,
[ C ( DTLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0f40 , /* L1D_CACHE_LD.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x0108 , /* DTLB_LOAD_MISSES.ANY */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0f41 , /* L1D_CACHE_ST.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x010c , /* MEM_STORE_RETIRED.DTLB_MISS */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0x0 ,
} ,
} ,
[ C ( ITLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01c0 , /* INST_RETIRED.ANY_P */
[ C ( RESULT_MISS ) ] = 0x20c8 , /* ITLB_MISS_RETIRED */
} ,
[ 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.ALL_BRANCHES */
[ C ( RESULT_MISS ) ] = 0x03e8 , /* BPU_CLEARS.ANY */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
2011-04-22 23:37:06 +02:00
[ C ( NODE ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x01b7 ,
[ C ( RESULT_MISS ) ] = 0x01b7 ,
} ,
} ,
2010-02-26 12:05:05 +01:00
} ;
2010-03-29 13:09:53 +02:00
static __initconst const u64 core2_hw_cache_event_ids
2010-02-26 12:05:05 +01:00
[ 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 ) ] = 0x0f40 , /* L1D_CACHE_LD.MESI */
[ C ( RESULT_MISS ) ] = 0x0140 , /* L1D_CACHE_LD.I_STATE */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0f41 , /* L1D_CACHE_ST.MESI */
[ C ( RESULT_MISS ) ] = 0x0141 , /* L1D_CACHE_ST.I_STATE */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x104e , /* L1D_PREFETCH.REQUESTS */
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( L1I ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0080 , /* L1I.READS */
[ C ( RESULT_MISS ) ] = 0x0081 , /* L1I.MISSES */
} ,
[ 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 ) ] = 0x4f29 , /* L2_LD.MESI */
[ C ( RESULT_MISS ) ] = 0x4129 , /* L2_LD.ISTATE */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x4f2A , /* L2_ST.MESI */
[ C ( RESULT_MISS ) ] = 0x412A , /* L2_ST.ISTATE */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0 ,
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( DTLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0f40 , /* L1D_CACHE_LD.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x0208 , /* DTLB_MISSES.MISS_LD */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0f41 , /* L1D_CACHE_ST.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x0808 , /* DTLB_MISSES.MISS_ST */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0 ,
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( ITLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x00c0 , /* INST_RETIRED.ANY_P */
[ C ( RESULT_MISS ) ] = 0x1282 , /* ITLBMISSES */
} ,
[ 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.ANY */
[ C ( RESULT_MISS ) ] = 0x00c5 , /* BP_INST_RETIRED.MISPRED */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
} ;
2010-03-29 13:09:53 +02:00
static __initconst const u64 atom_hw_cache_event_ids
2010-02-26 12:05:05 +01:00
[ 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 ) ] = 0x2140 , /* L1D_CACHE.LD */
[ C ( RESULT_MISS ) ] = 0 ,
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x2240 , /* L1D_CACHE.ST */
[ C ( RESULT_MISS ) ] = 0 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0 ,
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( L1I ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x0380 , /* L1I.READS */
[ C ( RESULT_MISS ) ] = 0x0280 , /* L1I.MISSES */
} ,
[ 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 ) ] = 0x4f29 , /* L2_LD.MESI */
[ C ( RESULT_MISS ) ] = 0x4129 , /* L2_LD.ISTATE */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x4f2A , /* L2_ST.MESI */
[ C ( RESULT_MISS ) ] = 0x412A , /* L2_ST.ISTATE */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0 ,
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( DTLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x2140 , /* L1D_CACHE_LD.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x0508 , /* DTLB_MISSES.MISS_LD */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x2240 , /* L1D_CACHE_ST.MESI (alias) */
[ C ( RESULT_MISS ) ] = 0x0608 , /* DTLB_MISSES.MISS_ST */
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = 0 ,
[ C ( RESULT_MISS ) ] = 0 ,
} ,
} ,
[ C ( ITLB ) ] = {
[ C ( OP_READ ) ] = {
[ C ( RESULT_ACCESS ) ] = 0x00c0 , /* INST_RETIRED.ANY_P */
[ C ( RESULT_MISS ) ] = 0x0282 , /* ITLB.MISSES */
} ,
[ 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.ANY */
[ C ( RESULT_MISS ) ] = 0x00c5 , /* BP_INST_RETIRED.MISPRED */
} ,
[ C ( OP_WRITE ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
[ C ( OP_PREFETCH ) ] = {
[ C ( RESULT_ACCESS ) ] = - 1 ,
[ C ( RESULT_MISS ) ] = - 1 ,
} ,
} ,
} ;
2012-02-09 23:20:57 +01:00
static inline bool intel_pmu_needs_lbr_smpl ( struct perf_event * event )
{
/* user explicitly requested branch sampling */
if ( has_branch_stack ( event ) )
return true ;
/* implicit branch sampling to correct PEBS skid */
if ( x86_pmu . intel_cap . pebs_trap & & event - > attr . precise_ip > 1 )
return true ;
return false ;
}
2010-02-26 12:05:05 +01:00
static void intel_pmu_disable_all ( void )
{
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
wrmsrl ( MSR_CORE_PERF_GLOBAL_CTRL , 0 ) ;
if ( test_bit ( X86_PMC_IDX_FIXED_BTS , cpuc - > active_mask ) )
intel_pmu_disable_bts ( ) ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
intel_pmu_pebs_disable_all ( ) ;
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_disable_all ( ) ;
2010-02-26 12:05:05 +01:00
}
2010-03-26 14:08:44 +01:00
static void intel_pmu_enable_all ( int added )
2010-02-26 12:05:05 +01:00
{
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
2010-03-08 13:57:14 +01:00
intel_pmu_pebs_enable_all ( ) ;
intel_pmu_lbr_enable_all ( ) ;
2011-10-05 14:01:21 +02:00
wrmsrl ( MSR_CORE_PERF_GLOBAL_CTRL ,
x86_pmu . intel_ctrl & ~ cpuc - > intel_ctrl_guest_mask ) ;
2010-02-26 12:05:05 +01:00
if ( test_bit ( X86_PMC_IDX_FIXED_BTS , cpuc - > active_mask ) ) {
struct perf_event * event =
cpuc - > events [ X86_PMC_IDX_FIXED_BTS ] ;
if ( WARN_ON_ONCE ( ! event ) )
return ;
intel_pmu_enable_bts ( event - > hw . config ) ;
}
}
2010-03-26 14:08:44 +01:00
/*
* Workaround for :
* Intel Errata AAK100 ( model 26 )
* Intel Errata AAP53 ( model 30 )
2010-03-29 16:37:17 +02:00
* Intel Errata BD53 ( model 44 )
2010-03-26 14:08:44 +01:00
*
2010-08-06 13:39:08 +08:00
* The official story :
* These chips need to be ' reset ' when adding counters by programming the
* magic three ( non - counting ) events 0x4300B5 , 0x4300D2 , and 0x4300B1 either
* in sequence on the same PMC or on different PMCs .
*
* In practise it appears some of these events do in fact count , and
* we need to programm all 4 events .
2010-03-26 14:08:44 +01:00
*/
2010-08-06 13:39:08 +08:00
static void intel_pmu_nhm_workaround ( void )
2010-03-26 14:08:44 +01:00
{
2010-08-06 13:39:08 +08:00
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
static const unsigned long nhm_magic [ 4 ] = {
0x4300B5 ,
0x4300D2 ,
0x4300B1 ,
0x4300B1
} ;
struct perf_event * event ;
int i ;
2010-03-26 14:08:44 +01:00
2010-08-06 13:39:08 +08:00
/*
* The Errata requires below steps :
* 1 ) Clear MSR_IA32_PEBS_ENABLE and MSR_CORE_PERF_GLOBAL_CTRL ;
* 2 ) Configure 4 PERFEVTSELx with the magic events and clear
* the corresponding PMCx ;
* 3 ) set bit0 ~ bit3 of MSR_CORE_PERF_GLOBAL_CTRL ;
* 4 ) Clear MSR_CORE_PERF_GLOBAL_CTRL ;
* 5 ) Clear 4 pairs of ERFEVTSELx and PMCx ;
*/
2010-03-26 14:08:44 +01:00
2010-08-06 13:39:08 +08:00
/*
* The real steps we choose are a little different from above .
* A ) To reduce MSR operations , we don ' t run step 1 ) as they
* are already cleared before this function is called ;
* B ) Call x86_perf_event_update to save PMCx before configuring
* PERFEVTSELx with magic number ;
* C ) With step 5 ) , we do clear only when the PERFEVTSELx is
* not used currently .
* D ) Call x86_perf_event_set_period to restore PMCx ;
*/
2010-03-26 14:08:44 +01:00
2010-08-06 13:39:08 +08:00
/* We always operate 4 pairs of PERF Counters */
for ( i = 0 ; i < 4 ; i + + ) {
event = cpuc - > events [ i ] ;
if ( event )
x86_perf_event_update ( event ) ;
}
2010-03-26 14:08:44 +01:00
2010-08-06 13:39:08 +08:00
for ( i = 0 ; i < 4 ; i + + ) {
wrmsrl ( MSR_ARCH_PERFMON_EVENTSEL0 + i , nhm_magic [ i ] ) ;
wrmsrl ( MSR_ARCH_PERFMON_PERFCTR0 + i , 0x0 ) ;
}
wrmsrl ( MSR_CORE_PERF_GLOBAL_CTRL , 0xf ) ;
wrmsrl ( MSR_CORE_PERF_GLOBAL_CTRL , 0x0 ) ;
2010-03-26 14:08:44 +01:00
2010-08-06 13:39:08 +08:00
for ( i = 0 ; i < 4 ; i + + ) {
event = cpuc - > events [ i ] ;
if ( event ) {
x86_perf_event_set_period ( event ) ;
2010-04-13 22:23:14 +02:00
__x86_pmu_enable_event ( & event - > hw ,
2010-08-06 13:39:08 +08:00
ARCH_PERFMON_EVENTSEL_ENABLE ) ;
} else
wrmsrl ( MSR_ARCH_PERFMON_EVENTSEL0 + i , 0x0 ) ;
2010-03-26 14:08:44 +01:00
}
2010-08-06 13:39:08 +08:00
}
static void intel_pmu_nhm_enable_all ( int added )
{
if ( added )
intel_pmu_nhm_workaround ( ) ;
2010-03-26 14:08:44 +01:00
intel_pmu_enable_all ( added ) ;
}
2010-02-26 12:05:05 +01:00
static inline u64 intel_pmu_get_status ( void )
{
u64 status ;
rdmsrl ( MSR_CORE_PERF_GLOBAL_STATUS , status ) ;
return status ;
}
static inline void intel_pmu_ack_status ( u64 ack )
{
wrmsrl ( MSR_CORE_PERF_GLOBAL_OVF_CTRL , ack ) ;
}
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
static void intel_pmu_disable_fixed ( struct hw_perf_event * hwc )
2010-02-26 12:05:05 +01:00
{
2010-03-02 20:32:08 +01:00
int idx = hwc - > idx - X86_PMC_IDX_FIXED ;
2010-02-26 12:05:05 +01:00
u64 ctrl_val , mask ;
mask = 0xfULL < < ( idx * 4 ) ;
rdmsrl ( hwc - > config_base , ctrl_val ) ;
ctrl_val & = ~ mask ;
2010-03-08 13:51:31 +01:00
wrmsrl ( hwc - > config_base , ctrl_val ) ;
2010-02-26 12:05:05 +01:00
}
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
static void intel_pmu_disable_event ( struct perf_event * event )
2010-02-26 12:05:05 +01:00
{
2010-03-02 20:32:08 +01:00
struct hw_perf_event * hwc = & event - > hw ;
2011-10-05 14:01:21 +02:00
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
2010-03-02 20:32:08 +01:00
if ( unlikely ( hwc - > idx = = X86_PMC_IDX_FIXED_BTS ) ) {
2010-02-26 12:05:05 +01:00
intel_pmu_disable_bts ( ) ;
intel_pmu_drain_bts_buffer ( ) ;
return ;
}
2011-10-05 14:01:21 +02:00
cpuc - > intel_ctrl_guest_mask & = ~ ( 1ull < < hwc - > idx ) ;
cpuc - > intel_ctrl_host_mask & = ~ ( 1ull < < hwc - > idx ) ;
2012-02-09 23:20:57 +01:00
/*
* must disable before any actual event
* because any event may be combined with LBR
*/
if ( intel_pmu_needs_lbr_smpl ( event ) )
intel_pmu_lbr_disable ( event ) ;
2010-02-26 12:05:05 +01:00
if ( unlikely ( hwc - > config_base = = MSR_ARCH_PERFMON_FIXED_CTR_CTRL ) ) {
2010-03-02 20:32:08 +01:00
intel_pmu_disable_fixed ( hwc ) ;
2010-02-26 12:05:05 +01:00
return ;
}
2010-03-02 20:32:08 +01:00
x86_pmu_disable_event ( event ) ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
2010-04-08 23:03:20 +02:00
if ( unlikely ( event - > attr . precise_ip ) )
2010-03-03 13:12:23 +01:00
intel_pmu_pebs_disable ( event ) ;
2010-02-26 12:05:05 +01:00
}
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
static void intel_pmu_enable_fixed ( struct hw_perf_event * hwc )
2010-02-26 12:05:05 +01:00
{
2010-03-02 20:32:08 +01:00
int idx = hwc - > idx - X86_PMC_IDX_FIXED ;
2010-02-26 12:05:05 +01:00
u64 ctrl_val , bits , mask ;
/*
* Enable IRQ generation ( 0x8 ) ,
* and enable ring - 3 counting ( 0x2 ) and ring - 0 counting ( 0x1 )
* if requested :
*/
bits = 0x8ULL ;
if ( hwc - > config & ARCH_PERFMON_EVENTSEL_USR )
bits | = 0x2 ;
if ( hwc - > config & ARCH_PERFMON_EVENTSEL_OS )
bits | = 0x1 ;
/*
* ANY bit is supported in v3 and up
*/
if ( x86_pmu . version > 2 & & hwc - > config & ARCH_PERFMON_EVENTSEL_ANY )
bits | = 0x4 ;
bits < < = ( idx * 4 ) ;
mask = 0xfULL < < ( idx * 4 ) ;
rdmsrl ( hwc - > config_base , ctrl_val ) ;
ctrl_val & = ~ mask ;
ctrl_val | = bits ;
2010-03-08 13:51:31 +01:00
wrmsrl ( hwc - > config_base , ctrl_val ) ;
2010-02-26 12:05:05 +01:00
}
2010-03-02 20:32:08 +01:00
static void intel_pmu_enable_event ( struct perf_event * event )
2010-02-26 12:05:05 +01:00
{
2010-03-02 20:32:08 +01:00
struct hw_perf_event * hwc = & event - > hw ;
2011-10-05 14:01:21 +02:00
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
2010-03-02 20:32:08 +01:00
if ( unlikely ( hwc - > idx = = X86_PMC_IDX_FIXED_BTS ) ) {
2010-12-18 16:28:55 +01:00
if ( ! __this_cpu_read ( cpu_hw_events . enabled ) )
2010-02-26 12:05:05 +01:00
return ;
intel_pmu_enable_bts ( hwc - > config ) ;
return ;
}
2012-02-09 23:20:57 +01:00
/*
* must enabled before any actual event
* because any event may be combined with LBR
*/
if ( intel_pmu_needs_lbr_smpl ( event ) )
intel_pmu_lbr_enable ( event ) ;
2010-02-26 12:05:05 +01:00
2011-10-05 14:01:21 +02:00
if ( event - > attr . exclude_host )
cpuc - > intel_ctrl_guest_mask | = ( 1ull < < hwc - > idx ) ;
if ( event - > attr . exclude_guest )
cpuc - > intel_ctrl_host_mask | = ( 1ull < < hwc - > idx ) ;
2010-02-26 12:05:05 +01:00
if ( unlikely ( hwc - > config_base = = MSR_ARCH_PERFMON_FIXED_CTR_CTRL ) ) {
2010-03-02 20:32:08 +01:00
intel_pmu_enable_fixed ( hwc ) ;
2010-02-26 12:05:05 +01:00
return ;
}
2010-04-08 23:03:20 +02:00
if ( unlikely ( event - > attr . precise_ip ) )
2010-03-03 13:12:23 +01:00
intel_pmu_pebs_enable ( event ) ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
2010-04-13 22:23:14 +02:00
__x86_pmu_enable_event ( hwc , ARCH_PERFMON_EVENTSEL_ENABLE ) ;
2010-02-26 12:05:05 +01:00
}
/*
* Save and restart an expired event . Called by NMI contexts ,
* so it has to be careful about preempting normal event ops :
*/
2011-08-30 20:41:05 -03:00
int intel_pmu_save_and_restart ( struct perf_event * event )
2010-02-26 12:05:05 +01:00
{
2010-03-02 20:18:39 +01:00
x86_perf_event_update ( event ) ;
return x86_perf_event_set_period ( event ) ;
2010-02-26 12:05:05 +01:00
}
static void intel_pmu_reset ( void )
{
2010-12-18 16:28:55 +01:00
struct debug_store * ds = __this_cpu_read ( cpu_hw_events . ds ) ;
2010-02-26 12:05:05 +01:00
unsigned long flags ;
int idx ;
2010-03-29 18:36:50 +02:00
if ( ! x86_pmu . num_counters )
2010-02-26 12:05:05 +01:00
return ;
local_irq_save ( flags ) ;
printk ( " clearing PMU state on CPU#%d \n " , smp_processor_id ( ) ) ;
2010-03-29 18:36:50 +02:00
for ( idx = 0 ; idx < x86_pmu . num_counters ; idx + + ) {
2011-02-02 17:40:57 +01:00
checking_wrmsrl ( x86_pmu_config_addr ( idx ) , 0ull ) ;
checking_wrmsrl ( x86_pmu_event_addr ( idx ) , 0ull ) ;
2010-02-26 12:05:05 +01:00
}
2010-03-29 18:36:50 +02:00
for ( idx = 0 ; idx < x86_pmu . num_counters_fixed ; idx + + )
2010-02-26 12:05:05 +01:00
checking_wrmsrl ( MSR_ARCH_PERFMON_FIXED_CTR0 + idx , 0ull ) ;
2010-03-29 18:36:50 +02:00
2010-02-26 12:05:05 +01:00
if ( ds )
ds - > bts_index = ds - > bts_buffer_base ;
local_irq_restore ( flags ) ;
}
/*
* 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 cpu_hw_events * cpuc ;
int bit , loops ;
2010-09-02 15:07:47 -04:00
u64 status ;
2010-09-10 13:28:01 +02:00
int handled ;
2010-02-26 12:05:05 +01:00
cpuc = & __get_cpu_var ( cpu_hw_events ) ;
2011-04-27 06:32:33 -04:00
/*
* Some chipsets need to unmask the LVTPC in a particular spot
* inside the nmi handler . As a result , the unmasking was pushed
* into all the nmi handlers .
*
* This handler doesn ' t seem to have any issues with the unmasking
* so it was left at the top .
*/
apic_write ( APIC_LVTPC , APIC_DM_NMI ) ;
2010-03-08 13:51:01 +01:00
intel_pmu_disable_all ( ) ;
2010-09-10 13:28:01 +02:00
handled = intel_pmu_drain_bts_buffer ( ) ;
2010-02-26 12:05:05 +01:00
status = intel_pmu_get_status ( ) ;
if ( ! status ) {
2010-03-26 14:08:44 +01:00
intel_pmu_enable_all ( 0 ) ;
2010-09-10 13:28:01 +02:00
return handled ;
2010-02-26 12:05:05 +01:00
}
loops = 0 ;
again :
2010-09-02 15:07:47 -04:00
intel_pmu_ack_status ( status ) ;
2010-02-26 12:05:05 +01:00
if ( + + loops > 100 ) {
WARN_ONCE ( 1 , " perfevents: irq loop stuck! \n " ) ;
perf_event_print_debug ( ) ;
intel_pmu_reset ( ) ;
2010-03-08 13:51:01 +01:00
goto done ;
2010-02-26 12:05:05 +01:00
}
inc_irq_stat ( apic_perf_irqs ) ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_read ( ) ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
/*
* PEBS overflow sets bit 62 in the global status register
*/
2010-09-02 15:07:49 -04:00
if ( __test_and_clear_bit ( 62 , ( unsigned long * ) & status ) ) {
handled + + ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
x86_pmu . drain_pebs ( regs ) ;
2010-09-02 15:07:49 -04:00
}
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
2010-03-05 13:41:37 -08:00
for_each_set_bit ( bit , ( unsigned long * ) & status , X86_PMC_IDX_MAX ) {
2010-02-26 12:05:05 +01:00
struct perf_event * event = cpuc - > events [ bit ] ;
2010-09-02 15:07:49 -04:00
handled + + ;
2010-02-26 12:05:05 +01:00
if ( ! test_bit ( bit , cpuc - > active_mask ) )
continue ;
if ( ! intel_pmu_save_and_restart ( event ) )
continue ;
2012-04-02 20:19:08 +02:00
perf_sample_data_init ( & data , 0 , event - > hw . last_period ) ;
2010-02-26 12:05:05 +01:00
2012-02-09 23:20:57 +01:00
if ( has_branch_stack ( event ) )
data . br_stack = & cpuc - > lbr_stack ;
2011-06-27 14:41:57 +02:00
if ( perf_event_overflow ( event , & data , regs ) )
perf: Rework the PMU methods
Replace pmu::{enable,disable,start,stop,unthrottle} with
pmu::{add,del,start,stop}, all of which take a flags argument.
The new interface extends the capability to stop a counter while
keeping it scheduled on the PMU. We replace the throttled state with
the generic stopped state.
This also allows us to efficiently stop/start counters over certain
code paths (like IRQ handlers).
It also allows scheduling a counter without it starting, allowing for
a generic frozen state (useful for rotating stopped counters).
The stopped state is implemented in two different ways, depending on
how the architecture implemented the throttled state:
1) We disable the counter:
a) the pmu has per-counter enable bits, we flip that
b) we program a NOP event, preserving the counter state
2) We store the counter state and ignore all read/overflow events
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: paulus <paulus@samba.org>
Cc: stephane eranian <eranian@googlemail.com>
Cc: Robert Richter <robert.richter@amd.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Lin Ming <ming.m.lin@intel.com>
Cc: Yanmin <yanmin_zhang@linux.intel.com>
Cc: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
Cc: David Miller <davem@davemloft.net>
Cc: Michael Cree <mcree@orcon.net.nz>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-06-16 14:37:10 +02:00
x86_pmu_stop ( event , 0 ) ;
2010-02-26 12:05:05 +01:00
}
/*
* Repeat if there is more work to be done :
*/
status = intel_pmu_get_status ( ) ;
if ( status )
goto again ;
2010-03-08 13:51:01 +01:00
done :
2010-03-26 14:08:44 +01:00
intel_pmu_enable_all ( 0 ) ;
2010-09-02 15:07:49 -04:00
return handled ;
2010-02-26 12:05:05 +01:00
}
static struct event_constraint *
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
intel_bts_constraints ( struct perf_event * event )
2010-02-26 12:05:05 +01:00
{
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
struct hw_perf_event * hwc = & event - > hw ;
unsigned int hw_event , bts_event ;
2010-02-26 12:05:05 +01:00
2011-04-26 13:24:33 +02:00
if ( event - > attr . freq )
return NULL ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
hw_event = hwc - > config & INTEL_ARCH_EVENT_MASK ;
bts_event = x86_pmu . event_map ( PERF_COUNT_HW_BRANCH_INSTRUCTIONS ) ;
2010-02-26 12:05:05 +01:00
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
if ( unlikely ( hw_event = = bts_event & & hwc - > sample_period = = 1 ) )
2010-02-26 12:05:05 +01:00
return & bts_constraint ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
2010-02-26 12:05:05 +01:00
return NULL ;
}
2012-06-05 15:30:31 +02:00
static int intel_alt_er ( int idx )
2011-05-23 11:08:15 +02:00
{
if ( ! ( x86_pmu . er_flags & ERF_HAS_RSP_1 ) )
2012-06-05 15:30:31 +02:00
return idx ;
2011-05-23 11:08:15 +02:00
2012-06-05 15:30:31 +02:00
if ( idx = = EXTRA_REG_RSP_0 )
return EXTRA_REG_RSP_1 ;
if ( idx = = EXTRA_REG_RSP_1 )
return EXTRA_REG_RSP_0 ;
return idx ;
}
static void intel_fixup_er ( struct perf_event * event , int idx )
{
event - > hw . extra_reg . idx = idx ;
if ( idx = = EXTRA_REG_RSP_0 ) {
2011-05-23 11:08:15 +02:00
event - > hw . config & = ~ INTEL_ARCH_EVENT_MASK ;
event - > hw . config | = 0x01b7 ;
event - > hw . extra_reg . reg = MSR_OFFCORE_RSP_0 ;
2012-06-05 15:30:31 +02:00
} else if ( idx = = EXTRA_REG_RSP_1 ) {
event - > hw . config & = ~ INTEL_ARCH_EVENT_MASK ;
event - > hw . config | = 0x01bb ;
event - > hw . extra_reg . reg = MSR_OFFCORE_RSP_1 ;
2011-05-23 11:08:15 +02:00
}
}
2011-06-06 16:57:03 +02:00
/*
* manage allocation of shared extra msr for certain events
*
* sharing can be :
* per - cpu : to be shared between the various events on a single PMU
* per - core : per - cpu + shared by HT threads
*/
2011-03-03 10:34:47 +08:00
static struct event_constraint *
2011-06-06 16:57:03 +02:00
__intel_shared_reg_get_constraints ( struct cpu_hw_events * cpuc ,
2012-02-09 23:20:53 +01:00
struct perf_event * event ,
struct hw_perf_event_extra * reg )
2011-03-03 10:34:47 +08:00
{
2011-06-06 16:57:03 +02:00
struct event_constraint * c = & emptyconstraint ;
2011-03-03 10:34:47 +08:00
struct er_account * era ;
2011-06-06 16:57:08 +02:00
unsigned long flags ;
2012-06-05 15:30:31 +02:00
int idx = reg - > idx ;
2011-03-03 10:34:47 +08:00
2012-06-05 15:30:31 +02:00
/*
* reg - > alloc can be set due to existing state , so for fake cpuc we
* need to ignore this , otherwise we might fail to allocate proper fake
* state for this extra reg constraint . Also see the comment below .
*/
if ( reg - > alloc & & ! cpuc - > is_fake )
2012-02-09 23:20:53 +01:00
return NULL ; /* call x86_get_event_constraint() */
2011-03-03 10:34:47 +08:00
2011-05-23 11:08:15 +02:00
again :
2012-06-05 15:30:31 +02:00
era = & cpuc - > shared_regs - > regs [ idx ] ;
2011-06-06 16:57:08 +02:00
/*
* we use spin_lock_irqsave ( ) to avoid lockdep issues when
* passing a fake cpuc
*/
raw_spin_lock_irqsave ( & era - > lock , flags ) ;
2011-06-06 16:57:03 +02:00
if ( ! atomic_read ( & era - > ref ) | | era - > config = = reg - > config ) {
2012-06-05 15:30:31 +02:00
/*
* If its a fake cpuc - - as per validate_ { group , event } ( ) we
* shouldn ' t touch event state and we can avoid doing so
* since both will only call get_event_constraints ( ) once
* on each event , this avoids the need for reg - > alloc .
*
* Not doing the ER fixup will only result in era - > reg being
* wrong , but since we won ' t actually try and program hardware
* this isn ' t a problem either .
*/
if ( ! cpuc - > is_fake ) {
if ( idx ! = reg - > idx )
intel_fixup_er ( event , idx ) ;
/*
* x86_schedule_events ( ) can call get_event_constraints ( )
* multiple times on events in the case of incremental
* scheduling ( ) . reg - > alloc ensures we only do the ER
* allocation once .
*/
reg - > alloc = 1 ;
}
2011-06-06 16:57:03 +02:00
/* lock in msr value */
era - > config = reg - > config ;
era - > reg = reg - > reg ;
/* one more user */
atomic_inc ( & era - > ref ) ;
2011-03-03 10:34:47 +08:00
/*
2012-02-09 23:20:53 +01:00
* need to call x86_get_event_constraint ( )
* to check if associated event has constraints
2011-03-03 10:34:47 +08:00
*/
2012-02-09 23:20:53 +01:00
c = NULL ;
2012-06-05 15:30:31 +02:00
} else {
idx = intel_alt_er ( idx ) ;
if ( idx ! = reg - > idx ) {
raw_spin_unlock_irqrestore ( & era - > lock , flags ) ;
goto again ;
}
2011-03-03 10:34:47 +08:00
}
2011-06-06 16:57:08 +02:00
raw_spin_unlock_irqrestore ( & era - > lock , flags ) ;
2011-03-03 10:34:47 +08:00
2011-06-06 16:57:03 +02:00
return c ;
}
static void
__intel_shared_reg_put_constraints ( struct cpu_hw_events * cpuc ,
struct hw_perf_event_extra * reg )
{
struct er_account * era ;
/*
2012-06-05 15:30:31 +02:00
* Only put constraint if extra reg was actually allocated . Also takes
* care of event which do not use an extra shared reg .
*
* Also , if this is a fake cpuc we shouldn ' t touch any event state
* ( reg - > alloc ) and we don ' t care about leaving inconsistent cpuc state
* either since it ' ll be thrown out .
2011-06-06 16:57:03 +02:00
*/
2012-06-05 15:30:31 +02:00
if ( ! reg - > alloc | | cpuc - > is_fake )
2011-06-06 16:57:03 +02:00
return ;
era = & cpuc - > shared_regs - > regs [ reg - > idx ] ;
/* one fewer user */
atomic_dec ( & era - > ref ) ;
/* allocate again next time */
reg - > alloc = 0 ;
}
static struct event_constraint *
intel_shared_regs_constraints ( struct cpu_hw_events * cpuc ,
struct perf_event * event )
{
2012-02-09 23:20:53 +01:00
struct event_constraint * c = NULL , * d ;
struct hw_perf_event_extra * xreg , * breg ;
xreg = & event - > hw . extra_reg ;
if ( xreg - > idx ! = EXTRA_REG_NONE ) {
c = __intel_shared_reg_get_constraints ( cpuc , event , xreg ) ;
if ( c = = & emptyconstraint )
return c ;
}
breg = & event - > hw . branch_reg ;
if ( breg - > idx ! = EXTRA_REG_NONE ) {
d = __intel_shared_reg_get_constraints ( cpuc , event , breg ) ;
if ( d = = & emptyconstraint ) {
__intel_shared_reg_put_constraints ( cpuc , xreg ) ;
c = d ;
}
}
2011-06-06 16:57:03 +02:00
return c ;
2011-03-03 10:34:47 +08:00
}
2011-08-30 20:41:05 -03:00
struct event_constraint *
x86_get_event_constraints ( struct cpu_hw_events * cpuc , struct perf_event * event )
{
struct event_constraint * c ;
if ( x86_pmu . event_constraints ) {
for_each_event_constraint ( c , x86_pmu . event_constraints ) {
if ( ( event - > hw . config & c - > cmask ) = = c - > code )
return c ;
}
}
return & unconstrained ;
}
2010-02-26 12:05:05 +01:00
static struct event_constraint *
intel_get_event_constraints ( struct cpu_hw_events * cpuc , struct perf_event * event )
{
struct event_constraint * c ;
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
c = intel_bts_constraints ( event ) ;
if ( c )
return c ;
c = intel_pebs_constraints ( event ) ;
2010-02-26 12:05:05 +01:00
if ( c )
return c ;
2011-06-06 16:57:03 +02:00
c = intel_shared_regs_constraints ( cpuc , event ) ;
2011-03-03 10:34:47 +08:00
if ( c )
return c ;
2010-02-26 12:05:05 +01:00
return x86_get_event_constraints ( cpuc , event ) ;
}
2011-06-06 16:57:03 +02:00
static void
intel_put_shared_regs_event_constraints ( struct cpu_hw_events * cpuc ,
2011-03-03 10:34:47 +08:00
struct perf_event * event )
{
2011-06-06 16:57:03 +02:00
struct hw_perf_event_extra * reg ;
2011-03-03 10:34:47 +08:00
2011-06-06 16:57:03 +02:00
reg = & event - > hw . extra_reg ;
if ( reg - > idx ! = EXTRA_REG_NONE )
__intel_shared_reg_put_constraints ( cpuc , reg ) ;
2012-02-09 23:20:53 +01:00
reg = & event - > hw . branch_reg ;
if ( reg - > idx ! = EXTRA_REG_NONE )
__intel_shared_reg_put_constraints ( cpuc , reg ) ;
2011-06-06 16:57:03 +02:00
}
2011-03-03 10:34:47 +08:00
2011-06-06 16:57:03 +02:00
static void intel_put_event_constraints ( struct cpu_hw_events * cpuc ,
struct perf_event * event )
{
intel_put_shared_regs_event_constraints ( cpuc , event ) ;
2011-03-03 10:34:47 +08:00
}
2012-06-05 10:26:43 +02:00
static void intel_pebs_aliases_core2 ( struct perf_event * event )
2010-03-30 17:00:06 +02:00
{
2012-06-05 10:26:43 +02:00
if ( ( event - > hw . config & X86_RAW_EVENT_MASK ) = = 0x003c ) {
2010-12-14 21:26:40 +01:00
/*
* Use an alternative encoding for CPU_CLK_UNHALTED . THREAD_P
* ( 0x003c ) so that we can use it with PEBS .
*
* The regular CPU_CLK_UNHALTED . THREAD_P event ( 0x003c ) isn ' t
* PEBS capable . However we can use INST_RETIRED . ANY_P
* ( 0x00c0 ) , which is a PEBS capable event , to get the same
* count .
*
* INST_RETIRED . ANY_P counts the number of cycles that retires
* CNTMASK instructions . By setting CNTMASK to a value ( 16 )
* larger than the maximum number of instructions that can be
* retired per cycle ( 4 ) and then inverting the condition , we
* count all cycles that retire 16 or less instructions , which
* is every cycle .
*
* Thereby we gain a PEBS capable cycle counter .
*/
2012-03-12 12:44:35 +01:00
u64 alt_config = X86_CONFIG ( . event = 0xc0 , . inv = 1 , . cmask = 16 ) ;
2012-06-05 10:26:43 +02:00
alt_config | = ( event - > hw . config & ~ X86_RAW_EVENT_MASK ) ;
event - > hw . config = alt_config ;
}
}
static void intel_pebs_aliases_snb ( struct perf_event * event )
{
if ( ( event - > hw . config & X86_RAW_EVENT_MASK ) = = 0x003c ) {
/*
* Use an alternative encoding for CPU_CLK_UNHALTED . THREAD_P
* ( 0x003c ) so that we can use it with PEBS .
*
* The regular CPU_CLK_UNHALTED . THREAD_P event ( 0x003c ) isn ' t
* PEBS capable . However we can use UOPS_RETIRED . ALL
* ( 0x01c2 ) , which is a PEBS capable event , to get the same
* count .
*
* UOPS_RETIRED . ALL counts the number of cycles that retires
* CNTMASK micro - ops . By setting CNTMASK to a value ( 16 )
* larger than the maximum number of micro - ops that can be
* retired per cycle ( 4 ) and then inverting the condition , we
* count all cycles that retire 16 or less micro - ops , which
* is every cycle .
*
* Thereby we gain a PEBS capable cycle counter .
*/
u64 alt_config = X86_CONFIG ( . event = 0xc2 , . umask = 0x01 , . inv = 1 , . cmask = 16 ) ;
2010-12-14 21:26:40 +01:00
alt_config | = ( event - > hw . config & ~ X86_RAW_EVENT_MASK ) ;
event - > hw . config = alt_config ;
}
2012-06-05 10:26:43 +02:00
}
static int intel_pmu_hw_config ( struct perf_event * event )
{
int ret = x86_pmu_hw_config ( event ) ;
if ( ret )
return ret ;
if ( event - > attr . precise_ip & & x86_pmu . pebs_aliases )
x86_pmu . pebs_aliases ( event ) ;
2010-12-14 21:26:40 +01:00
2012-02-09 23:20:57 +01:00
if ( intel_pmu_needs_lbr_smpl ( event ) ) {
ret = intel_pmu_setup_lbr_filter ( event ) ;
if ( ret )
return ret ;
}
2010-03-30 17:00:06 +02:00
if ( event - > attr . type ! = PERF_TYPE_RAW )
return 0 ;
if ( ! ( event - > attr . config & ARCH_PERFMON_EVENTSEL_ANY ) )
return 0 ;
if ( x86_pmu . version < 3 )
return - EINVAL ;
if ( perf_paranoid_cpu ( ) & & ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
event - > hw . config | = ARCH_PERFMON_EVENTSEL_ANY ;
return 0 ;
}
2011-10-05 14:01:21 +02:00
struct perf_guest_switch_msr * perf_guest_get_msrs ( int * nr )
{
if ( x86_pmu . guest_get_msrs )
return x86_pmu . guest_get_msrs ( nr ) ;
* nr = 0 ;
return NULL ;
}
EXPORT_SYMBOL_GPL ( perf_guest_get_msrs ) ;
static struct perf_guest_switch_msr * intel_guest_get_msrs ( int * nr )
{
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
struct perf_guest_switch_msr * arr = cpuc - > guest_switch_msrs ;
arr [ 0 ] . msr = MSR_CORE_PERF_GLOBAL_CTRL ;
arr [ 0 ] . host = x86_pmu . intel_ctrl & ~ cpuc - > intel_ctrl_guest_mask ;
arr [ 0 ] . guest = x86_pmu . intel_ctrl & ~ cpuc - > intel_ctrl_host_mask ;
* nr = 1 ;
return arr ;
}
static struct perf_guest_switch_msr * core_guest_get_msrs ( int * nr )
{
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
struct perf_guest_switch_msr * arr = cpuc - > guest_switch_msrs ;
int idx ;
for ( idx = 0 ; idx < x86_pmu . num_counters ; idx + + ) {
struct perf_event * event = cpuc - > events [ idx ] ;
arr [ idx ] . msr = x86_pmu_config_addr ( idx ) ;
arr [ idx ] . host = arr [ idx ] . guest = 0 ;
if ( ! test_bit ( idx , cpuc - > active_mask ) )
continue ;
arr [ idx ] . host = arr [ idx ] . guest =
event - > hw . config | ARCH_PERFMON_EVENTSEL_ENABLE ;
if ( event - > attr . exclude_host )
arr [ idx ] . host & = ~ ARCH_PERFMON_EVENTSEL_ENABLE ;
else if ( event - > attr . exclude_guest )
arr [ idx ] . guest & = ~ ARCH_PERFMON_EVENTSEL_ENABLE ;
}
* nr = x86_pmu . num_counters ;
return arr ;
}
static void core_pmu_enable_event ( struct perf_event * event )
{
if ( ! event - > attr . exclude_host )
x86_pmu_enable_event ( event ) ;
}
static void core_pmu_enable_all ( int added )
{
struct cpu_hw_events * cpuc = & __get_cpu_var ( cpu_hw_events ) ;
int idx ;
for ( idx = 0 ; idx < x86_pmu . num_counters ; idx + + ) {
struct hw_perf_event * hwc = & cpuc - > events [ idx ] - > hw ;
if ( ! test_bit ( idx , cpuc - > active_mask ) | |
cpuc - > events [ idx ] - > attr . exclude_host )
continue ;
__x86_pmu_enable_event ( hwc , ARCH_PERFMON_EVENTSEL_ENABLE ) ;
}
}
2012-03-15 20:09:14 +01:00
PMU_FORMAT_ATTR ( event , " config:0-7 " ) ;
PMU_FORMAT_ATTR ( umask , " config:8-15 " ) ;
PMU_FORMAT_ATTR ( edge , " config:18 " ) ;
PMU_FORMAT_ATTR ( pc , " config:19 " ) ;
PMU_FORMAT_ATTR ( any , " config:21 " ) ; /* v3 + */
PMU_FORMAT_ATTR ( inv , " config:23 " ) ;
PMU_FORMAT_ATTR ( cmask , " config:24-31 " ) ;
static struct attribute * intel_arch_formats_attr [ ] = {
& format_attr_event . attr ,
& format_attr_umask . attr ,
& format_attr_edge . attr ,
& format_attr_pc . attr ,
& format_attr_inv . attr ,
& format_attr_cmask . attr ,
NULL ,
} ;
2010-03-29 13:09:53 +02:00
static __initconst const struct x86_pmu core_pmu = {
2010-02-26 12:05:05 +01:00
. name = " core " ,
. handle_irq = x86_pmu_handle_irq ,
. disable_all = x86_pmu_disable_all ,
2011-10-05 14:01:21 +02:00
. enable_all = core_pmu_enable_all ,
. enable = core_pmu_enable_event ,
2010-02-26 12:05:05 +01:00
. disable = x86_pmu_disable_event ,
2010-03-30 17:00:06 +02:00
. hw_config = x86_pmu_hw_config ,
2010-03-11 19:54:39 +03:00
. schedule_events = x86_schedule_events ,
2010-02-26 12:05:05 +01:00
. eventsel = MSR_ARCH_PERFMON_EVENTSEL0 ,
. perfctr = MSR_ARCH_PERFMON_PERFCTR0 ,
. event_map = intel_pmu_event_map ,
. max_events = ARRAY_SIZE ( intel_perfmon_event_map ) ,
. apic = 1 ,
/*
* Intel PMCs cannot be accessed sanely above 32 bit width ,
* so we install an artificial 1 < < 31 period regardless of
* the generic event period :
*/
. max_period = ( 1ULL < < 31 ) - 1 ,
. get_event_constraints = intel_get_event_constraints ,
2011-03-03 10:34:47 +08:00
. put_event_constraints = intel_put_event_constraints ,
2010-02-26 12:05:05 +01:00
. event_constraints = intel_core_event_constraints ,
2011-10-05 14:01:21 +02:00
. guest_get_msrs = core_guest_get_msrs ,
2012-03-15 20:09:14 +01:00
. format_attrs = intel_arch_formats_attr ,
2010-02-26 12:05:05 +01:00
} ;
2011-08-30 20:41:05 -03:00
struct intel_shared_regs * allocate_shared_regs ( int cpu )
2011-06-06 16:57:03 +02:00
{
struct intel_shared_regs * regs ;
int i ;
regs = kzalloc_node ( sizeof ( struct intel_shared_regs ) ,
GFP_KERNEL , cpu_to_node ( cpu ) ) ;
if ( regs ) {
/*
* initialize the locks to keep lockdep happy
*/
for ( i = 0 ; i < EXTRA_REG_MAX ; i + + )
raw_spin_lock_init ( & regs - > regs [ i ] . lock ) ;
regs - > core_id = - 1 ;
}
return regs ;
}
2011-03-03 10:34:47 +08:00
static int intel_pmu_cpu_prepare ( int cpu )
{
struct cpu_hw_events * cpuc = & per_cpu ( cpu_hw_events , cpu ) ;
2012-02-09 23:20:53 +01:00
if ( ! ( x86_pmu . extra_regs | | x86_pmu . lbr_sel_map ) )
2011-03-03 10:34:50 +08:00
return NOTIFY_OK ;
2011-06-06 16:57:03 +02:00
cpuc - > shared_regs = allocate_shared_regs ( cpu ) ;
if ( ! cpuc - > shared_regs )
2011-03-03 10:34:47 +08:00
return NOTIFY_BAD ;
return NOTIFY_OK ;
}
2010-03-05 13:49:35 +01:00
static void intel_pmu_cpu_starting ( int cpu )
{
2011-03-03 10:34:47 +08:00
struct cpu_hw_events * cpuc = & per_cpu ( cpu_hw_events , cpu ) ;
int core_id = topology_core_id ( cpu ) ;
int i ;
2011-03-03 10:34:50 +08:00
init_debug_store_on_cpu ( cpu ) ;
/*
* Deal with CPUs that don ' t clear their LBRs on power - up .
*/
intel_pmu_lbr_reset ( ) ;
2012-02-09 23:20:53 +01:00
cpuc - > lbr_sel = NULL ;
if ( ! cpuc - > shared_regs )
2011-03-03 10:34:50 +08:00
return ;
2012-02-09 23:20:53 +01:00
if ( ! ( x86_pmu . er_flags & ERF_NO_HT_SHARING ) ) {
for_each_cpu ( i , topology_thread_cpumask ( cpu ) ) {
struct intel_shared_regs * pc ;
2011-03-03 10:34:47 +08:00
2012-02-09 23:20:53 +01:00
pc = per_cpu ( cpu_hw_events , i ) . shared_regs ;
if ( pc & & pc - > core_id = = core_id ) {
cpuc - > kfree_on_online = cpuc - > shared_regs ;
cpuc - > shared_regs = pc ;
break ;
}
2011-03-03 10:34:47 +08:00
}
2012-02-09 23:20:53 +01:00
cpuc - > shared_regs - > core_id = core_id ;
cpuc - > shared_regs - > refcnt + + ;
2011-03-03 10:34:47 +08:00
}
2012-02-09 23:20:53 +01:00
if ( x86_pmu . lbr_sel_map )
cpuc - > lbr_sel = & cpuc - > shared_regs - > regs [ EXTRA_REG_LBR ] ;
2010-03-05 13:49:35 +01:00
}
static void intel_pmu_cpu_dying ( int cpu )
{
2011-03-03 10:34:47 +08:00
struct cpu_hw_events * cpuc = & per_cpu ( cpu_hw_events , cpu ) ;
2011-06-06 16:57:03 +02:00
struct intel_shared_regs * pc ;
2011-03-03 10:34:47 +08:00
2011-06-06 16:57:03 +02:00
pc = cpuc - > shared_regs ;
2011-03-03 10:34:47 +08:00
if ( pc ) {
if ( pc - > core_id = = - 1 | | - - pc - > refcnt = = 0 )
kfree ( pc ) ;
2011-06-06 16:57:03 +02:00
cpuc - > shared_regs = NULL ;
2011-03-03 10:34:47 +08:00
}
2010-03-05 13:49:35 +01:00
fini_debug_store_on_cpu ( cpu ) ;
}
2012-02-09 23:21:00 +01:00
static void intel_pmu_flush_branch_stack ( void )
{
/*
* Intel LBR does not tag entries with the
* PID of the current task , then we need to
* flush it on ctxsw
* For now , we simply reset it
*/
if ( x86_pmu . lbr_nr )
intel_pmu_lbr_reset ( ) ;
}
2012-03-15 20:09:14 +01:00
PMU_FORMAT_ATTR ( offcore_rsp , " config1:0-63 " ) ;
static struct attribute * intel_arch3_formats_attr [ ] = {
& format_attr_event . attr ,
& format_attr_umask . attr ,
& format_attr_edge . attr ,
& format_attr_pc . attr ,
& format_attr_any . attr ,
& format_attr_inv . attr ,
& format_attr_cmask . attr ,
& format_attr_offcore_rsp . attr , /* XXX do NHM/WSM + SNB breakout */
NULL ,
} ;
2010-03-29 13:09:53 +02:00
static __initconst const struct x86_pmu intel_pmu = {
2010-02-26 12:05:05 +01:00
. name = " Intel " ,
. handle_irq = intel_pmu_handle_irq ,
. disable_all = intel_pmu_disable_all ,
. enable_all = intel_pmu_enable_all ,
. enable = intel_pmu_enable_event ,
. disable = intel_pmu_disable_event ,
2010-03-30 17:00:06 +02:00
. hw_config = intel_pmu_hw_config ,
2010-03-11 19:54:39 +03:00
. schedule_events = x86_schedule_events ,
2010-02-26 12:05:05 +01:00
. eventsel = MSR_ARCH_PERFMON_EVENTSEL0 ,
. perfctr = MSR_ARCH_PERFMON_PERFCTR0 ,
. event_map = intel_pmu_event_map ,
. max_events = ARRAY_SIZE ( intel_perfmon_event_map ) ,
. apic = 1 ,
/*
* Intel PMCs cannot be accessed sanely above 32 bit width ,
* so we install an artificial 1 < < 31 period regardless of
* the generic event period :
*/
. max_period = ( 1ULL < < 31 ) - 1 ,
2010-03-05 13:01:18 +01:00
. get_event_constraints = intel_get_event_constraints ,
2011-03-03 10:34:47 +08:00
. put_event_constraints = intel_put_event_constraints ,
2012-06-05 10:26:43 +02:00
. pebs_aliases = intel_pebs_aliases_core2 ,
2010-03-05 13:01:18 +01:00
2012-03-15 20:09:14 +01:00
. format_attrs = intel_arch3_formats_attr ,
2011-03-03 10:34:47 +08:00
. cpu_prepare = intel_pmu_cpu_prepare ,
2010-03-05 13:49:35 +01:00
. cpu_starting = intel_pmu_cpu_starting ,
. cpu_dying = intel_pmu_cpu_dying ,
2011-10-05 14:01:21 +02:00
. guest_get_msrs = intel_guest_get_msrs ,
2012-02-09 23:21:00 +01:00
. flush_branch_stack = intel_pmu_flush_branch_stack ,
2010-02-26 12:05:05 +01:00
} ;
2011-12-06 14:07:15 +01:00
static __init void intel_clovertown_quirk ( void )
2010-03-04 21:49:01 +01:00
{
/*
* PEBS is unreliable due to :
*
* AJ67 - PEBS may experience CPL leaks
* AJ68 - PEBS PMI may be delayed by one event
* AJ69 - GLOBAL_STATUS [ 62 ] will only be set when DEBUGCTL [ 12 ]
* AJ106 - FREEZE_LBRS_ON_PMI doesn ' t work in combination with PEBS
*
* AJ67 could be worked around by restricting the OS / USR flags .
* AJ69 could be worked around by setting PMU_FREEZE_ON_PMI .
*
* AJ106 could possibly be worked around by not allowing LBR
* usage from PEBS , including the fixup .
* AJ68 could possibly be worked around by always programming
2011-04-27 11:51:41 +02:00
* a pebs_event_reset [ 0 ] value and coping with the lost events .
2010-03-04 21:49:01 +01:00
*
* But taken together it might just make sense to not enable PEBS on
* these chips .
*/
printk ( KERN_WARNING " PEBS disabled due to CPU errata. \n " ) ;
x86_pmu . pebs = 0 ;
x86_pmu . pebs_constraints = NULL ;
}
2011-12-06 14:07:15 +01:00
static __init void intel_sandybridge_quirk ( void )
2011-11-15 10:51:15 +01:00
{
printk ( KERN_WARNING " PEBS disabled due to CPU errata. \n " ) ;
x86_pmu . pebs = 0 ;
x86_pmu . pebs_constraints = NULL ;
}
2011-12-06 14:07:15 +01:00
static const struct { int id ; char * name ; } intel_arch_events_map [ ] __initconst = {
{ PERF_COUNT_HW_CPU_CYCLES , " cpu cycles " } ,
{ PERF_COUNT_HW_INSTRUCTIONS , " instructions " } ,
{ PERF_COUNT_HW_BUS_CYCLES , " bus cycles " } ,
{ PERF_COUNT_HW_CACHE_REFERENCES , " cache references " } ,
{ PERF_COUNT_HW_CACHE_MISSES , " cache misses " } ,
{ PERF_COUNT_HW_BRANCH_INSTRUCTIONS , " branch instructions " } ,
{ PERF_COUNT_HW_BRANCH_MISSES , " branch misses " } ,
2011-11-10 14:57:26 +02:00
} ;
2011-12-06 14:07:15 +01:00
static __init void intel_arch_events_quirk ( void )
{
int bit ;
/* disable event that reported as not presend by cpuid */
for_each_set_bit ( bit , x86_pmu . events_mask , ARRAY_SIZE ( intel_arch_events_map ) ) {
intel_perfmon_event_map [ intel_arch_events_map [ bit ] . id ] = 0 ;
printk ( KERN_WARNING " CPUID marked event: \' %s \' unavailable \n " ,
intel_arch_events_map [ bit ] . name ) ;
}
}
static __init void intel_nehalem_quirk ( void )
{
union cpuid10_ebx ebx ;
ebx . full = x86_pmu . events_maskl ;
if ( ebx . split . no_branch_misses_retired ) {
/*
* Erratum AAJ80 detected , we work it around by using
* the BR_MISP_EXEC . ANY event . This will over - count
* branch - misses , but it ' s still much better than the
* architectural event which is often completely bogus :
*/
intel_perfmon_event_map [ PERF_COUNT_HW_BRANCH_MISSES ] = 0x7f89 ;
ebx . split . no_branch_misses_retired = 0 ;
x86_pmu . events_maskl = ebx . full ;
printk ( KERN_INFO " CPU erratum AAJ80 worked around \n " ) ;
}
}
2011-08-30 20:41:05 -03:00
__init int intel_pmu_init ( void )
2010-02-26 12:05:05 +01:00
{
union cpuid10_edx edx ;
union cpuid10_eax eax ;
2011-11-10 14:57:26 +02:00
union cpuid10_ebx ebx ;
2010-02-26 12:05:05 +01:00
unsigned int unused ;
int version ;
if ( ! cpu_has ( & boot_cpu_data , X86_FEATURE_ARCH_PERFMON ) ) {
2010-03-11 19:54:39 +03:00
switch ( boot_cpu_data . x86 ) {
case 0x6 :
return p6_pmu_init ( ) ;
case 0xf :
return p4_pmu_init ( ) ;
}
2010-02-26 12:05:05 +01:00
return - ENODEV ;
}
/*
* Check whether the Architectural PerfMon supports
* Branch Misses Retired hw_event or not .
*/
2011-11-10 14:57:26 +02:00
cpuid ( 10 , & eax . full , & ebx . full , & unused , & edx . full ) ;
if ( eax . split . mask_length < ARCH_PERFMON_EVENTS_COUNT )
2010-02-26 12:05:05 +01:00
return - ENODEV ;
version = eax . split . version_id ;
if ( version < 2 )
x86_pmu = core_pmu ;
else
x86_pmu = intel_pmu ;
x86_pmu . version = version ;
2010-03-29 18:36:50 +02:00
x86_pmu . num_counters = eax . split . num_counters ;
x86_pmu . cntval_bits = eax . split . bit_width ;
x86_pmu . cntval_mask = ( 1ULL < < eax . split . bit_width ) - 1 ;
2010-02-26 12:05:05 +01:00
2011-12-06 14:07:15 +01:00
x86_pmu . events_maskl = ebx . full ;
x86_pmu . events_mask_len = eax . split . mask_length ;
2010-02-26 12:05:05 +01:00
/*
* Quirk : v2 perfmon does not report fixed - purpose events , so
* assume at least 3 events :
*/
if ( version > 1 )
2010-03-29 18:36:50 +02:00
x86_pmu . num_counters_fixed = max ( ( int ) edx . split . num_counters_fixed , 3 ) ;
2010-02-26 12:05:05 +01:00
2010-03-03 17:07:40 +01:00
/*
* v2 and above have a perf capabilities MSR
*/
if ( version > 1 ) {
u64 capabilities ;
rdmsrl ( MSR_IA32_PERF_CAPABILITIES , capabilities ) ;
x86_pmu . intel_cap . capabilities = capabilities ;
}
perf, x86: Add PEBS infrastructure
This patch implements support for Intel Precise Event Based Sampling,
which is an alternative counter mode in which the counter triggers a
hardware assist to collect information on events. The hardware assist
takes a trap like snapshot of a subset of the machine registers.
This data is written to the Intel Debug-Store, which can be programmed
with a data threshold at which to raise a PMI.
With the PEBS hardware assist being trap like, the reported IP is always
one instruction after the actual instruction that triggered the event.
This implements a simple PEBS model that always takes a single PEBS event
at a time. This is done so that the interaction with the rest of the
system is as expected (freq adjust, period randomization, lbr,
callchains, etc.).
It adds an ABI element: perf_event_attr::precise, which indicates that we
wish to use this (constrained, but precise) mode.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: paulus@samba.org
Cc: eranian@google.com
Cc: robert.richter@amd.com
Cc: fweisbec@gmail.com
LKML-Reference: <20100304140100.392111285@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2010-03-02 19:52:12 +01:00
intel_ds_init ( ) ;
2011-12-06 14:07:15 +01:00
x86_add_quirk ( intel_arch_events_quirk ) ; /* Install first, so it runs last */
2010-02-26 12:05:05 +01:00
/*
* Install the hw - cache - events table :
*/
switch ( boot_cpu_data . x86_model ) {
case 14 : /* 65 nm core solo/duo, "Yonah" */
pr_cont ( " Core events, " ) ;
break ;
case 15 : /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
2011-12-06 14:07:15 +01:00
x86_add_quirk ( intel_clovertown_quirk ) ;
2010-02-26 12:05:05 +01:00
case 22 : /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
case 23 : /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
case 29 : /* six-core 45 nm xeon "Dunnington" */
memcpy ( hw_cache_event_ids , core2_hw_cache_event_ids ,
sizeof ( hw_cache_event_ids ) ) ;
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_init_core ( ) ;
2010-02-26 12:05:05 +01:00
x86_pmu . event_constraints = intel_core2_event_constraints ;
2011-03-02 17:05:01 +02:00
x86_pmu . pebs_constraints = intel_core2_pebs_event_constraints ;
2010-02-26 12:05:05 +01:00
pr_cont ( " Core2 events, " ) ;
break ;
case 26 : /* 45 nm nehalem, "Bloomfield" */
case 30 : /* 45 nm nehalem, "Lynnfield" */
2010-04-06 10:01:19 -04:00
case 46 : /* 45 nm nehalem-ex, "Beckton" */
2010-02-26 12:05:05 +01:00
memcpy ( hw_cache_event_ids , nehalem_hw_cache_event_ids ,
sizeof ( hw_cache_event_ids ) ) ;
2011-03-03 10:34:48 +08:00
memcpy ( hw_cache_extra_regs , nehalem_hw_cache_extra_regs ,
sizeof ( hw_cache_extra_regs ) ) ;
2010-02-26 12:05:05 +01:00
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_init_nhm ( ) ;
2010-02-26 12:05:05 +01:00
x86_pmu . event_constraints = intel_nehalem_event_constraints ;
2011-03-02 17:05:01 +02:00
x86_pmu . pebs_constraints = intel_nehalem_pebs_event_constraints ;
2010-03-26 14:08:44 +01:00
x86_pmu . enable_all = intel_pmu_nhm_enable_all ;
2011-03-03 10:34:47 +08:00
x86_pmu . extra_regs = intel_nehalem_extra_regs ;
2011-04-27 11:51:41 +02:00
2011-04-29 14:17:19 +02:00
/* UOPS_ISSUED.STALLED_CYCLES */
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_FRONTEND ] =
X86_CONFIG ( . event = 0x0e , . umask = 0x01 , . inv = 1 , . cmask = 1 ) ;
2011-04-29 14:17:19 +02:00
/* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_BACKEND ] =
X86_CONFIG ( . event = 0xb1 , . umask = 0x3f , . inv = 1 , . cmask = 1 ) ;
2011-04-24 08:18:31 +02:00
2011-12-06 14:07:15 +01:00
x86_add_quirk ( intel_nehalem_quirk ) ;
2011-04-27 11:51:41 +02:00
2010-03-26 14:08:44 +01:00
pr_cont ( " Nehalem events, " ) ;
2010-02-26 12:05:05 +01:00
break ;
2010-03-03 12:02:30 +01:00
2010-02-01 15:36:30 +01:00
case 28 : /* Atom */
2010-02-26 12:05:05 +01:00
memcpy ( hw_cache_event_ids , atom_hw_cache_event_ids ,
sizeof ( hw_cache_event_ids ) ) ;
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_init_atom ( ) ;
2010-02-26 12:05:05 +01:00
x86_pmu . event_constraints = intel_gen_event_constraints ;
2011-03-02 17:05:01 +02:00
x86_pmu . pebs_constraints = intel_atom_pebs_event_constraints ;
2010-02-26 12:05:05 +01:00
pr_cont ( " Atom events, " ) ;
break ;
case 37 : /* 32 nm nehalem, "Clarkdale" */
case 44 : /* 32 nm nehalem, "Gulftown" */
2011-04-21 16:48:35 -07:00
case 47 : /* 32 nm Xeon E7 */
2010-02-26 12:05:05 +01:00
memcpy ( hw_cache_event_ids , westmere_hw_cache_event_ids ,
sizeof ( hw_cache_event_ids ) ) ;
2011-03-03 10:34:48 +08:00
memcpy ( hw_cache_extra_regs , nehalem_hw_cache_extra_regs ,
sizeof ( hw_cache_extra_regs ) ) ;
2010-02-26 12:05:05 +01:00
2010-03-03 12:02:30 +01:00
intel_pmu_lbr_init_nhm ( ) ;
2010-02-26 12:05:05 +01:00
x86_pmu . event_constraints = intel_westmere_event_constraints ;
2010-03-29 16:37:17 +02:00
x86_pmu . enable_all = intel_pmu_nhm_enable_all ;
2011-03-02 17:05:01 +02:00
x86_pmu . pebs_constraints = intel_westmere_pebs_event_constraints ;
2011-03-03 10:34:47 +08:00
x86_pmu . extra_regs = intel_westmere_extra_regs ;
2011-05-23 11:08:15 +02:00
x86_pmu . er_flags | = ERF_HAS_RSP_1 ;
2011-04-30 09:14:54 +02:00
/* UOPS_ISSUED.STALLED_CYCLES */
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_FRONTEND ] =
X86_CONFIG ( . event = 0x0e , . umask = 0x01 , . inv = 1 , . cmask = 1 ) ;
2011-04-30 09:14:54 +02:00
/* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_BACKEND ] =
X86_CONFIG ( . event = 0xb1 , . umask = 0x3f , . inv = 1 , . cmask = 1 ) ;
2011-04-30 09:14:54 +02:00
2010-02-26 12:05:05 +01:00
pr_cont ( " Westmere events, " ) ;
break ;
2010-02-01 15:36:30 +01:00
2011-03-02 21:27:04 +08:00
case 42 : /* SandyBridge */
2011-08-02 14:01:35 +08:00
case 45 : /* SandyBridge, "Romely-EP" */
2012-06-05 10:26:43 +02:00
x86_add_quirk ( intel_sandybridge_quirk ) ;
case 58 : /* IvyBridge */
2011-03-02 21:27:04 +08:00
memcpy ( hw_cache_event_ids , snb_hw_cache_event_ids ,
sizeof ( hw_cache_event_ids ) ) ;
2012-02-09 23:20:55 +01:00
intel_pmu_lbr_init_snb ( ) ;
2011-03-02 21:27:04 +08:00
x86_pmu . event_constraints = intel_snb_event_constraints ;
2011-08-30 20:41:05 -03:00
x86_pmu . pebs_constraints = intel_snb_pebs_event_constraints ;
2012-06-05 10:26:43 +02:00
x86_pmu . pebs_aliases = intel_pebs_aliases_snb ;
2011-06-06 16:57:12 +02:00
x86_pmu . extra_regs = intel_snb_extra_regs ;
/* all extra regs are per-cpu when HT is on */
2011-05-23 11:08:15 +02:00
x86_pmu . er_flags | = ERF_HAS_RSP_1 ;
x86_pmu . er_flags | = ERF_NO_HT_SHARING ;
2011-05-06 07:14:02 +00:00
/* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_FRONTEND ] =
X86_CONFIG ( . event = 0x0e , . umask = 0x01 , . inv = 1 , . cmask = 1 ) ;
2011-05-06 07:14:02 +00:00
/* UOPS_DISPATCHED.THREAD,c=1,i=1 to count stall cycles*/
2012-03-12 12:44:35 +01:00
intel_perfmon_event_map [ PERF_COUNT_HW_STALLED_CYCLES_BACKEND ] =
X86_CONFIG ( . event = 0xb1 , . umask = 0x01 , . inv = 1 , . cmask = 1 ) ;
2011-05-06 07:14:02 +00:00
2011-03-02 21:27:04 +08:00
pr_cont ( " SandyBridge events, " ) ;
break ;
2010-02-26 12:05:05 +01:00
default :
2011-06-29 18:42:36 +03:00
switch ( x86_pmu . version ) {
case 1 :
x86_pmu . event_constraints = intel_v1_event_constraints ;
pr_cont ( " generic architected perfmon v1, " ) ;
break ;
default :
/*
* default constraints for v2 and up
*/
x86_pmu . event_constraints = intel_gen_event_constraints ;
pr_cont ( " generic architected perfmon, " ) ;
break ;
}
2010-02-26 12:05:05 +01:00
}
2011-11-10 14:57:26 +02:00
2010-02-26 12:05:05 +01:00
return 0 ;
}