You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (184 commits) perf probe: Clean up probe_point_lazy_walker() return value tracing: Fix irqoff selftest expanding max buffer tracing: Align 4 byte ints together in struct tracer tracing: Export trace_set_clr_event() tracing: Explain about unstable clock on resume with ring buffer warning ftrace/graph: Trace function entry before updating index ftrace: Add .ref.text as one of the safe areas to trace tracing: Adjust conditional expression latency formatting. tracing: Fix event alignment: skb:kfree_skb tracing: Fix event alignment: mce:mce_record tracing: Fix event alignment: kvm:kvm_hv_hypercall tracing: Fix event alignment: module:module_request tracing: Fix event alignment: ftrace:context_switch and ftrace:wakeup tracing: Remove lock_depth from event entry perf header: Stop using 'self' perf session: Use evlist/evsel for managing perf.data attributes perf top: Don't let events to eat up whole header line perf top: Fix events overflow in top command ring-buffer: Remove unused #include <linux/trace_irq.h> tracing: Add an 'overwrite' trace_option. ...
This commit is contained in:
@@ -247,6 +247,13 @@ You need very few things to get the syscalls tracing in an arch.
|
||||
- Support the TIF_SYSCALL_TRACEPOINT thread flags.
|
||||
- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
|
||||
in the ptrace syscalls tracing path.
|
||||
- If the system call table on this arch is more complicated than a simple array
|
||||
of addresses of the system calls, implement an arch_syscall_addr to return
|
||||
the address of a given system call.
|
||||
- If the symbol names of the system calls do not match the function names on
|
||||
this arch, define ARCH_HAS_SYSCALL_MATCH_SYM_NAME in asm/ftrace.h and
|
||||
implement arch_syscall_match_sym_name with the appropriate logic to return
|
||||
true if the function name corresponds with the symbol name.
|
||||
- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
|
||||
|
||||
|
||||
|
||||
+23
-128
@@ -80,11 +80,11 @@ of ftrace. Here is a list of some of the key files:
|
||||
tracers listed here can be configured by
|
||||
echoing their name into current_tracer.
|
||||
|
||||
tracing_enabled:
|
||||
tracing_on:
|
||||
|
||||
This sets or displays whether the current_tracer
|
||||
is activated and tracing or not. Echo 0 into this
|
||||
file to disable the tracer or 1 to enable it.
|
||||
This sets or displays whether writing to the trace
|
||||
ring buffer is enabled. Echo 0 into this file to disable
|
||||
the tracer or 1 to enable it.
|
||||
|
||||
trace:
|
||||
|
||||
@@ -202,10 +202,6 @@ Here is the list of current tracers that may be configured.
|
||||
to draw a graph of function calls similar to C code
|
||||
source.
|
||||
|
||||
"sched_switch"
|
||||
|
||||
Traces the context switches and wakeups between tasks.
|
||||
|
||||
"irqsoff"
|
||||
|
||||
Traces the areas that disable interrupts and saves
|
||||
@@ -273,39 +269,6 @@ format, the function name that was traced "path_put" and the
|
||||
parent function that called this function "path_walk". The
|
||||
timestamp is the time at which the function was entered.
|
||||
|
||||
The sched_switch tracer also includes tracing of task wakeups
|
||||
and context switches.
|
||||
|
||||
ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 2916:115:S
|
||||
ksoftirqd/1-7 [01] 1453.070013: 7:115:R + 10:115:S
|
||||
ksoftirqd/1-7 [01] 1453.070013: 7:115:R ==> 10:115:R
|
||||
events/1-10 [01] 1453.070013: 10:115:S ==> 2916:115:R
|
||||
kondemand/1-2916 [01] 1453.070013: 2916:115:S ==> 7:115:R
|
||||
ksoftirqd/1-7 [01] 1453.070013: 7:115:S ==> 0:140:R
|
||||
|
||||
Wake ups are represented by a "+" and the context switches are
|
||||
shown as "==>". The format is:
|
||||
|
||||
Context switches:
|
||||
|
||||
Previous task Next Task
|
||||
|
||||
<pid>:<prio>:<state> ==> <pid>:<prio>:<state>
|
||||
|
||||
Wake ups:
|
||||
|
||||
Current task Task waking up
|
||||
|
||||
<pid>:<prio>:<state> + <pid>:<prio>:<state>
|
||||
|
||||
The prio is the internal kernel priority, which is the inverse
|
||||
of the priority that is usually displayed by user-space tools.
|
||||
Zero represents the highest priority (99). Prio 100 starts the
|
||||
"nice" priorities with 100 being equal to nice -20 and 139 being
|
||||
nice 19. The prio "140" is reserved for the idle task which is
|
||||
the lowest priority thread (pid 0).
|
||||
|
||||
|
||||
Latency trace format
|
||||
--------------------
|
||||
|
||||
@@ -491,78 +454,10 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
|
||||
latencies, as described in "Latency
|
||||
trace format".
|
||||
|
||||
sched_switch
|
||||
------------
|
||||
|
||||
This tracer simply records schedule switches. Here is an example
|
||||
of how to use it.
|
||||
|
||||
# echo sched_switch > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# sleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
# cat trace
|
||||
|
||||
# tracer: sched_switch
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
# | | | | |
|
||||
bash-3997 [01] 240.132281: 3997:120:R + 4055:120:R
|
||||
bash-3997 [01] 240.132284: 3997:120:R ==> 4055:120:R
|
||||
sleep-4055 [01] 240.132371: 4055:120:S ==> 3997:120:R
|
||||
bash-3997 [01] 240.132454: 3997:120:R + 4055:120:S
|
||||
bash-3997 [01] 240.132457: 3997:120:R ==> 4055:120:R
|
||||
sleep-4055 [01] 240.132460: 4055:120:D ==> 3997:120:R
|
||||
bash-3997 [01] 240.132463: 3997:120:R + 4055:120:D
|
||||
bash-3997 [01] 240.132465: 3997:120:R ==> 4055:120:R
|
||||
<idle>-0 [00] 240.132589: 0:140:R + 4:115:S
|
||||
<idle>-0 [00] 240.132591: 0:140:R ==> 4:115:R
|
||||
ksoftirqd/0-4 [00] 240.132595: 4:115:S ==> 0:140:R
|
||||
<idle>-0 [00] 240.132598: 0:140:R + 4:115:S
|
||||
<idle>-0 [00] 240.132599: 0:140:R ==> 4:115:R
|
||||
ksoftirqd/0-4 [00] 240.132603: 4:115:S ==> 0:140:R
|
||||
sleep-4055 [01] 240.133058: 4055:120:S ==> 3997:120:R
|
||||
[...]
|
||||
|
||||
|
||||
As we have discussed previously about this format, the header
|
||||
shows the name of the trace and points to the options. The
|
||||
"FUNCTION" is a misnomer since here it represents the wake ups
|
||||
and context switches.
|
||||
|
||||
The sched_switch file only lists the wake ups (represented with
|
||||
'+') and context switches ('==>') with the previous task or
|
||||
current task first followed by the next task or task waking up.
|
||||
The format for both of these is PID:KERNEL-PRIO:TASK-STATE.
|
||||
Remember that the KERNEL-PRIO is the inverse of the actual
|
||||
priority with zero (0) being the highest priority and the nice
|
||||
values starting at 100 (nice -20). Below is a quick chart to map
|
||||
the kernel priority to user land priorities.
|
||||
|
||||
Kernel Space User Space
|
||||
===============================================================
|
||||
0(high) to 98(low) user RT priority 99(high) to 1(low)
|
||||
with SCHED_RR or SCHED_FIFO
|
||||
---------------------------------------------------------------
|
||||
99 sched_priority is not used in scheduling
|
||||
decisions(it must be specified as 0)
|
||||
---------------------------------------------------------------
|
||||
100(high) to 139(low) user nice -20(high) to 19(low)
|
||||
---------------------------------------------------------------
|
||||
140 idle task priority
|
||||
---------------------------------------------------------------
|
||||
|
||||
The task states are:
|
||||
|
||||
R - running : wants to run, may not actually be running
|
||||
S - sleep : process is waiting to be woken up (handles signals)
|
||||
D - disk sleep (uninterruptible sleep) : process must be woken up
|
||||
(ignores signals)
|
||||
T - stopped : process suspended
|
||||
t - traced : process is being traced (with something like gdb)
|
||||
Z - zombie : process waiting to be cleaned up
|
||||
X - unknown
|
||||
|
||||
overwrite - This controls what happens when the trace buffer is
|
||||
full. If "1" (default), the oldest events are
|
||||
discarded and overwritten. If "0", then the newest
|
||||
events are discarded.
|
||||
|
||||
ftrace_enabled
|
||||
--------------
|
||||
@@ -607,10 +502,10 @@ an example:
|
||||
# echo irqsoff > current_tracer
|
||||
# echo latency-format > trace_options
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: irqsoff
|
||||
#
|
||||
@@ -715,10 +610,10 @@ is much like the irqsoff tracer.
|
||||
# echo preemptoff > current_tracer
|
||||
# echo latency-format > trace_options
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: preemptoff
|
||||
#
|
||||
@@ -863,10 +758,10 @@ tracers.
|
||||
# echo preemptirqsoff > current_tracer
|
||||
# echo latency-format > trace_options
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: preemptirqsoff
|
||||
#
|
||||
@@ -1026,9 +921,9 @@ Instead of performing an 'ls', we will run 'sleep 1' under
|
||||
# echo wakeup > current_tracer
|
||||
# echo latency-format > trace_options
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# chrt -f 5 sleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: wakeup
|
||||
#
|
||||
@@ -1140,9 +1035,9 @@ ftrace_enabled is set; otherwise this tracer is a nop.
|
||||
|
||||
# sysctl kernel.ftrace_enabled=1
|
||||
# echo function > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# usleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: function
|
||||
#
|
||||
@@ -1180,7 +1075,7 @@ int trace_fd;
|
||||
[...]
|
||||
int main(int argc, char *argv[]) {
|
||||
[...]
|
||||
trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY);
|
||||
trace_fd = open(tracing_file("tracing_on"), O_WRONLY);
|
||||
[...]
|
||||
if (condition_hit()) {
|
||||
write(trace_fd, "0", 1);
|
||||
@@ -1631,9 +1526,9 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:
|
||||
# echo sys_nanosleep hrtimer_interrupt \
|
||||
> set_ftrace_filter
|
||||
# echo function > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# usleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: ftrace
|
||||
#
|
||||
@@ -1879,9 +1774,9 @@ different. The trace is live.
|
||||
# echo function > current_tracer
|
||||
# cat trace_pipe > /tmp/trace.out &
|
||||
[1] 4153
|
||||
# echo 1 > tracing_enabled
|
||||
# echo 1 > tracing_on
|
||||
# usleep 1
|
||||
# echo 0 > tracing_enabled
|
||||
# echo 0 > tracing_on
|
||||
# cat trace
|
||||
# tracer: function
|
||||
#
|
||||
|
||||
@@ -42,11 +42,25 @@ Synopsis of kprobe_events
|
||||
+|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
|
||||
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
|
||||
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
|
||||
(u8/u16/u32/u64/s8/s16/s32/s64) and string are supported.
|
||||
(u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
|
||||
are supported.
|
||||
|
||||
(*) only for return probe.
|
||||
(**) this is useful for fetching a field of data structures.
|
||||
|
||||
Types
|
||||
-----
|
||||
Several types are supported for fetch-args. Kprobe tracer will access memory
|
||||
by given type. Prefix 's' and 'u' means those types are signed and unsigned
|
||||
respectively. Traced arguments are shown in decimal (signed) or hex (unsigned).
|
||||
String type is a special type, which fetches a "null-terminated" string from
|
||||
kernel space. This means it will fail and store NULL if the string container
|
||||
has been paged out.
|
||||
Bitfield is another special type, which takes 3 parameters, bit-width, bit-
|
||||
offset, and container-size (usually 32). The syntax is;
|
||||
|
||||
b<bit-width>@<bit-offset>/<container-size>
|
||||
|
||||
|
||||
Per-Probe Event Filtering
|
||||
-------------------------
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#define sysretl_audit ia32_ret_from_sys_call
|
||||
#endif
|
||||
|
||||
.section .entry.text, "ax"
|
||||
|
||||
#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
|
||||
|
||||
.macro IA32_ARG_FIXUP noebp=0
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
|
||||
#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
|
||||
#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
|
||||
#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
|
||||
|
||||
/*
|
||||
* Auxiliary flags: Linux defined - For features scattered in various
|
||||
@@ -279,6 +280,7 @@ extern const char * const x86_power_flags[32];
|
||||
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
|
||||
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
|
||||
#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ)
|
||||
#define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
|
||||
|
||||
#if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
|
||||
# define cpu_has_invlpg 1
|
||||
|
||||
@@ -13,7 +13,6 @@ enum die_val {
|
||||
DIE_PANIC,
|
||||
DIE_NMI,
|
||||
DIE_DIE,
|
||||
DIE_NMIWATCHDOG,
|
||||
DIE_KERNELDEBUG,
|
||||
DIE_TRAP,
|
||||
DIE_GPF,
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
#define MSR_IA32_MCG_STATUS 0x0000017a
|
||||
#define MSR_IA32_MCG_CTL 0x0000017b
|
||||
|
||||
#define MSR_OFFCORE_RSP_0 0x000001a6
|
||||
#define MSR_OFFCORE_RSP_1 0x000001a7
|
||||
|
||||
#define MSR_IA32_PEBS_ENABLE 0x000003f1
|
||||
#define MSR_IA32_DS_AREA 0x00000600
|
||||
#define MSR_IA32_PERF_CAPABILITIES 0x00000345
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
|
||||
extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
|
||||
extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
|
||||
extern int reserve_perfctr_nmi(unsigned int);
|
||||
extern void release_perfctr_nmi(unsigned int);
|
||||
|
||||
@@ -17,10 +17,20 @@
|
||||
#endif
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/cpumask.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
extern int smp_num_siblings;
|
||||
extern unsigned int num_processors;
|
||||
|
||||
static inline bool cpu_has_ht_siblings(void)
|
||||
{
|
||||
bool has_siblings = false;
|
||||
#ifdef CONFIG_SMP
|
||||
has_siblings = cpu_has_ht && smp_num_siblings > 1;
|
||||
#endif
|
||||
return has_siblings;
|
||||
}
|
||||
|
||||
DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
|
||||
DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
|
||||
DECLARE_PER_CPU(u16, cpu_llc_id);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <asm/stacktrace.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/compat.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#if 0
|
||||
#undef wrmsrl
|
||||
@@ -93,6 +94,8 @@ struct amd_nb {
|
||||
struct event_constraint event_constraints[X86_PMC_IDX_MAX];
|
||||
};
|
||||
|
||||
struct intel_percore;
|
||||
|
||||
#define MAX_LBR_ENTRIES 16
|
||||
|
||||
struct cpu_hw_events {
|
||||
@@ -127,6 +130,13 @@ struct cpu_hw_events {
|
||||
struct perf_branch_stack lbr_stack;
|
||||
struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
|
||||
|
||||
/*
|
||||
* Intel percore register state.
|
||||
* Coordinate shared resources between HT threads.
|
||||
*/
|
||||
int percore_used; /* Used by this CPU? */
|
||||
struct intel_percore *per_core;
|
||||
|
||||
/*
|
||||
* AMD specific bits
|
||||
*/
|
||||
@@ -166,8 +176,10 @@ struct cpu_hw_events {
|
||||
/*
|
||||
* Constraint on the Event code + UMask
|
||||
*/
|
||||
#define PEBS_EVENT_CONSTRAINT(c, n) \
|
||||
#define INTEL_UEVENT_CONSTRAINT(c, n) \
|
||||
EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
|
||||
#define PEBS_EVENT_CONSTRAINT(c, n) \
|
||||
INTEL_UEVENT_CONSTRAINT(c, n)
|
||||
|
||||
#define EVENT_CONSTRAINT_END \
|
||||
EVENT_CONSTRAINT(0, 0, 0)
|
||||
@@ -175,6 +187,28 @@ struct cpu_hw_events {
|
||||
#define for_each_event_constraint(e, c) \
|
||||
for ((e) = (c); (e)->weight; (e)++)
|
||||
|
||||
/*
|
||||
* Extra registers for specific events.
|
||||
* Some events need large masks and require external MSRs.
|
||||
* Define a mapping to these extra registers.
|
||||
*/
|
||||
struct extra_reg {
|
||||
unsigned int event;
|
||||
unsigned int msr;
|
||||
u64 config_mask;
|
||||
u64 valid_mask;
|
||||
};
|
||||
|
||||
#define EVENT_EXTRA_REG(e, ms, m, vm) { \
|
||||
.event = (e), \
|
||||
.msr = (ms), \
|
||||
.config_mask = (m), \
|
||||
.valid_mask = (vm), \
|
||||
}
|
||||
#define INTEL_EVENT_EXTRA_REG(event, msr, vm) \
|
||||
EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
|
||||
#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
|
||||
|
||||
union perf_capabilities {
|
||||
struct {
|
||||
u64 lbr_format : 6;
|
||||
@@ -219,6 +253,7 @@ struct x86_pmu {
|
||||
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
|
||||
struct perf_event *event);
|
||||
struct event_constraint *event_constraints;
|
||||
struct event_constraint *percore_constraints;
|
||||
void (*quirks)(void);
|
||||
int perfctr_second_write;
|
||||
|
||||
@@ -247,6 +282,11 @@ struct x86_pmu {
|
||||
*/
|
||||
unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */
|
||||
int lbr_nr; /* hardware stack size */
|
||||
|
||||
/*
|
||||
* Extra registers for events
|
||||
*/
|
||||
struct extra_reg *extra_regs;
|
||||
};
|
||||
|
||||
static struct x86_pmu x86_pmu __read_mostly;
|
||||
@@ -271,6 +311,10 @@ static u64 __read_mostly hw_cache_event_ids
|
||||
[PERF_COUNT_HW_CACHE_MAX]
|
||||
[PERF_COUNT_HW_CACHE_OP_MAX]
|
||||
[PERF_COUNT_HW_CACHE_RESULT_MAX];
|
||||
static u64 __read_mostly hw_cache_extra_regs
|
||||
[PERF_COUNT_HW_CACHE_MAX]
|
||||
[PERF_COUNT_HW_CACHE_OP_MAX]
|
||||
[PERF_COUNT_HW_CACHE_RESULT_MAX];
|
||||
|
||||
/*
|
||||
* Propagate event elapsed time into the generic event.
|
||||
@@ -298,7 +342,7 @@ x86_perf_event_update(struct perf_event *event)
|
||||
*/
|
||||
again:
|
||||
prev_raw_count = local64_read(&hwc->prev_count);
|
||||
rdmsrl(hwc->event_base + idx, new_raw_count);
|
||||
rdmsrl(hwc->event_base, new_raw_count);
|
||||
|
||||
if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
|
||||
new_raw_count) != prev_raw_count)
|
||||
@@ -321,6 +365,49 @@ again:
|
||||
return new_raw_count;
|
||||
}
|
||||
|
||||
/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */
|
||||
static inline int x86_pmu_addr_offset(int index)
|
||||
{
|
||||
if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
|
||||
return index << 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
static inline unsigned int x86_pmu_config_addr(int index)
|
||||
{
|
||||
return x86_pmu.eventsel + x86_pmu_addr_offset(index);
|
||||
}
|
||||
|
||||
static inline unsigned int x86_pmu_event_addr(int index)
|
||||
{
|
||||
return x86_pmu.perfctr + x86_pmu_addr_offset(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find and validate any extra registers to set up.
|
||||
*/
|
||||
static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
|
||||
{
|
||||
struct extra_reg *er;
|
||||
|
||||
event->hw.extra_reg = 0;
|
||||
event->hw.extra_config = 0;
|
||||
|
||||
if (!x86_pmu.extra_regs)
|
||||
return 0;
|
||||
|
||||
for (er = x86_pmu.extra_regs; er->msr; er++) {
|
||||
if (er->event != (config & er->config_mask))
|
||||
continue;
|
||||
if (event->attr.config1 & ~er->valid_mask)
|
||||
return -EINVAL;
|
||||
event->hw.extra_reg = er->msr;
|
||||
event->hw.extra_config = event->attr.config1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static atomic_t active_events;
|
||||
static DEFINE_MUTEX(pmc_reserve_mutex);
|
||||
|
||||
@@ -331,12 +418,12 @@ static bool reserve_pmc_hardware(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < x86_pmu.num_counters; i++) {
|
||||
if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
|
||||
if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
|
||||
goto perfctr_fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < x86_pmu.num_counters; i++) {
|
||||
if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
|
||||
if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
|
||||
goto eventsel_fail;
|
||||
}
|
||||
|
||||
@@ -344,13 +431,13 @@ static bool reserve_pmc_hardware(void)
|
||||
|
||||
eventsel_fail:
|
||||
for (i--; i >= 0; i--)
|
||||
release_evntsel_nmi(x86_pmu.eventsel + i);
|
||||
release_evntsel_nmi(x86_pmu_config_addr(i));
|
||||
|
||||
i = x86_pmu.num_counters;
|
||||
|
||||
perfctr_fail:
|
||||
for (i--; i >= 0; i--)
|
||||
release_perfctr_nmi(x86_pmu.perfctr + i);
|
||||
release_perfctr_nmi(x86_pmu_event_addr(i));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -360,8 +447,8 @@ static void release_pmc_hardware(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < x86_pmu.num_counters; i++) {
|
||||
release_perfctr_nmi(x86_pmu.perfctr + i);
|
||||
release_evntsel_nmi(x86_pmu.eventsel + i);
|
||||
release_perfctr_nmi(x86_pmu_event_addr(i));
|
||||
release_evntsel_nmi(x86_pmu_config_addr(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,7 +469,7 @@ static bool check_hw_exists(void)
|
||||
* complain and bail.
|
||||
*/
|
||||
for (i = 0; i < x86_pmu.num_counters; i++) {
|
||||
reg = x86_pmu.eventsel + i;
|
||||
reg = x86_pmu_config_addr(i);
|
||||
ret = rdmsrl_safe(reg, &val);
|
||||
if (ret)
|
||||
goto msr_fail;
|
||||
@@ -407,8 +494,8 @@ static bool check_hw_exists(void)
|
||||
* that don't trap on the MSR access and always return 0s.
|
||||
*/
|
||||
val = 0xabcdUL;
|
||||
ret = checking_wrmsrl(x86_pmu.perfctr, val);
|
||||
ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
|
||||
ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
|
||||
ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
|
||||
if (ret || val != val_new)
|
||||
goto msr_fail;
|
||||
|
||||
@@ -442,8 +529,9 @@ static inline int x86_pmu_initialized(void)
|
||||
}
|
||||
|
||||
static inline int
|
||||
set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
|
||||
set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
|
||||
{
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
unsigned int cache_type, cache_op, cache_result;
|
||||
u64 config, val;
|
||||
|
||||
@@ -470,8 +558,8 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
|
||||
return -EINVAL;
|
||||
|
||||
hwc->config |= val;
|
||||
|
||||
return 0;
|
||||
attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
|
||||
return x86_pmu_extra_regs(val, event);
|
||||
}
|
||||
|
||||
static int x86_setup_perfctr(struct perf_event *event)
|
||||
@@ -496,10 +584,10 @@ static int x86_setup_perfctr(struct perf_event *event)
|
||||
}
|
||||
|
||||
if (attr->type == PERF_TYPE_RAW)
|
||||
return 0;
|
||||
return x86_pmu_extra_regs(event->attr.config, event);
|
||||
|
||||
if (attr->type == PERF_TYPE_HW_CACHE)
|
||||
return set_ext_hw_attr(hwc, attr);
|
||||
return set_ext_hw_attr(hwc, event);
|
||||
|
||||
if (attr->config >= x86_pmu.max_events)
|
||||
return -EINVAL;
|
||||
@@ -617,11 +705,11 @@ static void x86_pmu_disable_all(void)
|
||||
|
||||
if (!test_bit(idx, cpuc->active_mask))
|
||||
continue;
|
||||
rdmsrl(x86_pmu.eventsel + idx, val);
|
||||
rdmsrl(x86_pmu_config_addr(idx), val);
|
||||
if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
|
||||
continue;
|
||||
val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
|
||||
wrmsrl(x86_pmu.eventsel + idx, val);
|
||||
wrmsrl(x86_pmu_config_addr(idx), val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,21 +730,26 @@ static void x86_pmu_disable(struct pmu *pmu)
|
||||
x86_pmu.disable_all();
|
||||
}
|
||||
|
||||
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
|
||||
u64 enable_mask)
|
||||
{
|
||||
if (hwc->extra_reg)
|
||||
wrmsrl(hwc->extra_reg, hwc->extra_config);
|
||||
wrmsrl(hwc->config_base, hwc->config | enable_mask);
|
||||
}
|
||||
|
||||
static void x86_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 perf_event *event = cpuc->events[idx];
|
||||
u64 val;
|
||||
struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
|
||||
|
||||
if (!test_bit(idx, cpuc->active_mask))
|
||||
continue;
|
||||
|
||||
val = event->hw.config;
|
||||
val |= ARCH_PERFMON_EVENTSEL_ENABLE;
|
||||
wrmsrl(x86_pmu.eventsel + idx, val);
|
||||
__x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -821,15 +914,10 @@ static inline void x86_assign_hw_event(struct perf_event *event,
|
||||
hwc->event_base = 0;
|
||||
} else if (hwc->idx >= X86_PMC_IDX_FIXED) {
|
||||
hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
|
||||
/*
|
||||
* We set it so that event_base + idx in wrmsr/rdmsr maps to
|
||||
* MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
|
||||
*/
|
||||
hwc->event_base =
|
||||
MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
|
||||
hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0;
|
||||
} else {
|
||||
hwc->config_base = x86_pmu.eventsel;
|
||||
hwc->event_base = x86_pmu.perfctr;
|
||||
hwc->config_base = x86_pmu_config_addr(hwc->idx);
|
||||
hwc->event_base = x86_pmu_event_addr(hwc->idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,17 +1003,11 @@ static void x86_pmu_enable(struct pmu *pmu)
|
||||
x86_pmu.enable_all(added);
|
||||
}
|
||||
|
||||
static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
|
||||
u64 enable_mask)
|
||||
{
|
||||
wrmsrl(hwc->config_base + hwc->idx, hwc->config | enable_mask);
|
||||
}
|
||||
|
||||
static inline void x86_pmu_disable_event(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
wrmsrl(hwc->config_base + hwc->idx, hwc->config);
|
||||
wrmsrl(hwc->config_base, hwc->config);
|
||||
}
|
||||
|
||||
static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
|
||||
@@ -978,7 +1060,7 @@ x86_perf_event_set_period(struct perf_event *event)
|
||||
*/
|
||||
local64_set(&hwc->prev_count, (u64)-left);
|
||||
|
||||
wrmsrl(hwc->event_base + idx, (u64)(-left) & x86_pmu.cntval_mask);
|
||||
wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
|
||||
|
||||
/*
|
||||
* Due to erratum on certan cpu we need
|
||||
@@ -986,7 +1068,7 @@ x86_perf_event_set_period(struct perf_event *event)
|
||||
* is updated properly
|
||||
*/
|
||||
if (x86_pmu.perfctr_second_write) {
|
||||
wrmsrl(hwc->event_base + idx,
|
||||
wrmsrl(hwc->event_base,
|
||||
(u64)(-left) & x86_pmu.cntval_mask);
|
||||
}
|
||||
|
||||
@@ -1113,8 +1195,8 @@ void perf_event_print_debug(void)
|
||||
pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask);
|
||||
|
||||
for (idx = 0; idx < x86_pmu.num_counters; idx++) {
|
||||
rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
|
||||
rdmsrl(x86_pmu.perfctr + idx, pmc_count);
|
||||
rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
|
||||
rdmsrl(x86_pmu_event_addr(idx), pmc_count);
|
||||
|
||||
prev_left = per_cpu(pmc_prev_left[idx], cpu);
|
||||
|
||||
@@ -1389,7 +1471,7 @@ static void __init pmu_check_apic(void)
|
||||
pr_info("no hardware sampling interrupt available.\n");
|
||||
}
|
||||
|
||||
int __init init_hw_perf_events(void)
|
||||
static int __init init_hw_perf_events(void)
|
||||
{
|
||||
struct event_constraint *c;
|
||||
int err;
|
||||
@@ -1608,7 +1690,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x86_pmu_event_init(struct perf_event *event)
|
||||
static int x86_pmu_event_init(struct perf_event *event)
|
||||
{
|
||||
struct pmu *tmp;
|
||||
int err;
|
||||
|
||||
@@ -127,6 +127,11 @@ static int amd_pmu_hw_config(struct perf_event *event)
|
||||
/*
|
||||
* AMD64 events are detected based on their event codes.
|
||||
*/
|
||||
static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
|
||||
{
|
||||
return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
|
||||
}
|
||||
|
||||
static inline int amd_is_nb_event(struct hw_perf_event *hwc)
|
||||
{
|
||||
return (hwc->config & 0xe0) == 0xe0;
|
||||
@@ -385,13 +390,181 @@ static __initconst const struct x86_pmu amd_pmu = {
|
||||
.cpu_dead = amd_pmu_cpu_dead,
|
||||
};
|
||||
|
||||
/* AMD Family 15h */
|
||||
|
||||
#define AMD_EVENT_TYPE_MASK 0x000000F0ULL
|
||||
|
||||
#define AMD_EVENT_FP 0x00000000ULL ... 0x00000010ULL
|
||||
#define AMD_EVENT_LS 0x00000020ULL ... 0x00000030ULL
|
||||
#define AMD_EVENT_DC 0x00000040ULL ... 0x00000050ULL
|
||||
#define AMD_EVENT_CU 0x00000060ULL ... 0x00000070ULL
|
||||
#define AMD_EVENT_IC_DE 0x00000080ULL ... 0x00000090ULL
|
||||
#define AMD_EVENT_EX_LS 0x000000C0ULL
|
||||
#define AMD_EVENT_DE 0x000000D0ULL
|
||||
#define AMD_EVENT_NB 0x000000E0ULL ... 0x000000F0ULL
|
||||
|
||||
/*
|
||||
* AMD family 15h event code/PMC mappings:
|
||||
*
|
||||
* type = event_code & 0x0F0:
|
||||
*
|
||||
* 0x000 FP PERF_CTL[5:3]
|
||||
* 0x010 FP PERF_CTL[5:3]
|
||||
* 0x020 LS PERF_CTL[5:0]
|
||||
* 0x030 LS PERF_CTL[5:0]
|
||||
* 0x040 DC PERF_CTL[5:0]
|
||||
* 0x050 DC PERF_CTL[5:0]
|
||||
* 0x060 CU PERF_CTL[2:0]
|
||||
* 0x070 CU PERF_CTL[2:0]
|
||||
* 0x080 IC/DE PERF_CTL[2:0]
|
||||
* 0x090 IC/DE PERF_CTL[2:0]
|
||||
* 0x0A0 ---
|
||||
* 0x0B0 ---
|
||||
* 0x0C0 EX/LS PERF_CTL[5:0]
|
||||
* 0x0D0 DE PERF_CTL[2:0]
|
||||
* 0x0E0 NB NB_PERF_CTL[3:0]
|
||||
* 0x0F0 NB NB_PERF_CTL[3:0]
|
||||
*
|
||||
* Exceptions:
|
||||
*
|
||||
* 0x003 FP PERF_CTL[3]
|
||||
* 0x00B FP PERF_CTL[3]
|
||||
* 0x00D FP PERF_CTL[3]
|
||||
* 0x023 DE PERF_CTL[2:0]
|
||||
* 0x02D LS PERF_CTL[3]
|
||||
* 0x02E LS PERF_CTL[3,0]
|
||||
* 0x043 CU PERF_CTL[2:0]
|
||||
* 0x045 CU PERF_CTL[2:0]
|
||||
* 0x046 CU PERF_CTL[2:0]
|
||||
* 0x054 CU PERF_CTL[2:0]
|
||||
* 0x055 CU PERF_CTL[2:0]
|
||||
* 0x08F IC PERF_CTL[0]
|
||||
* 0x187 DE PERF_CTL[0]
|
||||
* 0x188 DE PERF_CTL[0]
|
||||
* 0x0DB EX PERF_CTL[5:0]
|
||||
* 0x0DC LS PERF_CTL[5:0]
|
||||
* 0x0DD LS PERF_CTL[5:0]
|
||||
* 0x0DE LS PERF_CTL[5:0]
|
||||
* 0x0DF LS PERF_CTL[5:0]
|
||||
* 0x1D6 EX PERF_CTL[5:0]
|
||||
* 0x1D8 EX PERF_CTL[5:0]
|
||||
*/
|
||||
|
||||
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
|
||||
static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
|
||||
static struct event_constraint amd_f15_PMC3 = EVENT_CONSTRAINT(0, 0x08, 0);
|
||||
static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT(0, 0x09, 0);
|
||||
static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
|
||||
static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
|
||||
|
||||
static struct event_constraint *
|
||||
amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
|
||||
{
|
||||
unsigned int event_code = amd_get_event_code(&event->hw);
|
||||
|
||||
switch (event_code & AMD_EVENT_TYPE_MASK) {
|
||||
case AMD_EVENT_FP:
|
||||
switch (event_code) {
|
||||
case 0x003:
|
||||
case 0x00B:
|
||||
case 0x00D:
|
||||
return &amd_f15_PMC3;
|
||||
default:
|
||||
return &amd_f15_PMC53;
|
||||
}
|
||||
case AMD_EVENT_LS:
|
||||
case AMD_EVENT_DC:
|
||||
case AMD_EVENT_EX_LS:
|
||||
switch (event_code) {
|
||||
case 0x023:
|
||||
case 0x043:
|
||||
case 0x045:
|
||||
case 0x046:
|
||||
case 0x054:
|
||||
case 0x055:
|
||||
return &amd_f15_PMC20;
|
||||
case 0x02D:
|
||||
return &amd_f15_PMC3;
|
||||
case 0x02E:
|
||||
return &amd_f15_PMC30;
|
||||
default:
|
||||
return &amd_f15_PMC50;
|
||||
}
|
||||
case AMD_EVENT_CU:
|
||||
case AMD_EVENT_IC_DE:
|
||||
case AMD_EVENT_DE:
|
||||
switch (event_code) {
|
||||
case 0x08F:
|
||||
case 0x187:
|
||||
case 0x188:
|
||||
return &amd_f15_PMC0;
|
||||
case 0x0DB ... 0x0DF:
|
||||
case 0x1D6:
|
||||
case 0x1D8:
|
||||
return &amd_f15_PMC50;
|
||||
default:
|
||||
return &amd_f15_PMC20;
|
||||
}
|
||||
case AMD_EVENT_NB:
|
||||
/* not yet implemented */
|
||||
return &emptyconstraint;
|
||||
default:
|
||||
return &emptyconstraint;
|
||||
}
|
||||
}
|
||||
|
||||
static __initconst const struct x86_pmu amd_pmu_f15h = {
|
||||
.name = "AMD Family 15h",
|
||||
.handle_irq = x86_pmu_handle_irq,
|
||||
.disable_all = x86_pmu_disable_all,
|
||||
.enable_all = x86_pmu_enable_all,
|
||||
.enable = x86_pmu_enable_event,
|
||||
.disable = x86_pmu_disable_event,
|
||||
.hw_config = amd_pmu_hw_config,
|
||||
.schedule_events = x86_schedule_events,
|
||||
.eventsel = MSR_F15H_PERF_CTL,
|
||||
.perfctr = MSR_F15H_PERF_CTR,
|
||||
.event_map = amd_pmu_event_map,
|
||||
.max_events = ARRAY_SIZE(amd_perfmon_event_map),
|
||||
.num_counters = 6,
|
||||
.cntval_bits = 48,
|
||||
.cntval_mask = (1ULL << 48) - 1,
|
||||
.apic = 1,
|
||||
/* use highest bit to detect overflow */
|
||||
.max_period = (1ULL << 47) - 1,
|
||||
.get_event_constraints = amd_get_event_constraints_f15h,
|
||||
/* nortbridge counters not yet implemented: */
|
||||
#if 0
|
||||
.put_event_constraints = amd_put_event_constraints,
|
||||
|
||||
.cpu_prepare = amd_pmu_cpu_prepare,
|
||||
.cpu_starting = amd_pmu_cpu_starting,
|
||||
.cpu_dead = amd_pmu_cpu_dead,
|
||||
#endif
|
||||
};
|
||||
|
||||
static __init int amd_pmu_init(void)
|
||||
{
|
||||
/* Performance-monitoring supported from K7 and later: */
|
||||
if (boot_cpu_data.x86 < 6)
|
||||
return -ENODEV;
|
||||
|
||||
x86_pmu = amd_pmu;
|
||||
/*
|
||||
* If core performance counter extensions exists, it must be
|
||||
* family 15h, otherwise fail. See x86_pmu_addr_offset().
|
||||
*/
|
||||
switch (boot_cpu_data.x86) {
|
||||
case 0x15:
|
||||
if (!cpu_has_perfctr_core)
|
||||
return -ENODEV;
|
||||
x86_pmu = amd_pmu_f15h;
|
||||
break;
|
||||
default:
|
||||
if (cpu_has_perfctr_core)
|
||||
return -ENODEV;
|
||||
x86_pmu = amd_pmu;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Events are common for all AMDs */
|
||||
memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -361,30 +361,88 @@ static int intel_pmu_drain_bts_buffer(void)
|
||||
/*
|
||||
* PEBS
|
||||
*/
|
||||
|
||||
static struct event_constraint intel_core_pebs_events[] = {
|
||||
PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INSTR_RETIRED.ANY */
|
||||
static struct event_constraint intel_core2_pebs_event_constraints[] = {
|
||||
PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
|
||||
PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0x01cb, 0x1), /* MEM_LOAD_RETIRED.L1D_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x02cb, 0x1), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x04cb, 0x1), /* MEM_LOAD_RETIRED.L2_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x08cb, 0x1), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x10cb, 0x1), /* MEM_LOAD_RETIRED.DTLB_MISS */
|
||||
INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_nehalem_pebs_events[] = {
|
||||
PEBS_EVENT_CONSTRAINT(0x00c0, 0xf), /* INSTR_RETIRED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0xfec1, 0xf), /* X87_OPS_RETIRED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0x00c5, 0xf), /* BR_INST_RETIRED.MISPRED */
|
||||
PEBS_EVENT_CONSTRAINT(0x1fc7, 0xf), /* SIMD_INST_RETURED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0x01cb, 0xf), /* MEM_LOAD_RETIRED.L1D_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x02cb, 0xf), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x04cb, 0xf), /* MEM_LOAD_RETIRED.L2_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x08cb, 0xf), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x10cb, 0xf), /* MEM_LOAD_RETIRED.DTLB_MISS */
|
||||
static struct event_constraint intel_atom_pebs_event_constraints[] = {
|
||||
PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
|
||||
PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
|
||||
INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
|
||||
INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
|
||||
PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
|
||||
INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INST_RETIRED.ANY */
|
||||
INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
|
||||
PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
|
||||
INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
|
||||
PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
|
||||
INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_westmere_pebs_event_constraints[] = {
|
||||
INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
|
||||
PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
|
||||
INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INSTR_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
|
||||
|
||||
INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
|
||||
PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
|
||||
INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
|
||||
INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_snb_pebs_events[] = {
|
||||
PEBS_EVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
|
||||
PEBS_EVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
|
||||
PEBS_EVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
|
||||
PEBS_EVENT_CONSTRAINT(0x01c4, 0xf), /* BR_INST_RETIRED.CONDITIONAL */
|
||||
PEBS_EVENT_CONSTRAINT(0x02c4, 0xf), /* BR_INST_RETIRED.NEAR_CALL */
|
||||
PEBS_EVENT_CONSTRAINT(0x04c4, 0xf), /* BR_INST_RETIRED.ALL_BRANCHES */
|
||||
PEBS_EVENT_CONSTRAINT(0x08c4, 0xf), /* BR_INST_RETIRED.NEAR_RETURN */
|
||||
PEBS_EVENT_CONSTRAINT(0x10c4, 0xf), /* BR_INST_RETIRED.NOT_TAKEN */
|
||||
PEBS_EVENT_CONSTRAINT(0x20c4, 0xf), /* BR_INST_RETIRED.NEAR_TAKEN */
|
||||
PEBS_EVENT_CONSTRAINT(0x40c4, 0xf), /* BR_INST_RETIRED.FAR_BRANCH */
|
||||
PEBS_EVENT_CONSTRAINT(0x01c5, 0xf), /* BR_MISP_RETIRED.CONDITIONAL */
|
||||
PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
|
||||
PEBS_EVENT_CONSTRAINT(0x04c5, 0xf), /* BR_MISP_RETIRED.ALL_BRANCHES */
|
||||
PEBS_EVENT_CONSTRAINT(0x10c5, 0xf), /* BR_MISP_RETIRED.NOT_TAKEN */
|
||||
PEBS_EVENT_CONSTRAINT(0x20c5, 0xf), /* BR_MISP_RETIRED.TAKEN */
|
||||
PEBS_EVENT_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
|
||||
PEBS_EVENT_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORE */
|
||||
PEBS_EVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
|
||||
PEBS_EVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
|
||||
PEBS_EVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
|
||||
PEBS_EVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
|
||||
PEBS_EVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
|
||||
PEBS_EVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
|
||||
PEBS_EVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
|
||||
PEBS_EVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
|
||||
PEBS_EVENT_CONSTRAINT(0x01d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L1_HIT */
|
||||
PEBS_EVENT_CONSTRAINT(0x02d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L2_HIT */
|
||||
PEBS_EVENT_CONSTRAINT(0x04d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.LLC_HIT */
|
||||
PEBS_EVENT_CONSTRAINT(0x40d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.HIT_LFB */
|
||||
PEBS_EVENT_CONSTRAINT(0x01d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS */
|
||||
PEBS_EVENT_CONSTRAINT(0x02d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT */
|
||||
PEBS_EVENT_CONSTRAINT(0x04d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM */
|
||||
PEBS_EVENT_CONSTRAINT(0x08d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE */
|
||||
PEBS_EVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
@@ -695,20 +753,17 @@ static void intel_ds_init(void)
|
||||
printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
|
||||
x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
|
||||
x86_pmu.pebs_constraints = intel_core_pebs_events;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
printk(KERN_CONT "PEBS fmt1%c, ", pebs_type);
|
||||
x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
|
||||
x86_pmu.pebs_constraints = intel_nehalem_pebs_events;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type);
|
||||
x86_pmu.pebs = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,9 +764,9 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
|
||||
u64 v;
|
||||
|
||||
/* an official way for overflow indication */
|
||||
rdmsrl(hwc->config_base + hwc->idx, v);
|
||||
rdmsrl(hwc->config_base, v);
|
||||
if (v & P4_CCCR_OVF) {
|
||||
wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF);
|
||||
wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -815,7 +815,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event)
|
||||
* state we need to clear P4_CCCR_OVF, otherwise interrupt get
|
||||
* asserted again and again
|
||||
*/
|
||||
(void)checking_wrmsrl(hwc->config_base + hwc->idx,
|
||||
(void)checking_wrmsrl(hwc->config_base,
|
||||
(u64)(p4_config_unpack_cccr(hwc->config)) &
|
||||
~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
|
||||
}
|
||||
@@ -885,7 +885,7 @@ static void p4_pmu_enable_event(struct perf_event *event)
|
||||
p4_pmu_enable_pebs(hwc->config);
|
||||
|
||||
(void)checking_wrmsrl(escr_addr, escr_conf);
|
||||
(void)checking_wrmsrl(hwc->config_base + hwc->idx,
|
||||
(void)checking_wrmsrl(hwc->config_base,
|
||||
(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ p6_pmu_disable_event(struct perf_event *event)
|
||||
if (cpuc->enabled)
|
||||
val |= ARCH_PERFMON_EVENTSEL_ENABLE;
|
||||
|
||||
(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
|
||||
(void)checking_wrmsrl(hwc->config_base, val);
|
||||
}
|
||||
|
||||
static void p6_pmu_enable_event(struct perf_event *event)
|
||||
@@ -81,7 +81,7 @@ static void p6_pmu_enable_event(struct perf_event *event)
|
||||
if (cpuc->enabled)
|
||||
val |= ARCH_PERFMON_EVENTSEL_ENABLE;
|
||||
|
||||
(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
|
||||
(void)checking_wrmsrl(hwc->config_base, val);
|
||||
}
|
||||
|
||||
static __initconst const struct x86_pmu p6_pmu = {
|
||||
|
||||
@@ -46,6 +46,8 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
|
||||
/* returns the bit offset of the performance counter register */
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_AMD:
|
||||
if (msr >= MSR_F15H_PERF_CTR)
|
||||
return (msr - MSR_F15H_PERF_CTR) >> 1;
|
||||
return msr - MSR_K7_PERFCTR0;
|
||||
case X86_VENDOR_INTEL:
|
||||
if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
|
||||
@@ -70,6 +72,8 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
|
||||
/* returns the bit offset of the event selection register */
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_AMD:
|
||||
if (msr >= MSR_F15H_PERF_CTL)
|
||||
return (msr - MSR_F15H_PERF_CTL) >> 1;
|
||||
return msr - MSR_K7_EVNTSEL0;
|
||||
case X86_VENDOR_INTEL:
|
||||
if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
|
||||
|
||||
@@ -320,31 +320,6 @@ void die(const char *str, struct pt_regs *regs, long err)
|
||||
oops_end(flags, regs, sig);
|
||||
}
|
||||
|
||||
void notrace __kprobes
|
||||
die_nmi(char *str, struct pt_regs *regs, int do_panic)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We are in trouble anyway, lets at least try
|
||||
* to get a message out.
|
||||
*/
|
||||
flags = oops_begin();
|
||||
printk(KERN_EMERG "%s", str);
|
||||
printk(" on CPU%d, ip %08lx, registers:\n",
|
||||
smp_processor_id(), regs->ip);
|
||||
show_registers(regs);
|
||||
oops_end(flags, regs, 0);
|
||||
if (do_panic || panic_on_oops)
|
||||
panic("Non maskable interrupt");
|
||||
nmi_exit();
|
||||
local_irq_enable();
|
||||
do_exit(SIGBUS);
|
||||
}
|
||||
|
||||
static int __init oops_setup(char *s)
|
||||
{
|
||||
if (!s)
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
#define sysexit_audit syscall_exit_work
|
||||
#endif
|
||||
|
||||
.section .entry.text, "ax"
|
||||
|
||||
/*
|
||||
* We use macros for low-level operations which need to be overridden
|
||||
* for paravirtualization. The following will never clobber any registers:
|
||||
@@ -788,7 +790,7 @@ ENDPROC(ptregs_clone)
|
||||
*/
|
||||
.section .init.rodata,"a"
|
||||
ENTRY(interrupt)
|
||||
.text
|
||||
.section .entry.text, "ax"
|
||||
.p2align 5
|
||||
.p2align CONFIG_X86_L1_CACHE_SHIFT
|
||||
ENTRY(irq_entries_start)
|
||||
@@ -807,7 +809,7 @@ vector=FIRST_EXTERNAL_VECTOR
|
||||
.endif
|
||||
.previous
|
||||
.long 1b
|
||||
.text
|
||||
.section .entry.text, "ax"
|
||||
vector=vector+1
|
||||
.endif
|
||||
.endr
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#define __AUDIT_ARCH_LE 0x40000000
|
||||
|
||||
.code64
|
||||
.section .entry.text, "ax"
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
ENTRY(mcount)
|
||||
@@ -744,7 +746,7 @@ END(stub_rt_sigreturn)
|
||||
*/
|
||||
.section .init.rodata,"a"
|
||||
ENTRY(interrupt)
|
||||
.text
|
||||
.section .entry.text
|
||||
.p2align 5
|
||||
.p2align CONFIG_X86_L1_CACHE_SHIFT
|
||||
ENTRY(irq_entries_start)
|
||||
@@ -763,7 +765,7 @@ vector=FIRST_EXTERNAL_VECTOR
|
||||
.endif
|
||||
.previous
|
||||
.quad 1b
|
||||
.text
|
||||
.section .entry.text
|
||||
vector=vector+1
|
||||
.endif
|
||||
.endr
|
||||
|
||||
@@ -437,18 +437,19 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
|
||||
return;
|
||||
}
|
||||
|
||||
trace.func = self_addr;
|
||||
trace.depth = current->curr_ret_stack + 1;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
*parent = old;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftrace_push_return_trace(old, self_addr, &trace.depth,
|
||||
frame_pointer) == -EBUSY) {
|
||||
*parent = old;
|
||||
return;
|
||||
}
|
||||
|
||||
trace.func = self_addr;
|
||||
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
current->curr_ret_stack--;
|
||||
*parent = old;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user