Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2...
[linux-2.6.git] / drivers / oprofile / cpu_buffer.c
1 /**
2  * @file cpu_buffer.c
3  *
4  * @remark Copyright 2002 OProfile authors
5  * @remark Read the file COPYING
6  *
7  * @author John Levon <levon@movementarian.org>
8  *
9  * Modified by Aravind Menon for Xen
10  * These modifications are:
11  * Copyright (C) 2005 Hewlett-Packard Co.
12  *
13  * Each CPU has a local buffer that stores PC value/event
14  * pairs. We also log context switches when we notice them.
15  * Eventually each CPU's buffer is processed into the global
16  * event buffer by sync_buffer().
17  *
18  * We use a local buffer for two reasons: an NMI or similar
19  * interrupt cannot synchronise, and high sampling rates
20  * would lead to catastrophic global synchronisation if
21  * a global buffer was used.
22  */
23
24 #include <linux/sched.h>
25 #include <linux/oprofile.h>
26 #include <linux/vmalloc.h>
27 #include <linux/errno.h>
28  
29 #include "event_buffer.h"
30 #include "cpu_buffer.h"
31 #include "buffer_sync.h"
32 #include "oprof.h"
33
34 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
35
36 static void wq_sync_buffer(void *);
37
38 #define DEFAULT_TIMER_EXPIRE (HZ / 10)
39 static int work_enabled;
40
41 static int32_t current_domain = COORDINATOR_DOMAIN;
42
43 void free_cpu_buffers(void)
44 {
45         int i;
46  
47         for_each_online_cpu(i)
48                 vfree(cpu_buffer[i].buffer);
49 }
50
51 int alloc_cpu_buffers(void)
52 {
53         int i;
54  
55         unsigned long buffer_size = fs_cpu_buffer_size;
56  
57         for_each_online_cpu(i) {
58                 struct oprofile_cpu_buffer * b = &cpu_buffer[i];
59  
60                 b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,
61                         cpu_to_node(i));
62                 if (!b->buffer)
63                         goto fail;
64  
65                 b->last_task = NULL;
66                 b->last_cpu_mode = -1;
67                 b->tracing = 0;
68                 b->buffer_size = buffer_size;
69                 b->tail_pos = 0;
70                 b->head_pos = 0;
71                 b->sample_received = 0;
72                 b->sample_lost_overflow = 0;
73                 b->cpu = i;
74                 INIT_WORK(&b->work, wq_sync_buffer, b);
75         }
76         return 0;
77
78 fail:
79         free_cpu_buffers();
80         return -ENOMEM;
81 }
82
83 void start_cpu_work(void)
84 {
85         int i;
86
87         work_enabled = 1;
88
89         for_each_online_cpu(i) {
90                 struct oprofile_cpu_buffer * b = &cpu_buffer[i];
91
92                 /*
93                  * Spread the work by 1 jiffy per cpu so they dont all
94                  * fire at once.
95                  */
96                 schedule_delayed_work_on(i, &b->work, DEFAULT_TIMER_EXPIRE + i);
97         }
98 }
99
100 void end_cpu_work(void)
101 {
102         int i;
103
104         work_enabled = 0;
105
106         for_each_online_cpu(i) {
107                 struct oprofile_cpu_buffer * b = &cpu_buffer[i];
108
109                 cancel_delayed_work(&b->work);
110         }
111
112         flush_scheduled_work();
113 }
114
115 /* Resets the cpu buffer to a sane state. */
116 void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf)
117 {
118         /* reset these to invalid values; the next sample
119          * collected will populate the buffer with proper
120          * values to initialize the buffer
121          */
122         cpu_buf->last_cpu_mode = -1;
123         cpu_buf->last_task = NULL;
124 }
125
126 /* compute number of available slots in cpu_buffer queue */
127 static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
128 {
129         unsigned long head = b->head_pos;
130         unsigned long tail = b->tail_pos;
131
132         if (tail > head)
133                 return (tail - head) - 1;
134
135         return tail + (b->buffer_size - head) - 1;
136 }
137
138 static void increment_head(struct oprofile_cpu_buffer * b)
139 {
140         unsigned long new_head = b->head_pos + 1;
141
142         /* Ensure anything written to the slot before we
143          * increment is visible */
144         wmb();
145
146         if (new_head < b->buffer_size)
147                 b->head_pos = new_head;
148         else
149                 b->head_pos = 0;
150 }
151
152 static inline void
153 add_sample(struct oprofile_cpu_buffer * cpu_buf,
154            unsigned long pc, unsigned long event)
155 {
156         struct op_sample * entry = &cpu_buf->buffer[cpu_buf->head_pos];
157         entry->eip = pc;
158         entry->event = event;
159         increment_head(cpu_buf);
160 }
161
162 static inline void
163 add_code(struct oprofile_cpu_buffer * buffer, unsigned long value)
164 {
165         add_sample(buffer, ESCAPE_CODE, value);
166 }
167
168 /* This must be safe from any context. It's safe writing here
169  * because of the head/tail separation of the writer and reader
170  * of the CPU buffer.
171  *
172  * cpu_mode is needed because on some architectures you cannot
173  * tell if you are in kernel or user space simply by looking at
174  * pc. We tag this in the buffer by generating kernel/user (and xen)
175  *  enter events whenever cpu_mode changes
176  */
177 static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
178                       int cpu_mode, unsigned long event)
179 {
180         struct task_struct * task;
181
182         cpu_buf->sample_received++;
183
184         if (nr_available_slots(cpu_buf) < 3) {
185                 cpu_buf->sample_lost_overflow++;
186                 return 0;
187         }
188
189         WARN_ON(cpu_mode > CPU_MODE_XEN);
190
191         task = current;
192
193         /* notice a switch from user->kernel or vice versa */
194         if (cpu_buf->last_cpu_mode != cpu_mode) {
195                 cpu_buf->last_cpu_mode = cpu_mode;
196                 add_code(cpu_buf, cpu_mode);
197         }
198         
199         /* notice a task switch */
200         /* if not processing other domain samples */
201         if ((cpu_buf->last_task != task) &&
202             (current_domain == COORDINATOR_DOMAIN)) {
203                 cpu_buf->last_task = task;
204                 add_code(cpu_buf, (unsigned long)task);
205         }
206  
207         add_sample(cpu_buf, pc, event);
208         return 1;
209 }
210
211 static int oprofile_begin_trace(struct oprofile_cpu_buffer * cpu_buf)
212 {
213         if (nr_available_slots(cpu_buf) < 4) {
214                 cpu_buf->sample_lost_overflow++;
215                 return 0;
216         }
217
218         add_code(cpu_buf, CPU_TRACE_BEGIN);
219         cpu_buf->tracing = 1;
220         return 1;
221 }
222
223 static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf)
224 {
225         cpu_buf->tracing = 0;
226 }
227
228 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
229                                 unsigned long event, int is_kernel)
230 {
231         struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
232
233         if (!backtrace_depth) {
234                 log_sample(cpu_buf, pc, is_kernel, event);
235                 return;
236         }
237
238         if (!oprofile_begin_trace(cpu_buf))
239                 return;
240
241         /* if log_sample() fail we can't backtrace since we lost the source
242          * of this event */
243         if (log_sample(cpu_buf, pc, is_kernel, event))
244                 oprofile_ops.backtrace(regs, backtrace_depth);
245         oprofile_end_trace(cpu_buf);
246 }
247
248 void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
249 {
250         int is_kernel = !user_mode(regs);
251         unsigned long pc = profile_pc(regs);
252
253         oprofile_add_ext_sample(pc, regs, event, is_kernel);
254 }
255
256 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
257 {
258         struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
259         log_sample(cpu_buf, pc, is_kernel, event);
260 }
261
262 void oprofile_add_trace(unsigned long pc)
263 {
264         struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
265
266         if (!cpu_buf->tracing)
267                 return;
268
269         if (nr_available_slots(cpu_buf) < 1) {
270                 cpu_buf->tracing = 0;
271                 cpu_buf->sample_lost_overflow++;
272                 return;
273         }
274
275         /* broken frame can give an eip with the same value as an escape code,
276          * abort the trace if we get it */
277         if (pc == ESCAPE_CODE) {
278                 cpu_buf->tracing = 0;
279                 cpu_buf->backtrace_aborted++;
280                 return;
281         }
282
283         add_sample(cpu_buf, pc, 0);
284 }
285
286 int oprofile_add_domain_switch(int32_t domain_id)
287 {
288         struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
289
290         /* should have space for switching into and out of domain 
291            (2 slots each) plus one sample and one cpu mode switch */
292         if (((nr_available_slots(cpu_buf) < 6) && 
293              (domain_id != COORDINATOR_DOMAIN)) ||
294             (nr_available_slots(cpu_buf) < 2))
295                 return 0;
296
297         add_code(cpu_buf, CPU_DOMAIN_SWITCH);
298         add_sample(cpu_buf, domain_id, 0);
299
300         current_domain = domain_id;
301
302         return 1;
303 }
304
305 /*
306  * This serves to avoid cpu buffer overflow, and makes sure
307  * the task mortuary progresses
308  *
309  * By using schedule_delayed_work_on and then schedule_delayed_work
310  * we guarantee this will stay on the correct cpu
311  */
312 static void wq_sync_buffer(void * data)
313 {
314         struct oprofile_cpu_buffer * b = data;
315         if (b->cpu != smp_processor_id()) {
316                 printk("WQ on CPU%d, prefer CPU%d\n",
317                        smp_processor_id(), b->cpu);
318         }
319         sync_buffer(b->cpu);
320
321         /* don't re-add the work if we're shutting down */
322         if (work_enabled)
323                 schedule_delayed_work(&b->work, DEFAULT_TIMER_EXPIRE);
324 }