aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/oprofile/buffer_sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/oprofile/buffer_sync.c')
-rw-r--r--drivers/oprofile/buffer_sync.c117
1 files changed, 40 insertions, 77 deletions
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index b55cd23ffdef..737bd9484822 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -268,18 +268,6 @@ lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset)
268 return cookie; 268 return cookie;
269} 269}
270 270
271static void increment_tail(struct oprofile_cpu_buffer *b)
272{
273 unsigned long new_tail = b->tail_pos + 1;
274
275 rmb(); /* be sure fifo pointers are synchromized */
276
277 if (new_tail < b->buffer_size)
278 b->tail_pos = new_tail;
279 else
280 b->tail_pos = 0;
281}
282
283static unsigned long last_cookie = INVALID_COOKIE; 271static unsigned long last_cookie = INVALID_COOKIE;
284 272
285static void add_cpu_switch(int i) 273static void add_cpu_switch(int i)
@@ -331,28 +319,25 @@ static void add_trace_begin(void)
331 319
332#define IBS_FETCH_CODE_SIZE 2 320#define IBS_FETCH_CODE_SIZE 2
333#define IBS_OP_CODE_SIZE 5 321#define IBS_OP_CODE_SIZE 5
334#define IBS_EIP(offset) \
335 (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip)
336#define IBS_EVENT(offset) \
337 (((struct op_sample *)&cpu_buf->buffer[(offset)])->event)
338 322
339/* 323/*
340 * Add IBS fetch and op entries to event buffer 324 * Add IBS fetch and op entries to event buffer
341 */ 325 */
342static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, 326static void add_ibs_begin(int cpu, int code, struct mm_struct *mm)
343 struct mm_struct *mm)
344{ 327{
345 unsigned long rip; 328 unsigned long rip;
346 int i, count; 329 int i, count;
347 unsigned long ibs_cookie = 0; 330 unsigned long ibs_cookie = 0;
348 off_t offset; 331 off_t offset;
332 struct op_sample *sample;
349 333
350 increment_tail(cpu_buf); /* move to RIP entry */ 334 sample = cpu_buffer_read_entry(cpu);
351 335 if (!sample)
352 rip = IBS_EIP(cpu_buf->tail_pos); 336 goto Error;
337 rip = sample->eip;
353 338
354#ifdef __LP64__ 339#ifdef __LP64__
355 rip += IBS_EVENT(cpu_buf->tail_pos) << 32; 340 rip += sample->event << 32;
356#endif 341#endif
357 342
358 if (mm) { 343 if (mm) {
@@ -376,8 +361,8 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
376 add_event_entry(offset); /* Offset from Dcookie */ 361 add_event_entry(offset); /* Offset from Dcookie */
377 362
378 /* we send the Dcookie offset, but send the raw Linear Add also*/ 363 /* we send the Dcookie offset, but send the raw Linear Add also*/
379 add_event_entry(IBS_EIP(cpu_buf->tail_pos)); 364 add_event_entry(sample->eip);
380 add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); 365 add_event_entry(sample->event);
381 366
382 if (code == IBS_FETCH_CODE) 367 if (code == IBS_FETCH_CODE)
383 count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ 368 count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/
@@ -385,10 +370,17 @@ static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code,
385 count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ 370 count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/
386 371
387 for (i = 0; i < count; i++) { 372 for (i = 0; i < count; i++) {
388 increment_tail(cpu_buf); 373 sample = cpu_buffer_read_entry(cpu);
389 add_event_entry(IBS_EIP(cpu_buf->tail_pos)); 374 if (!sample)
390 add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); 375 goto Error;
376 add_event_entry(sample->eip);
377 add_event_entry(sample->event);
391 } 378 }
379
380 return;
381
382Error:
383 return;
392} 384}
393 385
394#endif 386#endif
@@ -466,33 +458,6 @@ static inline int is_code(unsigned long val)
466} 458}
467 459
468 460
469/* "acquire" as many cpu buffer slots as we can */
470static unsigned long get_slots(struct oprofile_cpu_buffer *b)
471{
472 unsigned long head = b->head_pos;
473 unsigned long tail = b->tail_pos;
474
475 /*
476 * Subtle. This resets the persistent last_task
477 * and in_kernel values used for switching notes.
478 * BUT, there is a small window between reading
479 * head_pos, and this call, that means samples
480 * can appear at the new head position, but not
481 * be prefixed with the notes for switching
482 * kernel mode or a task switch. This small hole
483 * can lead to mis-attribution or samples where
484 * we don't know if it's in the kernel or not,
485 * at the start of an event buffer.
486 */
487 cpu_buffer_reset(b);
488
489 if (head >= tail)
490 return head - tail;
491
492 return head + (b->buffer_size - tail);
493}
494
495
496/* Move tasks along towards death. Any tasks on dead_tasks 461/* Move tasks along towards death. Any tasks on dead_tasks
497 * will definitely have no remaining references in any 462 * will definitely have no remaining references in any
498 * CPU buffers at this point, because we use two lists, 463 * CPU buffers at this point, because we use two lists,
@@ -559,61 +524,61 @@ typedef enum {
559 */ 524 */
560void sync_buffer(int cpu) 525void sync_buffer(int cpu)
561{ 526{
562 struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
563 struct mm_struct *mm = NULL; 527 struct mm_struct *mm = NULL;
528 struct mm_struct *oldmm;
564 struct task_struct *new; 529 struct task_struct *new;
565 unsigned long cookie = 0; 530 unsigned long cookie = 0;
566 int in_kernel = 1; 531 int in_kernel = 1;
567 sync_buffer_state state = sb_buffer_start; 532 sync_buffer_state state = sb_buffer_start;
568#ifndef CONFIG_OPROFILE_IBS
569 unsigned int i; 533 unsigned int i;
570 unsigned long available; 534 unsigned long available;
571#endif
572 535
573 mutex_lock(&buffer_mutex); 536 mutex_lock(&buffer_mutex);
574 537
575 add_cpu_switch(cpu); 538 add_cpu_switch(cpu);
576 539
577 /* Remember, only we can modify tail_pos */ 540 cpu_buffer_reset(cpu);
578 541 available = cpu_buffer_entries(cpu);
579#ifndef CONFIG_OPROFILE_IBS
580 available = get_slots(cpu_buf);
581 542
582 for (i = 0; i < available; ++i) { 543 for (i = 0; i < available; ++i) {
583#else 544 struct op_sample *s = cpu_buffer_read_entry(cpu);
584 while (get_slots(cpu_buf)) { 545 if (!s)
585#endif 546 break;
586 struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos];
587 547
588 if (is_code(s->eip)) { 548 if (is_code(s->eip)) {
589 if (s->event <= CPU_IS_KERNEL) { 549 switch (s->event) {
550 case 0:
551 case CPU_IS_KERNEL:
590 /* kernel/userspace switch */ 552 /* kernel/userspace switch */
591 in_kernel = s->event; 553 in_kernel = s->event;
592 if (state == sb_buffer_start) 554 if (state == sb_buffer_start)
593 state = sb_sample_start; 555 state = sb_sample_start;
594 add_kernel_ctx_switch(s->event); 556 add_kernel_ctx_switch(s->event);
595 } else if (s->event == CPU_TRACE_BEGIN) { 557 break;
558 case CPU_TRACE_BEGIN:
596 state = sb_bt_start; 559 state = sb_bt_start;
597 add_trace_begin(); 560 add_trace_begin();
561 break;
598#ifdef CONFIG_OPROFILE_IBS 562#ifdef CONFIG_OPROFILE_IBS
599 } else if (s->event == IBS_FETCH_BEGIN) { 563 case IBS_FETCH_BEGIN:
600 state = sb_bt_start; 564 state = sb_bt_start;
601 add_ibs_begin(cpu_buf, IBS_FETCH_CODE, mm); 565 add_ibs_begin(cpu, IBS_FETCH_CODE, mm);
602 } else if (s->event == IBS_OP_BEGIN) { 566 break;
567 case IBS_OP_BEGIN:
603 state = sb_bt_start; 568 state = sb_bt_start;
604 add_ibs_begin(cpu_buf, IBS_OP_CODE, mm); 569 add_ibs_begin(cpu, IBS_OP_CODE, mm);
570 break;
605#endif 571#endif
606 } else { 572 default:
607 struct mm_struct *oldmm = mm;
608
609 /* userspace context switch */ 573 /* userspace context switch */
574 oldmm = mm;
610 new = (struct task_struct *)s->event; 575 new = (struct task_struct *)s->event;
611
612 release_mm(oldmm); 576 release_mm(oldmm);
613 mm = take_tasks_mm(new); 577 mm = take_tasks_mm(new);
614 if (mm != oldmm) 578 if (mm != oldmm)
615 cookie = get_exec_dcookie(mm); 579 cookie = get_exec_dcookie(mm);
616 add_user_ctx_switch(new, cookie); 580 add_user_ctx_switch(new, cookie);
581 break;
617 } 582 }
618 } else if (state >= sb_bt_start && 583 } else if (state >= sb_bt_start &&
619 !add_sample(mm, s, in_kernel)) { 584 !add_sample(mm, s, in_kernel)) {
@@ -622,8 +587,6 @@ void sync_buffer(int cpu)
622 atomic_inc(&oprofile_stats.bt_lost_no_mapping); 587 atomic_inc(&oprofile_stats.bt_lost_no_mapping);
623 } 588 }
624 } 589 }
625
626 increment_tail(cpu_buf);
627 } 590 }
628 release_mm(mm); 591 release_mm(mm);
629 592