aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/events-msr.txt37
-rw-r--r--Documentation/trace/postprocess/decode_msr.py37
-rw-r--r--arch/x86/include/asm/msr-trace.h57
-rw-r--r--arch/x86/include/asm/msr.h31
-rw-r--r--arch/x86/lib/msr.c26
5 files changed, 188 insertions, 0 deletions
diff --git a/Documentation/trace/events-msr.txt b/Documentation/trace/events-msr.txt
new file mode 100644
index 000000000000..78c383bf06aa
--- /dev/null
+++ b/Documentation/trace/events-msr.txt
@@ -0,0 +1,37 @@
1
2The x86 kernel supports tracing most MSR (Model Specific Register) accesses.
3To see the definition of the MSRs on Intel systems please see the SDM
4at http://www.intel.com/sdm (Volume 3)
5
6Available trace points:
7
8/sys/kernel/debug/tracing/events/msr/
9
10Trace MSR reads
11
12read_msr
13
14msr: MSR number
15val: Value written
16failed: 1 if the access failed, otherwise 0
17
18
19Trace MSR writes
20
21write_msr
22
23msr: MSR number
24val: Value written
25failed: 1 if the access failed, otherwise 0
26
27
28Trace RDPMC in kernel
29
30rdpmc
31
32The trace data can be post processed with the postprocess/decode_msr.py script
33
34cat /sys/kernel/debug/tracing/trace | decode_msr.py /usr/src/linux/include/asm/msr-index.h
35
36to add symbolic MSR names.
37
diff --git a/Documentation/trace/postprocess/decode_msr.py b/Documentation/trace/postprocess/decode_msr.py
new file mode 100644
index 000000000000..0ab40e0db580
--- /dev/null
+++ b/Documentation/trace/postprocess/decode_msr.py
@@ -0,0 +1,37 @@
1#!/usr/bin/python
2# add symbolic names to read_msr / write_msr in trace
3# decode_msr msr-index.h < trace
4import sys
5import re
6
7msrs = dict()
8
9with open(sys.argv[1] if len(sys.argv) > 1 else "msr-index.h", "r") as f:
10 for j in f:
11 m = re.match(r'#define (MSR_\w+)\s+(0x[0-9a-fA-F]+)', j)
12 if m:
13 msrs[int(m.group(2), 16)] = m.group(1)
14
15extra_ranges = (
16 ( "MSR_LASTBRANCH_%d_FROM_IP", 0x680, 0x69F ),
17 ( "MSR_LASTBRANCH_%d_TO_IP", 0x6C0, 0x6DF ),
18 ( "LBR_INFO_%d", 0xdc0, 0xddf ),
19)
20
21for j in sys.stdin:
22 m = re.search(r'(read|write)_msr:\s+([0-9a-f]+)', j)
23 if m:
24 r = None
25 num = int(m.group(2), 16)
26 if num in msrs:
27 r = msrs[num]
28 else:
29 for er in extra_ranges:
30 if er[1] <= num <= er[2]:
31 r = er[0] % (num - er[1],)
32 break
33 if r:
34 j = j.replace(" " + m.group(2), " " + r + "(" + m.group(2) + ")")
35 print j,
36
37
diff --git a/arch/x86/include/asm/msr-trace.h b/arch/x86/include/asm/msr-trace.h
new file mode 100644
index 000000000000..7567225747d8
--- /dev/null
+++ b/arch/x86/include/asm/msr-trace.h
@@ -0,0 +1,57 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM msr
3
4#undef TRACE_INCLUDE_FILE
5#define TRACE_INCLUDE_FILE msr-trace
6
7#undef TRACE_INCLUDE_PATH
8#define TRACE_INCLUDE_PATH asm/
9
10#if !defined(_TRACE_MSR_H) || defined(TRACE_HEADER_MULTI_READ)
11#define _TRACE_MSR_H
12
13#include <linux/tracepoint.h>
14
15/*
16 * Tracing for x86 model specific registers. Directly maps to the
17 * RDMSR/WRMSR instructions.
18 */
19
20DECLARE_EVENT_CLASS(msr_trace_class,
21 TP_PROTO(unsigned msr, u64 val, int failed),
22 TP_ARGS(msr, val, failed),
23 TP_STRUCT__entry(
24 __field( unsigned, msr )
25 __field( u64, val )
26 __field( int, failed )
27 ),
28 TP_fast_assign(
29 __entry->msr = msr;
30 __entry->val = val;
31 __entry->failed = failed;
32 ),
33 TP_printk("%x, value %llx%s",
34 __entry->msr,
35 __entry->val,
36 __entry->failed ? " #GP" : "")
37);
38
39DEFINE_EVENT(msr_trace_class, read_msr,
40 TP_PROTO(unsigned msr, u64 val, int failed),
41 TP_ARGS(msr, val, failed)
42);
43
44DEFINE_EVENT(msr_trace_class, write_msr,
45 TP_PROTO(unsigned msr, u64 val, int failed),
46 TP_ARGS(msr, val, failed)
47);
48
49DEFINE_EVENT(msr_trace_class, rdpmc,
50 TP_PROTO(unsigned msr, u64 val, int failed),
51 TP_ARGS(msr, val, failed)
52);
53
54#endif /* _TRACE_MSR_H */
55
56/* This part must be outside protection */
57#include <trace/define_trace.h>
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 77d8b284e4a7..fedd6e6d1e43 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -57,11 +57,34 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
57#define EAX_EDX_RET(val, low, high) "=A" (val) 57#define EAX_EDX_RET(val, low, high) "=A" (val)
58#endif 58#endif
59 59
60#ifdef CONFIG_TRACEPOINTS
61/*
62 * Be very careful with includes. This header is prone to include loops.
63 */
64#include <asm/atomic.h>
65#include <linux/tracepoint-defs.h>
66
67extern struct tracepoint __tracepoint_read_msr;
68extern struct tracepoint __tracepoint_write_msr;
69extern struct tracepoint __tracepoint_rdpmc;
70#define msr_tracepoint_active(t) static_key_false(&(t).key)
71extern void do_trace_write_msr(unsigned msr, u64 val, int failed);
72extern void do_trace_read_msr(unsigned msr, u64 val, int failed);
73extern void do_trace_rdpmc(unsigned msr, u64 val, int failed);
74#else
75#define msr_tracepoint_active(t) false
76static inline void do_trace_write_msr(unsigned msr, u64 val, int failed) {}
77static inline void do_trace_read_msr(unsigned msr, u64 val, int failed) {}
78static inline void do_trace_rdpmc(unsigned msr, u64 val, int failed) {}
79#endif
80
60static inline unsigned long long native_read_msr(unsigned int msr) 81static inline unsigned long long native_read_msr(unsigned int msr)
61{ 82{
62 DECLARE_ARGS(val, low, high); 83 DECLARE_ARGS(val, low, high);
63 84
64 asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); 85 asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
86 if (msr_tracepoint_active(__tracepoint_read_msr))
87 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0);
65 return EAX_EDX_VAL(val, low, high); 88 return EAX_EDX_VAL(val, low, high);
66} 89}
67 90
@@ -78,6 +101,8 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
78 _ASM_EXTABLE(2b, 3b) 101 _ASM_EXTABLE(2b, 3b)
79 : [err] "=r" (*err), EAX_EDX_RET(val, low, high) 102 : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
80 : "c" (msr), [fault] "i" (-EIO)); 103 : "c" (msr), [fault] "i" (-EIO));
104 if (msr_tracepoint_active(__tracepoint_read_msr))
105 do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err);
81 return EAX_EDX_VAL(val, low, high); 106 return EAX_EDX_VAL(val, low, high);
82} 107}
83 108
@@ -85,6 +110,8 @@ static inline void native_write_msr(unsigned int msr,
85 unsigned low, unsigned high) 110 unsigned low, unsigned high)
86{ 111{
87 asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); 112 asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
113 if (msr_tracepoint_active(__tracepoint_read_msr))
114 do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
88} 115}
89 116
90/* Can be uninlined because referenced by paravirt */ 117/* Can be uninlined because referenced by paravirt */
@@ -102,6 +129,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
102 : "c" (msr), "0" (low), "d" (high), 129 : "c" (msr), "0" (low), "d" (high),
103 [fault] "i" (-EIO) 130 [fault] "i" (-EIO)
104 : "memory"); 131 : "memory");
132 if (msr_tracepoint_active(__tracepoint_read_msr))
133 do_trace_write_msr(msr, ((u64)high << 32 | low), err);
105 return err; 134 return err;
106} 135}
107 136
@@ -160,6 +189,8 @@ static inline unsigned long long native_read_pmc(int counter)
160 DECLARE_ARGS(val, low, high); 189 DECLARE_ARGS(val, low, high);
161 190
162 asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); 191 asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
192 if (msr_tracepoint_active(__tracepoint_rdpmc))
193 do_trace_rdpmc(counter, EAX_EDX_VAL(val, low, high), 0);
163 return EAX_EDX_VAL(val, low, high); 194 return EAX_EDX_VAL(val, low, high);
164} 195}
165 196
diff --git a/arch/x86/lib/msr.c b/arch/x86/lib/msr.c
index 43623739c7cf..004c861b1648 100644
--- a/arch/x86/lib/msr.c
+++ b/arch/x86/lib/msr.c
@@ -1,6 +1,8 @@
1#include <linux/module.h> 1#include <linux/module.h>
2#include <linux/preempt.h> 2#include <linux/preempt.h>
3#include <asm/msr.h> 3#include <asm/msr.h>
4#define CREATE_TRACE_POINTS
5#include <asm/msr-trace.h>
4 6
5struct msr *msrs_alloc(void) 7struct msr *msrs_alloc(void)
6{ 8{
@@ -108,3 +110,27 @@ int msr_clear_bit(u32 msr, u8 bit)
108{ 110{
109 return __flip_bit(msr, bit, false); 111 return __flip_bit(msr, bit, false);
110} 112}
113
114#ifdef CONFIG_TRACEPOINTS
115void do_trace_write_msr(unsigned msr, u64 val, int failed)
116{
117 trace_write_msr(msr, val, failed);
118}
119EXPORT_SYMBOL(do_trace_write_msr);
120EXPORT_TRACEPOINT_SYMBOL(write_msr);
121
122void do_trace_read_msr(unsigned msr, u64 val, int failed)
123{
124 trace_read_msr(msr, val, failed);
125}
126EXPORT_SYMBOL(do_trace_read_msr);
127EXPORT_TRACEPOINT_SYMBOL(read_msr);
128
129void do_trace_rdpmc(unsigned counter, u64 val, int failed)
130{
131 trace_rdpmc(counter, val, failed);
132}
133EXPORT_SYMBOL(do_trace_rdpmc);
134EXPORT_TRACEPOINT_SYMBOL(rdpmc);
135
136#endif