diff options
author | Barry Kasindorf <barry.kasindorf@amd.com> | 2008-07-22 15:08:54 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-26 05:48:04 -0400 |
commit | 345c25730d085c45622ac779da4dbd97dc3a10fe (patch) | |
tree | 12f31ee55b97ef9604b37990e05c523178c32901 /drivers/oprofile/buffer_sync.c | |
parent | ee648bc77f11b57d15a68d336fc30e343198f893 (diff) |
x86/oprofile: add IBS support for AMD CPUs, IBS buffer handling routines
This patchset supports the new profiling hardware available in the
latest AMD CPUs in the oProfile driver.
Signed-off-by: Barry Kasindorf <barry.kasindorf@amd.com>
Signed-off-by: Robert Richter <robert.richter@amd.com>
Cc: oprofile-list <oprofile-list@lists.sourceforge.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/oprofile/buffer_sync.c')
-rw-r--r-- | drivers/oprofile/buffer_sync.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 615929f6f0c2..e1782d2df09f 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Barry Kasindorf | ||
8 | * | 9 | * |
9 | * This is the core of the buffer management. Each | 10 | * This is the core of the buffer management. Each |
10 | * CPU buffer is processed and entered into the | 11 | * CPU buffer is processed and entered into the |
@@ -272,7 +273,7 @@ static void increment_tail(struct oprofile_cpu_buffer *b) | |||
272 | { | 273 | { |
273 | unsigned long new_tail = b->tail_pos + 1; | 274 | unsigned long new_tail = b->tail_pos + 1; |
274 | 275 | ||
275 | rmb(); | 276 | rmb(); /* be sure fifo pointers are synchromized */ |
276 | 277 | ||
277 | if (new_tail < b->buffer_size) | 278 | if (new_tail < b->buffer_size) |
278 | b->tail_pos = new_tail; | 279 | b->tail_pos = new_tail; |
@@ -327,6 +328,67 @@ static void add_trace_begin(void) | |||
327 | add_event_entry(TRACE_BEGIN_CODE); | 328 | add_event_entry(TRACE_BEGIN_CODE); |
328 | } | 329 | } |
329 | 330 | ||
331 | #define IBS_FETCH_CODE_SIZE 2 | ||
332 | #define IBS_OP_CODE_SIZE 5 | ||
333 | #define IBS_EIP(offset) \ | ||
334 | (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip) | ||
335 | #define IBS_EVENT(offset) \ | ||
336 | (((struct op_sample *)&cpu_buf->buffer[(offset)])->event) | ||
337 | |||
338 | /* | ||
339 | * Add IBS fetch and op entries to event buffer | ||
340 | */ | ||
341 | static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, | ||
342 | int in_kernel, struct mm_struct *mm) | ||
343 | { | ||
344 | unsigned long rip; | ||
345 | int i, count; | ||
346 | unsigned long ibs_cookie = 0; | ||
347 | off_t offset; | ||
348 | |||
349 | increment_tail(cpu_buf); /* move to RIP entry */ | ||
350 | |||
351 | rip = IBS_EIP(cpu_buf->tail_pos); | ||
352 | |||
353 | #ifdef __LP64__ | ||
354 | rip += IBS_EVENT(cpu_buf->tail_pos) << 32; | ||
355 | #endif | ||
356 | |||
357 | if (mm) { | ||
358 | ibs_cookie = lookup_dcookie(mm, rip, &offset); | ||
359 | |||
360 | if (ibs_cookie == NO_COOKIE) | ||
361 | offset = rip; | ||
362 | if (ibs_cookie == INVALID_COOKIE) { | ||
363 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); | ||
364 | offset = rip; | ||
365 | } | ||
366 | if (ibs_cookie != last_cookie) { | ||
367 | add_cookie_switch(ibs_cookie); | ||
368 | last_cookie = ibs_cookie; | ||
369 | } | ||
370 | } else | ||
371 | offset = rip; | ||
372 | |||
373 | add_event_entry(ESCAPE_CODE); | ||
374 | add_event_entry(code); | ||
375 | add_event_entry(offset); /* Offset from Dcookie */ | ||
376 | |||
377 | /* we send the Dcookie offset, but send the raw Linear Add also*/ | ||
378 | add_event_entry(IBS_EIP(cpu_buf->tail_pos)); | ||
379 | add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); | ||
380 | |||
381 | if (code == IBS_FETCH_CODE) | ||
382 | count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ | ||
383 | else | ||
384 | count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ | ||
385 | |||
386 | for (i = 0; i < count; i++) { | ||
387 | increment_tail(cpu_buf); | ||
388 | add_event_entry(IBS_EIP(cpu_buf->tail_pos)); | ||
389 | add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); | ||
390 | } | ||
391 | } | ||
330 | 392 | ||
331 | static void add_sample_entry(unsigned long offset, unsigned long event) | 393 | static void add_sample_entry(unsigned long offset, unsigned long event) |
332 | { | 394 | { |
@@ -524,6 +586,14 @@ void sync_buffer(int cpu) | |||
524 | } else if (s->event == CPU_TRACE_BEGIN) { | 586 | } else if (s->event == CPU_TRACE_BEGIN) { |
525 | state = sb_bt_start; | 587 | state = sb_bt_start; |
526 | add_trace_begin(); | 588 | add_trace_begin(); |
589 | } else if (s->event == IBS_FETCH_BEGIN) { | ||
590 | state = sb_bt_start; | ||
591 | add_ibs_begin(cpu_buf, | ||
592 | IBS_FETCH_CODE, in_kernel, mm); | ||
593 | } else if (s->event == IBS_OP_BEGIN) { | ||
594 | state = sb_bt_start; | ||
595 | add_ibs_begin(cpu_buf, | ||
596 | IBS_OP_CODE, in_kernel, mm); | ||
527 | } else { | 597 | } else { |
528 | struct mm_struct *oldmm = mm; | 598 | struct mm_struct *oldmm = mm; |
529 | 599 | ||