blob: d9cab7168058bdd88a4a59619ed2651cfc0b000a [file] [log] [blame]
Markus Metzgereee3af42008-01-30 13:31:09 +01001/*
2 * Debug Store support
3 *
4 * This provides a low-level interface to the hardware's Debug Store
Markus Metzger93fa7632008-04-08 11:01:58 +02005 * feature that is used for branch trace store (BTS) and
Markus Metzgereee3af42008-01-30 13:31:09 +01006 * precise-event based sampling (PEBS).
7 *
Markus Metzger93fa7632008-04-08 11:01:58 +02008 * It manages:
Markus Metzgerc2724772008-12-11 13:49:59 +01009 * - DS and BTS hardware configuration
Markus Metzger6abb11a2008-11-25 09:05:27 +010010 * - buffer overflow handling (to be done)
Markus Metzger93fa7632008-04-08 11:01:58 +020011 * - buffer access
12 *
Markus Metzgerc2724772008-12-11 13:49:59 +010013 * It does not do:
14 * - security checking (is the caller allowed to trace the task)
15 * - buffer allocation (memory accounting)
Markus Metzgereee3af42008-01-30 13:31:09 +010016 *
17 *
Markus Metzgerba2607f2009-01-19 10:38:35 +010018 * Copyright (C) 2007-2009 Intel Corporation.
19 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
Markus Metzgereee3af42008-01-30 13:31:09 +010020 */
21
Markus Metzger93fa7632008-04-08 11:01:58 +020022
Markus Metzgereee3af42008-01-30 13:31:09 +010023#include <asm/ds.h>
24
25#include <linux/errno.h>
26#include <linux/string.h>
27#include <linux/slab.h>
Markus Metzger93fa7632008-04-08 11:01:58 +020028#include <linux/sched.h>
Ingo Molnar3c9339042008-07-25 11:32:36 +020029#include <linux/mm.h>
Markus Metzgerca0002a2008-11-25 09:01:25 +010030#include <linux/kernel.h>
Markus Metzger93fa7632008-04-08 11:01:58 +020031
Markus Metzger8a327f62009-03-13 10:45:07 +010032#include "ds_selftest.h"
Markus Metzger93fa7632008-04-08 11:01:58 +020033
34/*
35 * The configuration for a particular DS hardware implementation.
36 */
37struct ds_configuration {
Markus Metzgerb8e47192009-03-13 10:46:42 +010038 /* The name of the configuration. */
Markus Metzgerc2724772008-12-11 13:49:59 +010039 const char *name;
Markus Metzgerb8e47192009-03-13 10:46:42 +010040 /* The size of pointer-typed fields in DS, BTS, and PEBS. */
Markus Metzgerbc44fb52009-03-13 10:42:18 +010041 unsigned char sizeof_ptr_field;
Markus Metzgerb8e47192009-03-13 10:46:42 +010042 /* The size of a BTS/PEBS record in bytes. */
Markus Metzger93fa7632008-04-08 11:01:58 +020043 unsigned char sizeof_rec[2];
Markus Metzgerb8e47192009-03-13 10:46:42 +010044 /* Control bit-masks indexed by enum ds_feature. */
Markus Metzgerc2724772008-12-11 13:49:59 +010045 unsigned long ctl[dsf_ctl_max];
Markus Metzger93fa7632008-04-08 11:01:58 +020046};
Markus Metzgerc2724772008-12-11 13:49:59 +010047static DEFINE_PER_CPU(struct ds_configuration, ds_cfg_array);
48
49#define ds_cfg per_cpu(ds_cfg_array, smp_processor_id())
50
Markus Metzgerb8e47192009-03-13 10:46:42 +010051#define MAX_SIZEOF_DS (12 * 8) /* Maximal size of a DS configuration. */
52#define MAX_SIZEOF_BTS (3 * 8) /* Maximal size of a BTS record. */
53#define DS_ALIGNMENT (1 << 3) /* BTS and PEBS buffer alignment. */
Markus Metzgerc2724772008-12-11 13:49:59 +010054
55#define BTS_CONTROL \
56 (ds_cfg.ctl[dsf_bts] | ds_cfg.ctl[dsf_bts_kernel] | ds_cfg.ctl[dsf_bts_user] |\
57 ds_cfg.ctl[dsf_bts_overflow])
58
Markus Metzgereee3af42008-01-30 13:31:09 +010059
Markus Metzgerca0002a2008-11-25 09:01:25 +010060/*
61 * A BTS or PEBS tracer.
62 *
63 * This holds the configuration of the tracer and serves as a handle
64 * to identify tracers.
65 */
66struct ds_tracer {
Markus Metzgerb8e47192009-03-13 10:46:42 +010067 /* The DS context (partially) owned by this tracer. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010068 struct ds_context *context;
Markus Metzgerb8e47192009-03-13 10:46:42 +010069 /* The buffer provided on ds_request() and its size in bytes. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010070 void *buffer;
71 size_t size;
Markus Metzgerca0002a2008-11-25 09:01:25 +010072};
73
74struct bts_tracer {
Markus Metzgerb8e47192009-03-13 10:46:42 +010075 /* The common DS part. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010076 struct ds_tracer ds;
Markus Metzgerb8e47192009-03-13 10:46:42 +010077 /* The trace including the DS configuration. */
Markus Metzgerc2724772008-12-11 13:49:59 +010078 struct bts_trace trace;
Markus Metzgerb8e47192009-03-13 10:46:42 +010079 /* Buffer overflow notification function. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010080 bts_ovfl_callback_t ovfl;
81};
82
83struct pebs_tracer {
Markus Metzgerb8e47192009-03-13 10:46:42 +010084 /* The common DS part. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010085 struct ds_tracer ds;
Markus Metzgerb8e47192009-03-13 10:46:42 +010086 /* The trace including the DS configuration. */
Markus Metzgerc2724772008-12-11 13:49:59 +010087 struct pebs_trace trace;
Markus Metzgerb8e47192009-03-13 10:46:42 +010088 /* Buffer overflow notification function. */
Markus Metzgerca0002a2008-11-25 09:01:25 +010089 pebs_ovfl_callback_t ovfl;
90};
Markus Metzgereee3af42008-01-30 13:31:09 +010091
92/*
93 * Debug Store (DS) save area configuration (see Intel64 and IA32
94 * Architectures Software Developer's Manual, section 18.5)
95 *
96 * The DS configuration consists of the following fields; different
97 * architetures vary in the size of those fields.
98 * - double-word aligned base linear address of the BTS buffer
99 * - write pointer into the BTS buffer
100 * - end linear address of the BTS buffer (one byte beyond the end of
101 * the buffer)
102 * - interrupt pointer into BTS buffer
103 * (interrupt occurs when write pointer passes interrupt pointer)
104 * - double-word aligned base linear address of the PEBS buffer
105 * - write pointer into the PEBS buffer
106 * - end linear address of the PEBS buffer (one byte beyond the end of
107 * the buffer)
108 * - interrupt pointer into PEBS buffer
109 * (interrupt occurs when write pointer passes interrupt pointer)
110 * - value to which counter is reset following counter overflow
111 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200112 * Later architectures use 64bit pointers throughout, whereas earlier
113 * architectures use 32bit pointers in 32bit mode.
Markus Metzgereee3af42008-01-30 13:31:09 +0100114 *
115 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200116 * We compute the base address for the first 8 fields based on:
117 * - the field size stored in the DS configuration
118 * - the relative field position
119 * - an offset giving the start of the respective region
Markus Metzgereee3af42008-01-30 13:31:09 +0100120 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200121 * This offset is further used to index various arrays holding
122 * information for BTS and PEBS at the respective index.
Markus Metzgereee3af42008-01-30 13:31:09 +0100123 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200124 * On later 32bit processors, we only access the lower 32bit of the
125 * 64bit pointer fields. The upper halves will be zeroed out.
Markus Metzgereee3af42008-01-30 13:31:09 +0100126 */
127
Markus Metzger93fa7632008-04-08 11:01:58 +0200128enum ds_field {
129 ds_buffer_base = 0,
130 ds_index,
131 ds_absolute_maximum,
132 ds_interrupt_threshold,
Markus Metzgereee3af42008-01-30 13:31:09 +0100133};
134
Markus Metzger93fa7632008-04-08 11:01:58 +0200135enum ds_qualifier {
136 ds_bts = 0,
137 ds_pebs
Markus Metzgereee3af42008-01-30 13:31:09 +0100138};
139
Markus Metzger93fa7632008-04-08 11:01:58 +0200140static inline unsigned long ds_get(const unsigned char *base,
141 enum ds_qualifier qual, enum ds_field field)
142{
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100143 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
Markus Metzger93fa7632008-04-08 11:01:58 +0200144 return *(unsigned long *)base;
145}
146
147static inline void ds_set(unsigned char *base, enum ds_qualifier qual,
148 enum ds_field field, unsigned long value)
149{
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100150 base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual)));
Markus Metzger93fa7632008-04-08 11:01:58 +0200151 (*(unsigned long *)base) = value;
152}
153
Markus Metzgereee3af42008-01-30 13:31:09 +0100154
155/*
Markus Metzger6abb11a2008-11-25 09:05:27 +0100156 * Locking is done only for allocating BTS or PEBS resources.
Markus Metzgereee3af42008-01-30 13:31:09 +0100157 */
Markus Metzgerc2724772008-12-11 13:49:59 +0100158static DEFINE_SPINLOCK(ds_lock);
Markus Metzgereee3af42008-01-30 13:31:09 +0100159
Markus Metzger93fa7632008-04-08 11:01:58 +0200160
161/*
162 * We either support (system-wide) per-cpu or per-thread allocation.
163 * We distinguish the two based on the task_struct pointer, where a
164 * NULL pointer indicates per-cpu allocation for the current cpu.
165 *
166 * Allocations are use-counted. As soon as resources are allocated,
167 * further allocations must be of the same type (per-cpu or
168 * per-thread). We model this by counting allocations (i.e. the number
169 * of tracers of a certain type) for one type negatively:
170 * =0 no tracers
171 * >0 number of per-thread tracers
172 * <0 number of per-cpu tracers
173 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200174 * Tracers essentially gives the number of ds contexts for a certain
175 * type of allocation.
176 */
Markus Metzgerc2724772008-12-11 13:49:59 +0100177static atomic_t tracers = ATOMIC_INIT(0);
Markus Metzger93fa7632008-04-08 11:01:58 +0200178
179static inline void get_tracer(struct task_struct *task)
Markus Metzgera95d67f2008-01-30 13:31:20 +0100180{
Markus Metzgerc2724772008-12-11 13:49:59 +0100181 if (task)
182 atomic_inc(&tracers);
183 else
184 atomic_dec(&tracers);
Markus Metzgereee3af42008-01-30 13:31:09 +0100185}
186
Markus Metzger93fa7632008-04-08 11:01:58 +0200187static inline void put_tracer(struct task_struct *task)
Markus Metzgereee3af42008-01-30 13:31:09 +0100188{
Markus Metzgerc2724772008-12-11 13:49:59 +0100189 if (task)
190 atomic_dec(&tracers);
191 else
192 atomic_inc(&tracers);
Markus Metzgereee3af42008-01-30 13:31:09 +0100193}
194
Markus Metzger93fa7632008-04-08 11:01:58 +0200195static inline int check_tracer(struct task_struct *task)
Markus Metzgera95d67f2008-01-30 13:31:20 +0100196{
Markus Metzgerc2724772008-12-11 13:49:59 +0100197 return task ?
198 (atomic_read(&tracers) >= 0) :
199 (atomic_read(&tracers) <= 0);
Markus Metzger93fa7632008-04-08 11:01:58 +0200200}
201
202
203/*
204 * The DS context is either attached to a thread or to a cpu:
205 * - in the former case, the thread_struct contains a pointer to the
206 * attached context.
207 * - in the latter case, we use a static array of per-cpu context
208 * pointers.
209 *
210 * Contexts are use-counted. They are allocated on first access and
211 * deallocated when the last user puts the context.
Markus Metzger93fa7632008-04-08 11:01:58 +0200212 */
Markus Metzgerc2724772008-12-11 13:49:59 +0100213struct ds_context {
Markus Metzgerb8e47192009-03-13 10:46:42 +0100214 /* The DS configuration; goes into MSR_IA32_DS_AREA. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100215 unsigned char ds[MAX_SIZEOF_DS];
Markus Metzgerb8e47192009-03-13 10:46:42 +0100216 /* The owner of the BTS and PEBS configuration, respectively. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100217 struct bts_tracer *bts_master;
218 struct pebs_tracer *pebs_master;
Markus Metzgerb8e47192009-03-13 10:46:42 +0100219 /* Use count. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100220 unsigned long count;
Markus Metzgerb8e47192009-03-13 10:46:42 +0100221 /* Pointer to the context pointer field. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100222 struct ds_context **this;
Markus Metzgerb8e47192009-03-13 10:46:42 +0100223 /* The traced task; NULL for current cpu. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100224 struct task_struct *task;
225};
Markus Metzger93fa7632008-04-08 11:01:58 +0200226
Markus Metzgerc2724772008-12-11 13:49:59 +0100227static DEFINE_PER_CPU(struct ds_context *, system_context_array);
228
229#define system_context per_cpu(system_context_array, smp_processor_id())
Markus Metzger93fa7632008-04-08 11:01:58 +0200230
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100231
232static inline struct ds_context *ds_get_context(struct task_struct *task)
Markus Metzger93fa7632008-04-08 11:01:58 +0200233{
Markus Metzger93fa7632008-04-08 11:01:58 +0200234 struct ds_context **p_context =
Markus Metzgerc2724772008-12-11 13:49:59 +0100235 (task ? &task->thread.ds_ctx : &system_context);
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100236 struct ds_context *context = NULL;
237 struct ds_context *new_context = NULL;
Markus Metzgerde90add2008-11-25 08:52:56 +0100238 unsigned long irq;
Markus Metzger93fa7632008-04-08 11:01:58 +0200239
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100240 /* Chances are small that we already have a context. */
241 new_context = kzalloc(sizeof(*new_context), GFP_KERNEL);
242 if (!new_context)
243 return NULL;
244
245 spin_lock_irqsave(&ds_lock, irq);
246
247 context = *p_context;
Markus Metzger93fa7632008-04-08 11:01:58 +0200248 if (!context) {
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100249 context = new_context;
Markus Metzger93fa7632008-04-08 11:01:58 +0200250
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100251 context->this = p_context;
252 context->task = task;
253 context->count = 0;
Markus Metzgerde90add2008-11-25 08:52:56 +0100254
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100255 if (task)
256 set_tsk_thread_flag(task, TIF_DS_AREA_MSR);
Markus Metzgerde90add2008-11-25 08:52:56 +0100257
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100258 if (!task || (task == current))
259 wrmsrl(MSR_IA32_DS_AREA, (unsigned long)context->ds);
Markus Metzgerde90add2008-11-25 08:52:56 +0100260
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100261 *p_context = context;
Markus Metzgerc2724772008-12-11 13:49:59 +0100262 }
Markus Metzger93fa7632008-04-08 11:01:58 +0200263
Markus Metzgercc1dc6d2008-12-16 15:51:03 +0100264 context->count++;
265
266 spin_unlock_irqrestore(&ds_lock, irq);
267
268 if (context != new_context)
269 kfree(new_context);
270
Markus Metzger93fa7632008-04-08 11:01:58 +0200271 return context;
272}
273
Markus Metzger93fa7632008-04-08 11:01:58 +0200274static inline void ds_put_context(struct ds_context *context)
275{
Markus Metzgerde90add2008-11-25 08:52:56 +0100276 unsigned long irq;
277
Markus Metzger93fa7632008-04-08 11:01:58 +0200278 if (!context)
279 return;
280
Markus Metzgerde90add2008-11-25 08:52:56 +0100281 spin_lock_irqsave(&ds_lock, irq);
Markus Metzger93fa7632008-04-08 11:01:58 +0200282
Markus Metzgerc2724772008-12-11 13:49:59 +0100283 if (--context->count) {
284 spin_unlock_irqrestore(&ds_lock, irq);
285 return;
286 }
Markus Metzger93fa7632008-04-08 11:01:58 +0200287
Cyrill Gorcunov573da422008-04-28 23:15:04 +0400288 *(context->this) = NULL;
Markus Metzger93fa7632008-04-08 11:01:58 +0200289
290 if (context->task)
291 clear_tsk_thread_flag(context->task, TIF_DS_AREA_MSR);
292
293 if (!context->task || (context->task == current))
294 wrmsrl(MSR_IA32_DS_AREA, 0);
295
Markus Metzgerde90add2008-11-25 08:52:56 +0100296 spin_unlock_irqrestore(&ds_lock, irq);
Markus Metzgerc2724772008-12-11 13:49:59 +0100297
298 kfree(context);
Markus Metzger93fa7632008-04-08 11:01:58 +0200299}
300
301
302/*
Markus Metzgerc2724772008-12-11 13:49:59 +0100303 * Call the tracer's callback on a buffer overflow.
Markus Metzger93fa7632008-04-08 11:01:58 +0200304 *
Markus Metzger93fa7632008-04-08 11:01:58 +0200305 * context: the ds context
306 * qual: the buffer type
307 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100308static void ds_overflow(struct ds_context *context, enum ds_qualifier qual)
Markus Metzger93fa7632008-04-08 11:01:58 +0200309{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100310 switch (qual) {
Markus Metzgerc2724772008-12-11 13:49:59 +0100311 case ds_bts:
312 if (context->bts_master &&
313 context->bts_master->ovfl)
314 context->bts_master->ovfl(context->bts_master);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100315 break;
Markus Metzgerc2724772008-12-11 13:49:59 +0100316 case ds_pebs:
317 if (context->pebs_master &&
318 context->pebs_master->ovfl)
319 context->pebs_master->ovfl(context->pebs_master);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100320 break;
321 }
Markus Metzger93fa7632008-04-08 11:01:58 +0200322}
323
324
Markus Metzgerc2724772008-12-11 13:49:59 +0100325/*
326 * Write raw data into the BTS or PEBS buffer.
327 *
328 * The remainder of any partially written record is zeroed out.
329 *
330 * context: the DS context
331 * qual: the buffer type
332 * record: the data to write
333 * size: the size of the data
334 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100335static int ds_write(struct ds_context *context, enum ds_qualifier qual,
336 const void *record, size_t size)
Markus Metzger93fa7632008-04-08 11:01:58 +0200337{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100338 int bytes_written = 0;
Markus Metzger93fa7632008-04-08 11:01:58 +0200339
340 if (!record)
341 return -EINVAL;
342
Markus Metzger93fa7632008-04-08 11:01:58 +0200343 while (size) {
344 unsigned long base, index, end, write_end, int_th;
345 unsigned long write_size, adj_write_size;
Markus Metzgereee3af42008-01-30 13:31:09 +0100346
Markus Metzger93fa7632008-04-08 11:01:58 +0200347 /*
Markus Metzgerb8e47192009-03-13 10:46:42 +0100348 * Write as much as possible without producing an
Markus Metzger93fa7632008-04-08 11:01:58 +0200349 * overflow interrupt.
350 *
Markus Metzgerb8e47192009-03-13 10:46:42 +0100351 * Interrupt_threshold must either be
Markus Metzger93fa7632008-04-08 11:01:58 +0200352 * - bigger than absolute_maximum or
353 * - point to a record between buffer_base and absolute_maximum
354 *
Markus Metzgerb8e47192009-03-13 10:46:42 +0100355 * Index points to a valid record.
Markus Metzger93fa7632008-04-08 11:01:58 +0200356 */
357 base = ds_get(context->ds, qual, ds_buffer_base);
358 index = ds_get(context->ds, qual, ds_index);
359 end = ds_get(context->ds, qual, ds_absolute_maximum);
360 int_th = ds_get(context->ds, qual, ds_interrupt_threshold);
361
362 write_end = min(end, int_th);
363
Markus Metzgerb8e47192009-03-13 10:46:42 +0100364 /*
365 * If we are already beyond the interrupt threshold,
366 * we fill the entire buffer.
367 */
Markus Metzger93fa7632008-04-08 11:01:58 +0200368 if (write_end <= index)
369 write_end = end;
370
371 if (write_end <= index)
Markus Metzgerca0002a2008-11-25 09:01:25 +0100372 break;
Markus Metzger93fa7632008-04-08 11:01:58 +0200373
374 write_size = min((unsigned long) size, write_end - index);
375 memcpy((void *)index, record, write_size);
376
377 record = (const char *)record + write_size;
Markus Metzgerca0002a2008-11-25 09:01:25 +0100378 size -= write_size;
379 bytes_written += write_size;
Markus Metzger93fa7632008-04-08 11:01:58 +0200380
381 adj_write_size = write_size / ds_cfg.sizeof_rec[qual];
382 adj_write_size *= ds_cfg.sizeof_rec[qual];
383
Markus Metzgerb8e47192009-03-13 10:46:42 +0100384 /* Zero out trailing bytes. */
Markus Metzger93fa7632008-04-08 11:01:58 +0200385 memset((char *)index + write_size, 0,
386 adj_write_size - write_size);
387 index += adj_write_size;
388
389 if (index >= end)
390 index = base;
391 ds_set(context->ds, qual, ds_index, index);
392
393 if (index >= int_th)
Markus Metzgerca0002a2008-11-25 09:01:25 +0100394 ds_overflow(context, qual);
Markus Metzger93fa7632008-04-08 11:01:58 +0200395 }
396
Markus Metzgerca0002a2008-11-25 09:01:25 +0100397 return bytes_written;
Markus Metzgereee3af42008-01-30 13:31:09 +0100398}
399
Markus Metzgerc2724772008-12-11 13:49:59 +0100400
401/*
402 * Branch Trace Store (BTS) uses the following format. Different
403 * architectures vary in the size of those fields.
404 * - source linear address
405 * - destination linear address
406 * - flags
407 *
408 * Later architectures use 64bit pointers throughout, whereas earlier
409 * architectures use 32bit pointers in 32bit mode.
410 *
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100411 * We compute the base address for the fields based on:
Markus Metzgerc2724772008-12-11 13:49:59 +0100412 * - the field size stored in the DS configuration
413 * - the relative field position
414 *
415 * In order to store additional information in the BTS buffer, we use
416 * a special source address to indicate that the record requires
417 * special interpretation.
418 *
419 * Netburst indicated via a bit in the flags field whether the branch
420 * was predicted; this is ignored.
421 *
422 * We use two levels of abstraction:
423 * - the raw data level defined here
424 * - an arch-independent level defined in ds.h
425 */
426
427enum bts_field {
428 bts_from,
429 bts_to,
430 bts_flags,
431
432 bts_qual = bts_from,
433 bts_jiffies = bts_to,
434 bts_pid = bts_flags,
435
436 bts_qual_mask = (bts_qual_max - 1),
437 bts_escape = ((unsigned long)-1 & ~bts_qual_mask)
438};
439
440static inline unsigned long bts_get(const char *base, enum bts_field field)
441{
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100442 base += (ds_cfg.sizeof_ptr_field * field);
Markus Metzgerc2724772008-12-11 13:49:59 +0100443 return *(unsigned long *)base;
444}
445
446static inline void bts_set(char *base, enum bts_field field, unsigned long val)
447{
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100448 base += (ds_cfg.sizeof_ptr_field * field);;
Markus Metzgerc2724772008-12-11 13:49:59 +0100449 (*(unsigned long *)base) = val;
450}
451
452
453/*
454 * The raw BTS data is architecture dependent.
455 *
456 * For higher-level users, we give an arch-independent view.
457 * - ds.h defines struct bts_struct
458 * - bts_read translates one raw bts record into a bts_struct
459 * - bts_write translates one bts_struct into the raw format and
460 * writes it into the top of the parameter tracer's buffer.
461 *
462 * return: bytes read/written on success; -Eerrno, otherwise
463 */
464static int bts_read(struct bts_tracer *tracer, const void *at,
465 struct bts_struct *out)
Markus Metzgereee3af42008-01-30 13:31:09 +0100466{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100467 if (!tracer)
468 return -EINVAL;
469
Markus Metzgerc2724772008-12-11 13:49:59 +0100470 if (at < tracer->trace.ds.begin)
471 return -EINVAL;
472
473 if (tracer->trace.ds.end < (at + tracer->trace.ds.size))
474 return -EINVAL;
475
476 memset(out, 0, sizeof(*out));
477 if ((bts_get(at, bts_qual) & ~bts_qual_mask) == bts_escape) {
478 out->qualifier = (bts_get(at, bts_qual) & bts_qual_mask);
479 out->variant.timestamp.jiffies = bts_get(at, bts_jiffies);
480 out->variant.timestamp.pid = bts_get(at, bts_pid);
481 } else {
482 out->qualifier = bts_branch;
483 out->variant.lbr.from = bts_get(at, bts_from);
484 out->variant.lbr.to = bts_get(at, bts_to);
Markus Metzgerd072c252008-12-16 15:53:11 +0100485
486 if (!out->variant.lbr.from && !out->variant.lbr.to)
487 out->qualifier = bts_invalid;
Markus Metzgerc2724772008-12-11 13:49:59 +0100488 }
489
490 return ds_cfg.sizeof_rec[ds_bts];
Markus Metzgereee3af42008-01-30 13:31:09 +0100491}
492
Markus Metzgerc2724772008-12-11 13:49:59 +0100493static int bts_write(struct bts_tracer *tracer, const struct bts_struct *in)
Markus Metzger93fa7632008-04-08 11:01:58 +0200494{
Markus Metzgerc2724772008-12-11 13:49:59 +0100495 unsigned char raw[MAX_SIZEOF_BTS];
496
Markus Metzgerca0002a2008-11-25 09:01:25 +0100497 if (!tracer)
498 return -EINVAL;
499
Markus Metzgerc2724772008-12-11 13:49:59 +0100500 if (MAX_SIZEOF_BTS < ds_cfg.sizeof_rec[ds_bts])
501 return -EOVERFLOW;
502
503 switch (in->qualifier) {
504 case bts_invalid:
505 bts_set(raw, bts_from, 0);
506 bts_set(raw, bts_to, 0);
507 bts_set(raw, bts_flags, 0);
508 break;
509 case bts_branch:
510 bts_set(raw, bts_from, in->variant.lbr.from);
511 bts_set(raw, bts_to, in->variant.lbr.to);
512 bts_set(raw, bts_flags, 0);
513 break;
514 case bts_task_arrives:
515 case bts_task_departs:
516 bts_set(raw, bts_qual, (bts_escape | in->qualifier));
517 bts_set(raw, bts_jiffies, in->variant.timestamp.jiffies);
518 bts_set(raw, bts_pid, in->variant.timestamp.pid);
519 break;
520 default:
521 return -EINVAL;
522 }
523
524 return ds_write(tracer->ds.context, ds_bts, raw,
525 ds_cfg.sizeof_rec[ds_bts]);
Markus Metzger93fa7632008-04-08 11:01:58 +0200526}
Markus Metzgereee3af42008-01-30 13:31:09 +0100527
Markus Metzgerc2724772008-12-11 13:49:59 +0100528
529static void ds_write_config(struct ds_context *context,
530 struct ds_trace *cfg, enum ds_qualifier qual)
Markus Metzger93fa7632008-04-08 11:01:58 +0200531{
Markus Metzgerc2724772008-12-11 13:49:59 +0100532 unsigned char *ds = context->ds;
Markus Metzger93fa7632008-04-08 11:01:58 +0200533
Markus Metzgerc2724772008-12-11 13:49:59 +0100534 ds_set(ds, qual, ds_buffer_base, (unsigned long)cfg->begin);
535 ds_set(ds, qual, ds_index, (unsigned long)cfg->top);
536 ds_set(ds, qual, ds_absolute_maximum, (unsigned long)cfg->end);
537 ds_set(ds, qual, ds_interrupt_threshold, (unsigned long)cfg->ith);
538}
Markus Metzger93fa7632008-04-08 11:01:58 +0200539
Markus Metzgerc2724772008-12-11 13:49:59 +0100540static void ds_read_config(struct ds_context *context,
541 struct ds_trace *cfg, enum ds_qualifier qual)
542{
543 unsigned char *ds = context->ds;
Markus Metzger93fa7632008-04-08 11:01:58 +0200544
Markus Metzgerc2724772008-12-11 13:49:59 +0100545 cfg->begin = (void *)ds_get(ds, qual, ds_buffer_base);
546 cfg->top = (void *)ds_get(ds, qual, ds_index);
547 cfg->end = (void *)ds_get(ds, qual, ds_absolute_maximum);
548 cfg->ith = (void *)ds_get(ds, qual, ds_interrupt_threshold);
549}
550
551static void ds_init_ds_trace(struct ds_trace *trace, enum ds_qualifier qual,
552 void *base, size_t size, size_t ith,
553 unsigned int flags) {
554 unsigned long buffer, adj;
555
Markus Metzgerb8e47192009-03-13 10:46:42 +0100556 /*
557 * Adjust the buffer address and size to meet alignment
Markus Metzgerc2724772008-12-11 13:49:59 +0100558 * constraints:
559 * - buffer is double-word aligned
560 * - size is multiple of record size
561 *
562 * We checked the size at the very beginning; we have enough
563 * space to do the adjustment.
564 */
565 buffer = (unsigned long)base;
566
567 adj = ALIGN(buffer, DS_ALIGNMENT) - buffer;
568 buffer += adj;
569 size -= adj;
570
571 trace->n = size / ds_cfg.sizeof_rec[qual];
572 trace->size = ds_cfg.sizeof_rec[qual];
573
574 size = (trace->n * trace->size);
575
576 trace->begin = (void *)buffer;
577 trace->top = trace->begin;
578 trace->end = (void *)(buffer + size);
Markus Metzgerb8e47192009-03-13 10:46:42 +0100579 /*
580 * The value for 'no threshold' is -1, which will set the
Markus Metzgerc2724772008-12-11 13:49:59 +0100581 * threshold outside of the buffer, just like we want it.
582 */
583 trace->ith = (void *)(buffer + size - ith);
584
585 trace->flags = flags;
586}
587
588
589static int ds_request(struct ds_tracer *tracer, struct ds_trace *trace,
590 enum ds_qualifier qual, struct task_struct *task,
591 void *base, size_t size, size_t th, unsigned int flags)
592{
593 struct ds_context *context;
594 int error;
595
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100596 error = -EOPNOTSUPP;
597 if (!ds_cfg.sizeof_rec[qual])
598 goto out;
599
Markus Metzgerc2724772008-12-11 13:49:59 +0100600 error = -EINVAL;
601 if (!base)
602 goto out;
603
Markus Metzgerb8e47192009-03-13 10:46:42 +0100604 /* We require some space to do alignment adjustments below. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100605 error = -EINVAL;
606 if (size < (DS_ALIGNMENT + ds_cfg.sizeof_rec[qual]))
607 goto out;
608
609 if (th != (size_t)-1) {
610 th *= ds_cfg.sizeof_rec[qual];
611
612 error = -EINVAL;
613 if (size <= th)
614 goto out;
615 }
616
617 tracer->buffer = base;
618 tracer->size = size;
619
620 error = -ENOMEM;
621 context = ds_get_context(task);
622 if (!context)
623 goto out;
624 tracer->context = context;
625
626 ds_init_ds_trace(trace, qual, base, size, th, flags);
627
628 error = 0;
629 out:
630 return error;
631}
632
633struct bts_tracer *ds_request_bts(struct task_struct *task,
634 void *base, size_t size,
635 bts_ovfl_callback_t ovfl, size_t th,
636 unsigned int flags)
637{
638 struct bts_tracer *tracer;
639 unsigned long irq;
640 int error;
641
Markus Metzgerb8e47192009-03-13 10:46:42 +0100642 /* Buffer overflow notification is not yet implemented. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100643 error = -EOPNOTSUPP;
644 if (ovfl)
645 goto out;
646
647 error = -ENOMEM;
648 tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
649 if (!tracer)
650 goto out;
651 tracer->ovfl = ovfl;
652
653 error = ds_request(&tracer->ds, &tracer->trace.ds,
654 ds_bts, task, base, size, th, flags);
655 if (error < 0)
656 goto out_tracer;
657
658
659 spin_lock_irqsave(&ds_lock, irq);
660
661 error = -EPERM;
662 if (!check_tracer(task))
663 goto out_unlock;
664 get_tracer(task);
665
666 error = -EPERM;
667 if (tracer->ds.context->bts_master)
668 goto out_put_tracer;
669 tracer->ds.context->bts_master = tracer;
670
671 spin_unlock_irqrestore(&ds_lock, irq);
672
673
674 tracer->trace.read = bts_read;
675 tracer->trace.write = bts_write;
676
677 ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
678 ds_resume_bts(tracer);
679
680 return tracer;
681
682 out_put_tracer:
683 put_tracer(task);
684 out_unlock:
685 spin_unlock_irqrestore(&ds_lock, irq);
686 ds_put_context(tracer->ds.context);
687 out_tracer:
688 kfree(tracer);
689 out:
690 return ERR_PTR(error);
691}
692
693struct pebs_tracer *ds_request_pebs(struct task_struct *task,
694 void *base, size_t size,
695 pebs_ovfl_callback_t ovfl, size_t th,
696 unsigned int flags)
697{
698 struct pebs_tracer *tracer;
699 unsigned long irq;
700 int error;
701
Markus Metzgerb8e47192009-03-13 10:46:42 +0100702 /* Buffer overflow notification is not yet implemented. */
Markus Metzgerc2724772008-12-11 13:49:59 +0100703 error = -EOPNOTSUPP;
704 if (ovfl)
705 goto out;
706
707 error = -ENOMEM;
708 tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
709 if (!tracer)
710 goto out;
711 tracer->ovfl = ovfl;
712
713 error = ds_request(&tracer->ds, &tracer->trace.ds,
714 ds_pebs, task, base, size, th, flags);
715 if (error < 0)
716 goto out_tracer;
717
718 spin_lock_irqsave(&ds_lock, irq);
719
720 error = -EPERM;
721 if (!check_tracer(task))
722 goto out_unlock;
723 get_tracer(task);
724
725 error = -EPERM;
726 if (tracer->ds.context->pebs_master)
727 goto out_put_tracer;
728 tracer->ds.context->pebs_master = tracer;
729
730 spin_unlock_irqrestore(&ds_lock, irq);
731
Markus Metzger73bf1b62009-03-05 08:57:21 +0100732 ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
Markus Metzgerc2724772008-12-11 13:49:59 +0100733 ds_resume_pebs(tracer);
734
735 return tracer;
736
737 out_put_tracer:
738 put_tracer(task);
739 out_unlock:
740 spin_unlock_irqrestore(&ds_lock, irq);
741 ds_put_context(tracer->ds.context);
742 out_tracer:
743 kfree(tracer);
744 out:
745 return ERR_PTR(error);
746}
747
748void ds_release_bts(struct bts_tracer *tracer)
749{
750 if (!tracer)
751 return;
752
753 ds_suspend_bts(tracer);
754
755 WARN_ON_ONCE(tracer->ds.context->bts_master != tracer);
756 tracer->ds.context->bts_master = NULL;
757
758 put_tracer(tracer->ds.context->task);
759 ds_put_context(tracer->ds.context);
760
761 kfree(tracer);
762}
763
764void ds_suspend_bts(struct bts_tracer *tracer)
765{
766 struct task_struct *task;
767
768 if (!tracer)
769 return;
770
771 task = tracer->ds.context->task;
772
773 if (!task || (task == current))
774 update_debugctlmsr(get_debugctlmsr() & ~BTS_CONTROL);
775
776 if (task) {
777 task->thread.debugctlmsr &= ~BTS_CONTROL;
778
779 if (!task->thread.debugctlmsr)
780 clear_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
781 }
782}
783
784void ds_resume_bts(struct bts_tracer *tracer)
785{
786 struct task_struct *task;
787 unsigned long control;
788
789 if (!tracer)
790 return;
791
792 task = tracer->ds.context->task;
793
794 control = ds_cfg.ctl[dsf_bts];
795 if (!(tracer->trace.ds.flags & BTS_KERNEL))
796 control |= ds_cfg.ctl[dsf_bts_kernel];
797 if (!(tracer->trace.ds.flags & BTS_USER))
798 control |= ds_cfg.ctl[dsf_bts_user];
799
800 if (task) {
801 task->thread.debugctlmsr |= control;
802 set_tsk_thread_flag(task, TIF_DEBUGCTLMSR);
803 }
804
805 if (!task || (task == current))
806 update_debugctlmsr(get_debugctlmsr() | control);
807}
808
809void ds_release_pebs(struct pebs_tracer *tracer)
810{
811 if (!tracer)
812 return;
813
814 ds_suspend_pebs(tracer);
815
816 WARN_ON_ONCE(tracer->ds.context->pebs_master != tracer);
817 tracer->ds.context->pebs_master = NULL;
818
819 put_tracer(tracer->ds.context->task);
820 ds_put_context(tracer->ds.context);
821
822 kfree(tracer);
823}
824
825void ds_suspend_pebs(struct pebs_tracer *tracer)
826{
827
828}
829
830void ds_resume_pebs(struct pebs_tracer *tracer)
831{
832
833}
834
835const struct bts_trace *ds_read_bts(struct bts_tracer *tracer)
836{
837 if (!tracer)
838 return NULL;
839
840 ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_bts);
841 return &tracer->trace;
842}
843
844const struct pebs_trace *ds_read_pebs(struct pebs_tracer *tracer)
845{
846 if (!tracer)
847 return NULL;
848
849 ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_pebs);
850 tracer->trace.reset_value =
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100851 *(u64 *)(tracer->ds.context->ds +
852 (ds_cfg.sizeof_ptr_field * 8));
Markus Metzgerc2724772008-12-11 13:49:59 +0100853
854 return &tracer->trace;
Markus Metzger93fa7632008-04-08 11:01:58 +0200855}
856
Markus Metzgerca0002a2008-11-25 09:01:25 +0100857int ds_reset_bts(struct bts_tracer *tracer)
Markus Metzger93fa7632008-04-08 11:01:58 +0200858{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100859 if (!tracer)
860 return -EINVAL;
861
Markus Metzgerc2724772008-12-11 13:49:59 +0100862 tracer->trace.ds.top = tracer->trace.ds.begin;
863
864 ds_set(tracer->ds.context->ds, ds_bts, ds_index,
865 (unsigned long)tracer->trace.ds.top);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100866
867 return 0;
Markus Metzger93fa7632008-04-08 11:01:58 +0200868}
869
Markus Metzgerca0002a2008-11-25 09:01:25 +0100870int ds_reset_pebs(struct pebs_tracer *tracer)
Markus Metzger93fa7632008-04-08 11:01:58 +0200871{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100872 if (!tracer)
873 return -EINVAL;
874
Markus Metzgerc2724772008-12-11 13:49:59 +0100875 tracer->trace.ds.top = tracer->trace.ds.begin;
Markus Metzgerca0002a2008-11-25 09:01:25 +0100876
Markus Metzgerc2724772008-12-11 13:49:59 +0100877 ds_set(tracer->ds.context->ds, ds_bts, ds_index,
878 (unsigned long)tracer->trace.ds.top);
Markus Metzger93fa7632008-04-08 11:01:58 +0200879
Markus Metzgerca0002a2008-11-25 09:01:25 +0100880 return 0;
Markus Metzger93fa7632008-04-08 11:01:58 +0200881}
882
Markus Metzgerca0002a2008-11-25 09:01:25 +0100883int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value)
Markus Metzger93fa7632008-04-08 11:01:58 +0200884{
Markus Metzgerca0002a2008-11-25 09:01:25 +0100885 if (!tracer)
886 return -EINVAL;
Markus Metzger93fa7632008-04-08 11:01:58 +0200887
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100888 *(u64 *)(tracer->ds.context->ds +
889 (ds_cfg.sizeof_ptr_field * 8)) = value;
Markus Metzger93fa7632008-04-08 11:01:58 +0200890
Markus Metzgerca0002a2008-11-25 09:01:25 +0100891 return 0;
Markus Metzger93fa7632008-04-08 11:01:58 +0200892}
893
Markus Metzgerc2724772008-12-11 13:49:59 +0100894static const struct ds_configuration ds_cfg_netburst = {
Markus Metzgerba2607f2009-01-19 10:38:35 +0100895 .name = "Netburst",
Markus Metzgerc2724772008-12-11 13:49:59 +0100896 .ctl[dsf_bts] = (1 << 2) | (1 << 3),
897 .ctl[dsf_bts_kernel] = (1 << 5),
898 .ctl[dsf_bts_user] = (1 << 6),
Markus Metzger93fa7632008-04-08 11:01:58 +0200899};
Markus Metzgerc2724772008-12-11 13:49:59 +0100900static const struct ds_configuration ds_cfg_pentium_m = {
Markus Metzgerba2607f2009-01-19 10:38:35 +0100901 .name = "Pentium M",
Markus Metzgerc2724772008-12-11 13:49:59 +0100902 .ctl[dsf_bts] = (1 << 6) | (1 << 7),
Markus Metzgereee3af42008-01-30 13:31:09 +0100903};
Markus Metzgerba2607f2009-01-19 10:38:35 +0100904static const struct ds_configuration ds_cfg_core2_atom = {
905 .name = "Core 2/Atom",
Markus Metzgerc2724772008-12-11 13:49:59 +0100906 .ctl[dsf_bts] = (1 << 6) | (1 << 7),
907 .ctl[dsf_bts_kernel] = (1 << 9),
908 .ctl[dsf_bts_user] = (1 << 10),
Markus Metzgerc2724772008-12-11 13:49:59 +0100909};
Markus Metzgereee3af42008-01-30 13:31:09 +0100910
Markus Metzgerc2724772008-12-11 13:49:59 +0100911static void
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100912ds_configure(const struct ds_configuration *cfg,
913 struct cpuinfo_x86 *cpu)
Markus Metzgereee3af42008-01-30 13:31:09 +0100914{
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100915 unsigned long nr_pebs_fields = 0;
916
917 printk(KERN_INFO "[ds] using %s configuration\n", cfg->name);
918
919#ifdef __i386__
920 nr_pebs_fields = 10;
921#else
922 nr_pebs_fields = 18;
923#endif
924
Markus Metzgerc2724772008-12-11 13:49:59 +0100925 memset(&ds_cfg, 0, sizeof(ds_cfg));
Markus Metzgereee3af42008-01-30 13:31:09 +0100926 ds_cfg = *cfg;
Markus Metzgerca0002a2008-11-25 09:01:25 +0100927
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100928 ds_cfg.sizeof_ptr_field =
929 (cpu_has(cpu, X86_FEATURE_DTES64) ? 8 : 4);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100930
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100931 ds_cfg.sizeof_rec[ds_bts] = ds_cfg.sizeof_ptr_field * 3;
932 ds_cfg.sizeof_rec[ds_pebs] = ds_cfg.sizeof_ptr_field * nr_pebs_fields;
933
934 if (!cpu_has(cpu, X86_FEATURE_BTS)) {
935 ds_cfg.sizeof_rec[ds_bts] = 0;
Markus Metzgerc2724772008-12-11 13:49:59 +0100936 printk(KERN_INFO "[ds] bts not available\n");
937 }
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100938 if (!cpu_has(cpu, X86_FEATURE_PEBS)) {
939 ds_cfg.sizeof_rec[ds_pebs] = 0;
Markus Metzgerc2724772008-12-11 13:49:59 +0100940 printk(KERN_INFO "[ds] pebs not available\n");
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100941 }
942
Markus Metzger8a327f62009-03-13 10:45:07 +0100943 if (ds_cfg.sizeof_rec[ds_bts]) {
944 int error;
945
946 error = ds_selftest_bts();
947 if (error) {
948 WARN(1, "[ds] selftest failed. disabling bts.\n");
949 ds_cfg.sizeof_rec[ds_bts] = 0;
950 }
951 }
952
953 if (ds_cfg.sizeof_rec[ds_pebs]) {
954 int error;
955
956 error = ds_selftest_pebs();
957 if (error) {
958 WARN(1, "[ds] selftest failed. disabling pebs.\n");
959 ds_cfg.sizeof_rec[ds_pebs] = 0;
960 }
961 }
962
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100963 printk(KERN_INFO "[ds] sizes: address: %u bit, ",
964 8 * ds_cfg.sizeof_ptr_field);
965 printk("bts/pebs record: %u/%u bytes\n",
966 ds_cfg.sizeof_rec[ds_bts], ds_cfg.sizeof_rec[ds_pebs]);
Markus Metzgerc2724772008-12-11 13:49:59 +0100967
968 WARN_ON_ONCE(MAX_SIZEOF_DS < (12 * ds_cfg.sizeof_field));
Markus Metzgereee3af42008-01-30 13:31:09 +0100969}
970
971void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
972{
973 switch (c->x86) {
974 case 0x6:
975 switch (c->x86_model) {
Markus Metzgerba2607f2009-01-19 10:38:35 +0100976 case 0x9:
977 case 0xd: /* Pentium M */
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100978 ds_configure(&ds_cfg_pentium_m, c);
Markus Metzgereee3af42008-01-30 13:31:09 +0100979 break;
Markus Metzgerba2607f2009-01-19 10:38:35 +0100980 case 0xf:
981 case 0x17: /* Core2 */
982 case 0x1c: /* Atom */
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100983 ds_configure(&ds_cfg_core2_atom, c);
Markus Metzgerba2607f2009-01-19 10:38:35 +0100984 break;
Markus Metzgerb8e47192009-03-13 10:46:42 +0100985 case 0x1a: /* Core i7 */
Markus Metzgerba2607f2009-01-19 10:38:35 +0100986 default:
Markus Metzgerb8e47192009-03-13 10:46:42 +0100987 /* Sorry, don't know about them. */
Markus Metzgereee3af42008-01-30 13:31:09 +0100988 break;
Markus Metzgereee3af42008-01-30 13:31:09 +0100989 }
990 break;
Markus Metzgerba2607f2009-01-19 10:38:35 +0100991 case 0xf:
Markus Metzgereee3af42008-01-30 13:31:09 +0100992 switch (c->x86_model) {
Markus Metzgereee3af42008-01-30 13:31:09 +0100993 case 0x0:
994 case 0x1:
995 case 0x2: /* Netburst */
Markus Metzgerbc44fb52009-03-13 10:42:18 +0100996 ds_configure(&ds_cfg_netburst, c);
Markus Metzgereee3af42008-01-30 13:31:09 +0100997 break;
Markus Metzgereee3af42008-01-30 13:31:09 +0100998 default:
Markus Metzgerb8e47192009-03-13 10:46:42 +0100999 /* Sorry, don't know about them. */
Markus Metzgereee3af42008-01-30 13:31:09 +01001000 break;
1001 }
1002 break;
1003 default:
Markus Metzgerb8e47192009-03-13 10:46:42 +01001004 /* Sorry, don't know about them. */
Markus Metzgereee3af42008-01-30 13:31:09 +01001005 break;
1006 }
1007}
Markus Metzger93fa7632008-04-08 11:01:58 +02001008
Markus Metzgerc2724772008-12-11 13:49:59 +01001009/*
1010 * Change the DS configuration from tracing prev to tracing next.
1011 */
1012void ds_switch_to(struct task_struct *prev, struct task_struct *next)
Markus Metzger93fa7632008-04-08 11:01:58 +02001013{
Markus Metzgerc2724772008-12-11 13:49:59 +01001014 struct ds_context *prev_ctx = prev->thread.ds_ctx;
1015 struct ds_context *next_ctx = next->thread.ds_ctx;
1016
1017 if (prev_ctx) {
1018 update_debugctlmsr(0);
1019
1020 if (prev_ctx->bts_master &&
1021 (prev_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
1022 struct bts_struct ts = {
1023 .qualifier = bts_task_departs,
1024 .variant.timestamp.jiffies = jiffies_64,
1025 .variant.timestamp.pid = prev->pid
1026 };
1027 bts_write(prev_ctx->bts_master, &ts);
1028 }
Markus Metzgerca0002a2008-11-25 09:01:25 +01001029 }
Markus Metzgerc2724772008-12-11 13:49:59 +01001030
1031 if (next_ctx) {
1032 if (next_ctx->bts_master &&
1033 (next_ctx->bts_master->trace.ds.flags & BTS_TIMESTAMPS)) {
1034 struct bts_struct ts = {
1035 .qualifier = bts_task_arrives,
1036 .variant.timestamp.jiffies = jiffies_64,
1037 .variant.timestamp.pid = next->pid
1038 };
1039 bts_write(next_ctx->bts_master, &ts);
1040 }
1041
1042 wrmsrl(MSR_IA32_DS_AREA, (unsigned long)next_ctx->ds);
1043 }
1044
1045 update_debugctlmsr(next->thread.debugctlmsr);
Markus Metzger93fa7632008-04-08 11:01:58 +02001046}
Markus Metzgerbf53de92008-12-19 15:10:24 +01001047
1048void ds_copy_thread(struct task_struct *tsk, struct task_struct *father)
1049{
1050 clear_tsk_thread_flag(tsk, TIF_DS_AREA_MSR);
1051 tsk->thread.ds_ctx = NULL;
1052}
1053
1054void ds_exit_thread(struct task_struct *tsk)
1055{
Markus Metzgerbf53de92008-12-19 15:10:24 +01001056}