blob: 99b6c39774a44179fcf3554a096449962167d490 [file] [log] [blame]
Markus Metzgereee3af42008-01-30 13:31:09 +01001/*
2 * Debug Store (DS) 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:
9 * - per-thread and per-cpu allocation of BTS and PEBS
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 *
13 * It assumes:
Markus Metzger6abb11a2008-11-25 09:05:27 +010014 * - get_task_struct on all traced tasks
15 * - current is allowed to trace tasks
Markus Metzgereee3af42008-01-30 13:31:09 +010016 *
17 *
Markus Metzger93fa7632008-04-08 11:01:58 +020018 * Copyright (C) 2007-2008 Intel Corporation.
19 * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
Markus Metzgereee3af42008-01-30 13:31:09 +010020 */
21
H. Peter Anvin1965aae2008-10-22 22:26:29 -070022#ifndef _ASM_X86_DS_H
23#define _ASM_X86_DS_H
Markus Metzgereee3af42008-01-30 13:31:09 +010024
Markus Metzger93fa7632008-04-08 11:01:58 +020025
Markus Metzgereee3af42008-01-30 13:31:09 +010026#include <linux/types.h>
27#include <linux/init.h>
Markus Metzgerca0002a2008-11-25 09:01:25 +010028#include <linux/err.h>
Markus Metzgereee3af42008-01-30 13:31:09 +010029
Markus Metzgereee3af42008-01-30 13:31:09 +010030
Markus Metzgere5e8ca62008-11-25 08:47:19 +010031#ifdef CONFIG_X86_DS
32
Markus Metzger93fa7632008-04-08 11:01:58 +020033struct task_struct;
Markus Metzgerca0002a2008-11-25 09:01:25 +010034struct ds_tracer;
35struct bts_tracer;
36struct pebs_tracer;
37
38typedef void (*bts_ovfl_callback_t)(struct bts_tracer *);
39typedef void (*pebs_ovfl_callback_t)(struct pebs_tracer *);
Markus Metzgereee3af42008-01-30 13:31:09 +010040
Markus Metzger93fa7632008-04-08 11:01:58 +020041/*
42 * Request BTS or PEBS
Markus Metzgereee3af42008-01-30 13:31:09 +010043 *
Markus Metzger93fa7632008-04-08 11:01:58 +020044 * Due to alignement constraints, the actual buffer may be slightly
45 * smaller than the requested or provided buffer.
46 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010047 * Returns a pointer to a tracer structure on success, or
48 * ERR_PTR(errcode) on failure.
49 *
50 * The interrupt threshold is independent from the overflow callback
51 * to allow users to use their own overflow interrupt handling mechanism.
Markus Metzger93fa7632008-04-08 11:01:58 +020052 *
53 * task: the task to request recording for;
54 * NULL for per-cpu recording on the current cpu
55 * base: the base pointer for the (non-pageable) buffer;
Markus Metzger6abb11a2008-11-25 09:05:27 +010056 * size: the size of the provided buffer in bytes
Markus Metzger93fa7632008-04-08 11:01:58 +020057 * ovfl: pointer to a function to be called on buffer overflow;
58 * NULL if cyclic buffer requested
Markus Metzgerca0002a2008-11-25 09:01:25 +010059 * th: the interrupt threshold in records from the end of the buffer;
60 * -1 if no interrupt threshold is requested.
Markus Metzgereee3af42008-01-30 13:31:09 +010061 */
Markus Metzgerca0002a2008-11-25 09:01:25 +010062extern struct bts_tracer *ds_request_bts(struct task_struct *task,
63 void *base, size_t size,
64 bts_ovfl_callback_t ovfl, size_t th);
65extern struct pebs_tracer *ds_request_pebs(struct task_struct *task,
66 void *base, size_t size,
67 pebs_ovfl_callback_t ovfl,
68 size_t th);
Markus Metzger93fa7632008-04-08 11:01:58 +020069
70/*
71 * Release BTS or PEBS resources
72 *
Markus Metzger93fa7632008-04-08 11:01:58 +020073 * Returns 0 on success; -Eerrno otherwise
74 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010075 * tracer: the tracer handle returned from ds_request_~()
Markus Metzger93fa7632008-04-08 11:01:58 +020076 */
Markus Metzgerca0002a2008-11-25 09:01:25 +010077extern int ds_release_bts(struct bts_tracer *tracer);
78extern int ds_release_pebs(struct pebs_tracer *tracer);
Markus Metzger93fa7632008-04-08 11:01:58 +020079
80/*
Markus Metzgerca0002a2008-11-25 09:01:25 +010081 * Get the (array) index of the write pointer.
Markus Metzger93fa7632008-04-08 11:01:58 +020082 * (assuming an array of BTS/PEBS records)
83 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010084 * Returns 0 on success; -Eerrno on error
Markus Metzger93fa7632008-04-08 11:01:58 +020085 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010086 * tracer: the tracer handle returned from ds_request_~()
87 * pos (out): will hold the result
Markus Metzger93fa7632008-04-08 11:01:58 +020088 */
Markus Metzgerca0002a2008-11-25 09:01:25 +010089extern int ds_get_bts_index(struct bts_tracer *tracer, size_t *pos);
90extern int ds_get_pebs_index(struct pebs_tracer *tracer, size_t *pos);
Markus Metzger93fa7632008-04-08 11:01:58 +020091
92/*
Markus Metzgerca0002a2008-11-25 09:01:25 +010093 * Get the (array) index one record beyond the end of the array.
Markus Metzger93fa7632008-04-08 11:01:58 +020094 * (assuming an array of BTS/PEBS records)
95 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010096 * Returns 0 on success; -Eerrno on error
Markus Metzger93fa7632008-04-08 11:01:58 +020097 *
Markus Metzgerca0002a2008-11-25 09:01:25 +010098 * tracer: the tracer handle returned from ds_request_~()
99 * pos (out): will hold the result
Markus Metzger93fa7632008-04-08 11:01:58 +0200100 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100101extern int ds_get_bts_end(struct bts_tracer *tracer, size_t *pos);
102extern int ds_get_pebs_end(struct pebs_tracer *tracer, size_t *pos);
Markus Metzger93fa7632008-04-08 11:01:58 +0200103
104/*
105 * Provide a pointer to the BTS/PEBS record at parameter index.
106 * (assuming an array of BTS/PEBS records)
107 *
108 * The pointer points directly into the buffer. The user is
109 * responsible for copying the record.
110 *
111 * Returns the size of a single record on success; -Eerrno on error
112 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100113 * tracer: the tracer handle returned from ds_request_~()
Markus Metzger93fa7632008-04-08 11:01:58 +0200114 * index: the index of the requested record
115 * record (out): pointer to the requested record
116 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100117extern int ds_access_bts(struct bts_tracer *tracer,
Markus Metzger93fa7632008-04-08 11:01:58 +0200118 size_t index, const void **record);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100119extern int ds_access_pebs(struct pebs_tracer *tracer,
Markus Metzger93fa7632008-04-08 11:01:58 +0200120 size_t index, const void **record);
121
122/*
123 * Write one or more BTS/PEBS records at the write pointer index and
124 * advance the write pointer.
125 *
126 * If size is not a multiple of the record size, trailing bytes are
127 * zeroed out.
128 *
129 * May result in one or more overflow notifications.
130 *
131 * If called during overflow handling, that is, with index >=
132 * interrupt threshold, the write will wrap around.
133 *
134 * An overflow notification is given if and when the interrupt
135 * threshold is reached during or after the write.
136 *
137 * Returns the number of bytes written or -Eerrno.
138 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100139 * tracer: the tracer handle returned from ds_request_~()
Markus Metzger93fa7632008-04-08 11:01:58 +0200140 * buffer: the buffer to write
141 * size: the size of the buffer
142 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100143extern int ds_write_bts(struct bts_tracer *tracer,
Markus Metzger93fa7632008-04-08 11:01:58 +0200144 const void *buffer, size_t size);
Markus Metzgerca0002a2008-11-25 09:01:25 +0100145extern int ds_write_pebs(struct pebs_tracer *tracer,
Markus Metzger93fa7632008-04-08 11:01:58 +0200146 const void *buffer, size_t size);
147
148/*
Markus Metzger93fa7632008-04-08 11:01:58 +0200149 * Reset the write pointer of the BTS/PEBS buffer.
150 *
151 * Returns 0 on success; -Eerrno on error
152 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100153 * tracer: the tracer handle returned from ds_request_~()
Markus Metzger93fa7632008-04-08 11:01:58 +0200154 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100155extern int ds_reset_bts(struct bts_tracer *tracer);
156extern int ds_reset_pebs(struct pebs_tracer *tracer);
Markus Metzger93fa7632008-04-08 11:01:58 +0200157
158/*
159 * Clear the BTS/PEBS buffer and reset the write pointer.
160 * The entire buffer will be zeroed out.
161 *
162 * Returns 0 on success; -Eerrno on error
163 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100164 * tracer: the tracer handle returned from ds_request_~()
Markus Metzger93fa7632008-04-08 11:01:58 +0200165 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100166extern int ds_clear_bts(struct bts_tracer *tracer);
167extern int ds_clear_pebs(struct pebs_tracer *tracer);
Markus Metzger93fa7632008-04-08 11:01:58 +0200168
169/*
170 * Provide the PEBS counter reset value.
171 *
172 * Returns 0 on success; -Eerrno on error
173 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100174 * tracer: the tracer handle returned from ds_request_pebs()
Markus Metzger93fa7632008-04-08 11:01:58 +0200175 * value (out): the counter reset value
176 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100177extern int ds_get_pebs_reset(struct pebs_tracer *tracer, u64 *value);
Markus Metzger93fa7632008-04-08 11:01:58 +0200178
179/*
180 * Set the PEBS counter reset value.
181 *
182 * Returns 0 on success; -Eerrno on error
183 *
Markus Metzgerca0002a2008-11-25 09:01:25 +0100184 * tracer: the tracer handle returned from ds_request_pebs()
Markus Metzger93fa7632008-04-08 11:01:58 +0200185 * value: the new counter reset value
186 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100187extern int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value);
Markus Metzger93fa7632008-04-08 11:01:58 +0200188
189/*
190 * Initialization
191 */
192struct cpuinfo_x86;
193extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *);
194
195
196
197/*
198 * The DS context - part of struct thread_struct.
199 */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100200#define MAX_SIZEOF_DS (12 * 8)
201
Markus Metzger93fa7632008-04-08 11:01:58 +0200202struct ds_context {
203 /* pointer to the DS configuration; goes into MSR_IA32_DS_AREA */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100204 unsigned char ds[MAX_SIZEOF_DS];
Markus Metzger93fa7632008-04-08 11:01:58 +0200205 /* the owner of the BTS and PEBS configuration, respectively */
Markus Metzgerca0002a2008-11-25 09:01:25 +0100206 struct ds_tracer *owner[2];
Markus Metzger93fa7632008-04-08 11:01:58 +0200207 /* use count */
208 unsigned long count;
209 /* a pointer to the context location inside the thread_struct
210 * or the per_cpu context array */
211 struct ds_context **this;
212 /* a pointer to the task owning this context, or NULL, if the
213 * context is owned by a cpu */
214 struct task_struct *task;
Markus Metzgereee3af42008-01-30 13:31:09 +0100215};
216
Markus Metzger93fa7632008-04-08 11:01:58 +0200217/* called by exit_thread() to free leftover contexts */
218extern void ds_free(struct ds_context *context);
Markus Metzgereee3af42008-01-30 13:31:09 +0100219
Markus Metzger93fa7632008-04-08 11:01:58 +0200220#else /* CONFIG_X86_DS */
Markus Metzgereee3af42008-01-30 13:31:09 +0100221
Markus Metzgere5e8ca62008-11-25 08:47:19 +0100222struct cpuinfo_x86;
223static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {}
Markus Metzgereee3af42008-01-30 13:31:09 +0100224
Markus Metzger93fa7632008-04-08 11:01:58 +0200225#endif /* CONFIG_X86_DS */
H. Peter Anvin1965aae2008-10-22 22:26:29 -0700226#endif /* _ASM_X86_DS_H */