aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-03-13 06:54:40 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-13 06:57:22 -0400
commite9a22d1fb94050b7d600019c32e6b672d539054b (patch)
tree1e062f00e3fe7a3ace7b0c6b930ed6cdacd37166
parent321bb5e1ac461c04b6a93f795010d6eb01d8c5ca (diff)
x86, bts: cleanups
Impact: cleanup, no code changed Cc: Markus Metzger <markus.t.metzger@intel.com> LKML-Reference: <20090313104218.A30096@sedona.ch.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/ds.c142
-rw-r--r--arch/x86/kernel/ds_selftest.h2
-rw-r--r--kernel/trace/trace_hw_branches.c6
-rw-r--r--kernel/trace/trace_selftest.c5
4 files changed, 87 insertions, 68 deletions
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index d9cab716805..7363e01ba08 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -19,43 +19,52 @@
19 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009 19 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
20 */ 20 */
21 21
22 22#include <linux/kernel.h>
23#include <asm/ds.h>
24
25#include <linux/errno.h>
26#include <linux/string.h> 23#include <linux/string.h>
27#include <linux/slab.h> 24#include <linux/errno.h>
28#include <linux/sched.h> 25#include <linux/sched.h>
26#include <linux/slab.h>
29#include <linux/mm.h> 27#include <linux/mm.h>
30#include <linux/kernel.h> 28
29#include <asm/ds.h>
31 30
32#include "ds_selftest.h" 31#include "ds_selftest.h"
33 32
34/* 33/*
35 * The configuration for a particular DS hardware implementation. 34 * The configuration for a particular DS hardware implementation:
36 */ 35 */
37struct ds_configuration { 36struct ds_configuration {
38 /* The name of the configuration. */ 37 /* The name of the configuration: */
39 const char *name; 38 const char *name;
40 /* The size of pointer-typed fields in DS, BTS, and PEBS. */ 39
41 unsigned char sizeof_ptr_field; 40 /* The size of pointer-typed fields in DS, BTS, and PEBS: */
42 /* The size of a BTS/PEBS record in bytes. */ 41 unsigned char sizeof_ptr_field;
43 unsigned char sizeof_rec[2]; 42
44 /* Control bit-masks indexed by enum ds_feature. */ 43 /* The size of a BTS/PEBS record in bytes: */
45 unsigned long ctl[dsf_ctl_max]; 44 unsigned char sizeof_rec[2];
45
46 /* Control bit-masks indexed by enum ds_feature: */
47 unsigned long ctl[dsf_ctl_max];
46}; 48};
47static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array); 49static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
48 50
49#define ds_cfg per_cpu(ds_cfg_array, smp_processor_id()) 51#define ds_cfg per_cpu(ds_cfg_array, smp_processor_id())
50 52
51#define MAX_SIZEOF_DS (12 * 8) /* Maximal size of a DS configuration. */ 53/* Maximal size of a DS configuration: */
52#define MAX_SIZEOF_BTS (3 * 8) /* Maximal size of a BTS record. */ 54#define MAX_SIZEOF_DS (12 * 8)
53#define DS_ALIGNMENT (1 << 3) /* BTS and PEBS buffer alignment. */
54 55
55#define BTS_CONTROL \ 56/* Maximal size of a BTS record: */
56 (ds_cfg.ctl[dsf_bts] | ds_cfg.ctl[dsf_bts_kernel] | ds_cfg.ctl[dsf_bts_user] |\ 57#define MAX_SIZEOF_BTS (3 * 8)
57 ds_cfg.ctl[dsf_bts_overflow])
58 58
59/* BTS and PEBS buffer alignment: */
60#define DS_ALIGNMENT (1 << 3)
61
62/* Mask of control bits in the DS MSR register: */
63#define BTS_CONTROL \
64 ( ds_cfg.ctl[dsf_bts] | \
65 ds_cfg.ctl[dsf_bts_kernel] | \
66 ds_cfg.ctl[dsf_bts_user] | \
67 ds_cfg.ctl[dsf_bts_overflow] )
59 68
60/* 69/*
61 * A BTS or PEBS tracer. 70 * A BTS or PEBS tracer.
@@ -65,28 +74,32 @@ static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
65 */ 74 */
66struct ds_tracer { 75struct ds_tracer {
67 /* The DS context (partially) owned by this tracer. */ 76 /* The DS context (partially) owned by this tracer. */
68 struct ds_context *context; 77 struct ds_context *context;
69 /* The buffer provided on ds_request() and its size in bytes. */ 78 /* The buffer provided on ds_request() and its size in bytes. */
70 void *buffer; 79 void *buffer;
71 size_t size; 80 size_t size;
72}; 81};
73 82
74struct bts_tracer { 83struct bts_tracer {
75 /* The common DS part. */ 84 /* The common DS part: */
76 struct ds_tracer ds; 85 struct ds_tracer ds;
77 /* The trace including the DS configuration. */ 86
78 struct bts_trace trace; 87 /* The trace including the DS configuration: */
79 /* Buffer overflow notification function. */ 88 struct bts_trace trace;
80 bts_ovfl_callback_t ovfl; 89
90 /* Buffer overflow notification function: */
91 bts_ovfl_callback_t ovfl;
81}; 92};
82 93
83struct pebs_tracer { 94struct pebs_tracer {
84 /* The common DS part. */ 95 /* The common DS part: */
85 struct ds_tracer ds; 96 struct ds_tracer ds;
86 /* The trace including the DS configuration. */ 97
87 struct pebs_trace trace; 98 /* The trace including the DS configuration: */
88 /* Buffer overflow notification function. */ 99 struct pebs_trace trace;
89 pebs_ovfl_callback_t ovfl; 100
101 /* Buffer overflow notification function: */
102 pebs_ovfl_callback_t ovfl;
90}; 103};
91 104
92/* 105/*
@@ -95,6 +108,7 @@ struct pebs_tracer {
95 * 108 *
96 * The DS configuration consists of the following fields; different 109 * The DS configuration consists of the following fields; different
97 * architetures vary in the size of those fields. 110 * architetures vary in the size of those fields.
111 *
98 * - double-word aligned base linear address of the BTS buffer 112 * - double-word aligned base linear address of the BTS buffer
99 * - write pointer into the BTS buffer 113 * - write pointer into the BTS buffer
100 * - end linear address of the BTS buffer (one byte beyond the end of 114 * - end linear address of the BTS buffer (one byte beyond the end of
@@ -133,19 +147,20 @@ enum ds_field {
133}; 147};
134 148
135enum ds_qualifier { 149enum ds_qualifier {
136 ds_bts = 0, 150 ds_bts = 0,
137 ds_pebs 151 ds_pebs
138}; 152};
139 153
140static inline unsigned long ds_get(const unsigned char *base, 154static inline unsigned long
141 enum ds_qualifier qual, enum ds_field field) 155ds_get(const unsigned char *base, enum ds_qualifier qual, enum ds_field field)
142{ 156{
143 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual))); 157 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
144 return *(unsigned long *)base; 158 return *(unsigned long *)base;
145} 159}
146 160
147static inline void ds_set(unsigned char *base, enum ds_qualifier qual, 161static inline void
148 enum ds_field field, unsigned long value) 162ds_set(unsigned char *base, enum ds_qualifier qual, enum ds_field field,
163 unsigned long value)
149{ 164{
150 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual))); 165 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
151 (*(unsigned long *)base) = value; 166 (*(unsigned long *)base) = value;
@@ -157,7 +172,6 @@ static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
157 */ 172 */
158static DEFINE_SPINLOCK(ds_lock); 173static DEFINE_SPINLOCK(ds_lock);
159 174
160
161/* 175/*
162 * We either support (system-wide) per-cpu or per-thread allocation. 176 * We either support (system-wide) per-cpu or per-thread allocation.
163 * We distinguish the two based on the task_struct pointer, where a 177 * We distinguish the two based on the task_struct pointer, where a
@@ -211,17 +225,21 @@ static inline int check_tracer(struct task_struct *task)
211 * deallocated when the last user puts the context. 225 * deallocated when the last user puts the context.
212 */ 226 */
213struct ds_context { 227struct ds_context {
214 /* The DS configuration; goes into MSR_IA32_DS_AREA. */ 228 /* The DS configuration; goes into MSR_IA32_DS_AREA: */
215 unsigned char ds[MAX_SIZEOF_DS]; 229 unsigned char ds[MAX_SIZEOF_DS];
216 /* The owner of the BTS and PEBS configuration, respectively. */ 230
217 struct bts_tracer *bts_master; 231 /* The owner of the BTS and PEBS configuration, respectively: */
218 struct pebs_tracer *pebs_master; 232 struct bts_tracer *bts_master;
219 /* Use count. */ 233 struct pebs_tracer *pebs_master;
234
235 /* Use count: */
220 unsigned long count; 236 unsigned long count;
221 /* Pointer to the context pointer field. */ 237
222 struct ds_context **this; 238 /* Pointer to the context pointer field: */
223 /* The traced task; NULL for current cpu. */ 239 struct ds_context **this;
224 struct task_struct *task; 240
241 /* The traced task; NULL for current cpu: */
242 struct task_struct *task;
225}; 243};
226 244
227static DEFINE_PER_CPU(struct ds_context *, system_context_array); 245static DEFINE_PER_CPU(struct ds_context *, system_context_array);
@@ -328,9 +346,9 @@ static void ds_overflow(struct ds_context *context, enum ds_qualifier qual)
328 * The remainder of any partially written record is zeroed out. 346 * The remainder of any partially written record is zeroed out.
329 * 347 *
330 * context: the DS context 348 * context: the DS context
331 * qual: the buffer type 349 * qual: the buffer type
332 * record: the data to write 350 * record: the data to write
333 * size: the size of the data 351 * size: the size of the data
334 */ 352 */
335static int ds_write(struct ds_context *context, enum ds_qualifier qual, 353static int ds_write(struct ds_context *context, enum ds_qualifier qual,
336 const void *record, size_t size) 354 const void *record, size_t size)
@@ -429,12 +447,12 @@ enum bts_field {
429 bts_to, 447 bts_to,
430 bts_flags, 448 bts_flags,
431 449
432 bts_qual = bts_from, 450 bts_qual = bts_from,
433 bts_jiffies = bts_to, 451 bts_jiffies = bts_to,
434 bts_pid = bts_flags, 452 bts_pid = bts_flags,
435 453
436 bts_qual_mask = (bts_qual_max - 1), 454 bts_qual_mask = (bts_qual_max - 1),
437 bts_escape = ((unsigned long)-1 & ~bts_qual_mask) 455 bts_escape = ((unsigned long)-1 & ~bts_qual_mask)
438}; 456};
439 457
440static inline unsigned long bts_get(const char *base, enum bts_field field) 458static inline unsigned long bts_get(const char *base, enum bts_field field)
@@ -461,8 +479,8 @@ static inline void bts_set(char *base, enum bts_field field, unsigned long val)
461 * 479 *
462 * return: bytes read/written on success; -Eerrno, otherwise 480 * return: bytes read/written on success; -Eerrno, otherwise
463 */ 481 */
464static int bts_read(struct bts_tracer *tracer, const void *at, 482static int
465 struct bts_struct *out) 483bts_read(struct bts_tracer *tracer, const void *at, struct bts_struct *out)
466{ 484{
467 if (!tracer) 485 if (!tracer)
468 return -EINVAL; 486 return -EINVAL;
diff --git a/arch/x86/kernel/ds_selftest.h b/arch/x86/kernel/ds_selftest.h
index 0e6e19d4c7d..2ba8745c666 100644
--- a/arch/x86/kernel/ds_selftest.h
+++ b/arch/x86/kernel/ds_selftest.h
@@ -12,4 +12,4 @@ extern int ds_selftest_pebs(void);
12#else 12#else
13static inline int ds_selftest_bts(void) { return 0; } 13static inline int ds_selftest_bts(void) { return 0; }
14static inline int ds_selftest_pebs(void) { return 0; } 14static inline int ds_selftest_pebs(void) { return 0; }
15#endif /* CONFIG_X86_DS_SELFTEST */ 15#endif
diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c
index 4ca82700c04..8b2109a6c61 100644
--- a/kernel/trace/trace_hw_branches.c
+++ b/kernel/trace/trace_hw_branches.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * h/w branch tracer for x86 based on bts 2 * h/w branch tracer for x86 based on BTS
3 * 3 *
4 * Copyright (C) 2008-2009 Intel Corporation. 4 * Copyright (C) 2008-2009 Intel Corporation.
5 * Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009 5 * Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009
@@ -15,8 +15,8 @@
15 15
16#include <asm/ds.h> 16#include <asm/ds.h>
17 17
18#include "trace.h"
19#include "trace_output.h" 18#include "trace_output.h"
19#include "trace.h"
20 20
21 21
22#define BTS_BUFFER_SIZE (1 << 13) 22#define BTS_BUFFER_SIZE (1 << 13)
@@ -197,10 +197,10 @@ static void bts_trace_print_header(struct seq_file *m)
197 197
198static enum print_line_t bts_trace_print_line(struct trace_iterator *iter) 198static enum print_line_t bts_trace_print_line(struct trace_iterator *iter)
199{ 199{
200 unsigned long symflags = TRACE_ITER_SYM_OFFSET;
200 struct trace_entry *entry = iter->ent; 201 struct trace_entry *entry = iter->ent;
201 struct trace_seq *seq = &iter->seq; 202 struct trace_seq *seq = &iter->seq;
202 struct hw_branch_entry *it; 203 struct hw_branch_entry *it;
203 unsigned long symflags = TRACE_ITER_SYM_OFFSET;
204 204
205 trace_assign_type(it, entry); 205 trace_assign_type(it, entry);
206 206
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 3c7b797d0d2..b9109126706 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -189,6 +189,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace,
189#else 189#else
190# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; }) 190# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
191#endif /* CONFIG_DYNAMIC_FTRACE */ 191#endif /* CONFIG_DYNAMIC_FTRACE */
192
192/* 193/*
193 * Simple verification test of ftrace function tracer. 194 * Simple verification test of ftrace function tracer.
194 * Enable ftrace, sleep 1/10 second, and then read the trace 195 * Enable ftrace, sleep 1/10 second, and then read the trace
@@ -698,10 +699,10 @@ int
698trace_selftest_startup_hw_branches(struct tracer *trace, 699trace_selftest_startup_hw_branches(struct tracer *trace,
699 struct trace_array *tr) 700 struct trace_array *tr)
700{ 701{
701 unsigned long count;
702 int ret;
703 struct trace_iterator iter; 702 struct trace_iterator iter;
704 struct tracer tracer; 703 struct tracer tracer;
704 unsigned long count;
705 int ret;
705 706
706 if (!trace->open) { 707 if (!trace->open) {
707 printk(KERN_CONT "missing open function..."); 708 printk(KERN_CONT "missing open function...");