|
Packit |
577717 |
/* $Id: perfctr.h,v 1.1.2.16 2010/11/07 19:46:06 mikpe Exp $
|
|
Packit |
577717 |
* x86/x86_64 Performance-Monitoring Counters driver
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* Copyright (C) 1999-2010 Mikael Pettersson
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#ifndef _ASM_X86_PERFCTR_H
|
|
Packit |
577717 |
#define _ASM_X86_PERFCTR_H
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* cpu_type values */
|
|
Packit |
577717 |
#define PERFCTR_X86_GENERIC 0 /* any x86 with rdtsc */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P5 1 /* no rdpmc */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P5MMX 2
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P6 3
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_PII 4
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_PIII 5
|
|
Packit |
577717 |
#define PERFCTR_X86_CYRIX_MII 6
|
|
Packit |
577717 |
#define PERFCTR_X86_WINCHIP_C6 7 /* no rdtsc */
|
|
Packit |
577717 |
#define PERFCTR_X86_WINCHIP_2 8 /* no rdtsc */
|
|
Packit |
577717 |
#define PERFCTR_X86_AMD_K7 9
|
|
Packit |
577717 |
#define PERFCTR_X86_VIA_C3 10 /* no pmc0 */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P4 11 /* model 0 and 1 */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P4M2 12 /* model 2 */
|
|
Packit |
577717 |
#define PERFCTR_X86_AMD_K8 13
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_PENTM 14 /* Pentium M */
|
|
Packit |
577717 |
#define PERFCTR_X86_AMD_K8C 15 /* Revision C */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_P4M3 16 /* model 3 and above */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_CORE 17 /* family 6 model 14 */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_CORE2 18 /* family 6, models 15, 22, 23, 29 */
|
|
Packit |
577717 |
#define PERFCTR_X86_AMD_FAM10H 19 /* family 10h, family 11h */
|
|
Packit |
577717 |
#define PERFCTR_X86_AMD_FAM10 PERFCTR_X86_AMD_FAM10H /* XXX: compat crap, delete soon */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_ATOM 20 /* family 6 model 28 */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_NHLM 21 /* Nehalem: family 6 models 26, 30, 46 */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_COREI7 PERFCTR_X86_INTEL_NHLM /* XXX: compat crap, delete soon */
|
|
Packit |
577717 |
#define PERFCTR_X86_INTEL_WSTMR 22 /* Westmere: family 6 models 37, 44 */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct perfctr_sum_ctrs {
|
|
Packit |
577717 |
unsigned long long tsc;
|
|
Packit |
577717 |
unsigned long long pmc[18];
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct perfctr_cpu_control {
|
|
Packit |
577717 |
unsigned int tsc_on;
|
|
Packit |
577717 |
unsigned int nractrs; /* # of a-mode counters */
|
|
Packit |
577717 |
unsigned int nrictrs; /* # of i-mode counters */
|
|
Packit |
577717 |
unsigned int pmc_map[18];
|
|
Packit |
577717 |
unsigned int evntsel[18]; /* one per counter, even on P5 */
|
|
Packit |
577717 |
union {
|
|
Packit |
577717 |
/* Note: envtsel_high[] and p4.escr[] must occupy the same locations */
|
|
Packit |
577717 |
struct {
|
|
Packit |
577717 |
unsigned int escr[18];
|
|
Packit |
577717 |
unsigned int pebs_enable; /* for replay tagging */
|
|
Packit |
577717 |
unsigned int pebs_matrix_vert; /* for replay tagging */
|
|
Packit |
577717 |
} p4;
|
|
Packit |
577717 |
unsigned int evntsel_high[18];
|
|
Packit |
577717 |
/* Note: nhlm.offcore_rsp[] must not overlap evntsel_high[],
|
|
Packit |
577717 |
instead we make it overlap the p4.pebs_ fields */
|
|
Packit |
577717 |
struct {
|
|
Packit |
577717 |
unsigned int _padding[18];
|
|
Packit |
577717 |
unsigned int offcore_rsp[2];
|
|
Packit |
577717 |
} nhlm;
|
|
Packit |
577717 |
}; /* XXX: should be a named field 'u', but that breaks source-code compatibility */
|
|
Packit |
577717 |
int ireset[18]; /* < 0, for i-mode counters */
|
|
Packit |
577717 |
unsigned int _reserved1;
|
|
Packit |
577717 |
unsigned int _reserved2;
|
|
Packit |
577717 |
unsigned int _reserved3;
|
|
Packit |
577717 |
unsigned int _reserved4;
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
struct perfctr_cpu_state {
|
|
Packit |
577717 |
unsigned int cstatus;
|
|
Packit |
577717 |
struct { /* k1 is opaque in the user ABI */
|
|
Packit |
577717 |
unsigned int id;
|
|
Packit |
577717 |
int isuspend_cpu;
|
|
Packit |
577717 |
} k1;
|
|
Packit |
577717 |
/* The two tsc fields must be inlined. Placing them in a
|
|
Packit |
577717 |
sub-struct causes unwanted internal padding on x86-64. */
|
|
Packit |
577717 |
unsigned int tsc_start;
|
|
Packit |
577717 |
unsigned long long tsc_sum;
|
|
Packit |
577717 |
struct {
|
|
Packit |
577717 |
unsigned int map;
|
|
Packit |
577717 |
unsigned int start;
|
|
Packit |
577717 |
unsigned long long sum;
|
|
Packit |
577717 |
} pmc[18]; /* the size is not part of the user ABI */
|
|
Packit |
577717 |
#ifdef __KERNEL__
|
|
Packit |
577717 |
struct perfctr_cpu_control control;
|
|
Packit |
577717 |
unsigned int core2_fixed_ctr_ctrl;
|
|
Packit |
577717 |
unsigned int p4_escr_map[18];
|
|
Packit |
577717 |
#ifdef CONFIG_PERFCTR_INTERRUPT_SUPPORT
|
|
Packit |
577717 |
unsigned int pending_interrupt;
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
};
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* cstatus is a re-encoding of control.tsc_on/nractrs/nrictrs
|
|
Packit |
577717 |
which should have less overhead in most cases */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline
|
|
Packit |
577717 |
unsigned int __perfctr_mk_cstatus(unsigned int tsc_on, unsigned int have_ictrs,
|
|
Packit |
577717 |
unsigned int nrictrs, unsigned int nractrs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (tsc_on<<31) | (have_ictrs<<16) | ((nractrs+nrictrs)<<8) | nractrs;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline
|
|
Packit |
577717 |
unsigned int perfctr_mk_cstatus(unsigned int tsc_on, unsigned int nractrs,
|
|
Packit |
577717 |
unsigned int nrictrs)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return __perfctr_mk_cstatus(tsc_on, nrictrs, nrictrs, nractrs);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline unsigned int perfctr_cstatus_enabled(unsigned int cstatus)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return cstatus;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline int perfctr_cstatus_has_tsc(unsigned int cstatus)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (int)cstatus < 0; /* test and jump on sign */
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline unsigned int perfctr_cstatus_nractrs(unsigned int cstatus)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return cstatus & 0x7F; /* and with imm8 */
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline unsigned int perfctr_cstatus_nrctrs(unsigned int cstatus)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return (cstatus >> 8) & 0x7F;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
static inline unsigned int perfctr_cstatus_has_ictrs(unsigned int cstatus)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return cstatus & (0x7F << 16);
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/*
|
|
Packit |
577717 |
* 'struct siginfo' support for perfctr overflow signals.
|
|
Packit |
577717 |
* In unbuffered mode, si_code is set to SI_PMC_OVF and a bitmask
|
|
Packit |
577717 |
* describing which perfctrs overflowed is put in si_pmc_ovf_mask.
|
|
Packit |
577717 |
* A bitmask is used since more than one perfctr can have overflowed
|
|
Packit |
577717 |
* by the time the interrupt handler runs.
|
|
Packit |
577717 |
*
|
|
Packit |
577717 |
* glibc's <signal.h> doesn't seem to define __SI_FAULT or __SI_CODE(),
|
|
Packit |
577717 |
* and including <asm/siginfo.h> as well may cause redefinition errors,
|
|
Packit |
577717 |
* so the user and kernel values are different #defines here.
|
|
Packit |
577717 |
*/
|
|
Packit |
577717 |
#ifdef __KERNEL__
|
|
Packit |
577717 |
#define SI_PMC_OVF (__SI_FAULT|'P')
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
#define SI_PMC_OVF ('P')
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#define si_pmc_ovf_mask _sifields._pad[0] /* XXX: use an unsigned field later */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* version number for user-visible CPU-specific data */
|
|
Packit |
577717 |
#define PERFCTR_CPU_VERSION 0x0501 /* 5.1 */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#ifdef __KERNEL__
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(CONFIG_PERFCTR) || defined(CONFIG_PERFCTR_MODULE)
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Driver init/exit. */
|
|
Packit |
577717 |
extern int perfctr_cpu_init(void);
|
|
Packit |
577717 |
extern void perfctr_cpu_exit(void);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* CPU type name. */
|
|
Packit |
577717 |
extern char *perfctr_cpu_name;
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Hardware reservation. */
|
|
Packit |
577717 |
extern const char *perfctr_cpu_reserve(const char *service);
|
|
Packit |
577717 |
extern void perfctr_cpu_release(const char *service);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* PRE: state has no running interrupt-mode counters.
|
|
Packit |
577717 |
Check that the new control data is valid.
|
|
Packit |
577717 |
Update the driver's private control data.
|
|
Packit |
577717 |
cpumask must be NULL for global-mode counters and non-NULL
|
|
Packit |
577717 |
for per-thread counters. If cpumask is non-NULL and the control
|
|
Packit |
577717 |
data requires the task to be restricted to a specific set of
|
|
Packit |
577717 |
CPUs, then *cpumask will be updated accordingly.
|
|
Packit |
577717 |
Returns a negative error code if the control data is invalid. */
|
|
Packit |
577717 |
extern int perfctr_cpu_update_control(struct perfctr_cpu_state *state, cpumask_t *cpumask);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Read a-mode counters. Subtract from start and accumulate into sums.
|
|
Packit |
577717 |
Must be called with preemption disabled. */
|
|
Packit |
577717 |
extern void perfctr_cpu_suspend(struct perfctr_cpu_state *state);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Write control registers. Read a-mode counters into start.
|
|
Packit |
577717 |
Must be called with preemption disabled. */
|
|
Packit |
577717 |
extern void perfctr_cpu_resume(struct perfctr_cpu_state *state);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Perform an efficient combined suspend/resume operation.
|
|
Packit |
577717 |
Must be called with preemption disabled. */
|
|
Packit |
577717 |
extern void perfctr_cpu_sample(struct perfctr_cpu_state *state);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* The type of a perfctr overflow interrupt handler.
|
|
Packit |
577717 |
It will be called in IRQ context, with preemption disabled. */
|
|
Packit |
577717 |
typedef void (*perfctr_ihandler_t)(unsigned long pc);
|
|
Packit |
577717 |
|
|
Packit |
577717 |
/* Operations related to overflow interrupt handling. */
|
|
Packit |
577717 |
#ifdef CONFIG_X86_LOCAL_APIC
|
|
Packit |
577717 |
extern void __perfctr_cpu_mask_interrupts(void);
|
|
Packit |
577717 |
extern void __perfctr_cpu_unmask_interrupts(void);
|
|
Packit |
577717 |
extern void perfctr_cpu_set_ihandler(perfctr_ihandler_t);
|
|
Packit |
577717 |
extern void perfctr_cpu_ireload(struct perfctr_cpu_state*);
|
|
Packit |
577717 |
extern unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state*);
|
|
Packit |
577717 |
static inline int perfctr_cpu_has_pending_interrupt(const struct perfctr_cpu_state *state)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return state->pending_interrupt;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
static inline void perfctr_cpu_set_ihandler(perfctr_ihandler_t x) { }
|
|
Packit |
577717 |
static inline int perfctr_cpu_has_pending_interrupt(const struct perfctr_cpu_state *state)
|
|
Packit |
577717 |
{
|
|
Packit |
577717 |
return 0;
|
|
Packit |
577717 |
}
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#endif /* CONFIG_PERFCTR */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#if defined(CONFIG_KPERFCTR) && defined(CONFIG_X86_LOCAL_APIC)
|
|
Packit |
577717 |
asmlinkage void perfctr_interrupt(struct pt_regs*);
|
|
Packit |
577717 |
#include <linux/version.h>
|
|
Packit |
577717 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) /* 2.6.27-rc1 */
|
|
Packit |
577717 |
#define perfctr_vector_init() \
|
|
Packit |
577717 |
alloc_intr_gate(LOCAL_PERFCTR_VECTOR, perfctr_interrupt)
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
#define perfctr_vector_init() \
|
|
Packit |
577717 |
set_intr_gate(LOCAL_PERFCTR_VECTOR, perfctr_interrupt)
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
#else
|
|
Packit |
577717 |
#define perfctr_vector_init() do{}while(0)
|
|
Packit |
577717 |
#endif
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#endif /* __KERNEL__ */
|
|
Packit |
577717 |
|
|
Packit |
577717 |
#endif /* _ASM_X86_PERFCTR_H */
|