diff options
-rw-r--r-- | arch/mips/kernel/perf_event.c | 63 |
1 files changed, 6 insertions, 57 deletions
diff --git a/arch/mips/kernel/perf_event.c b/arch/mips/kernel/perf_event.c index 3d55761146e5..8f7d2f84d095 100644 --- a/arch/mips/kernel/perf_event.c +++ b/arch/mips/kernel/perf_event.c | |||
@@ -534,21 +534,13 @@ handle_associated_event(struct cpu_hw_events *cpuc, | |||
534 | #include "perf_event_mipsxx.c" | 534 | #include "perf_event_mipsxx.c" |
535 | 535 | ||
536 | /* Callchain handling code. */ | 536 | /* Callchain handling code. */ |
537 | static inline void | ||
538 | callchain_store(struct perf_callchain_entry *entry, | ||
539 | u64 ip) | ||
540 | { | ||
541 | if (entry->nr < PERF_MAX_STACK_DEPTH) | ||
542 | entry->ip[entry->nr++] = ip; | ||
543 | } | ||
544 | 537 | ||
545 | /* | 538 | /* |
546 | * Leave userspace callchain empty for now. When we find a way to trace | 539 | * Leave userspace callchain empty for now. When we find a way to trace |
547 | * the user stack callchains, we add here. | 540 | * the user stack callchains, we add here. |
548 | */ | 541 | */ |
549 | static void | 542 | void perf_callchain_user(struct perf_callchain_entry *entry, |
550 | perf_callchain_user(struct pt_regs *regs, | 543 | struct pt_regs *regs) |
551 | struct perf_callchain_entry *entry) | ||
552 | { | 544 | { |
553 | } | 545 | } |
554 | 546 | ||
@@ -561,23 +553,21 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, | |||
561 | while (!kstack_end(sp)) { | 553 | while (!kstack_end(sp)) { |
562 | addr = *sp++; | 554 | addr = *sp++; |
563 | if (__kernel_text_address(addr)) { | 555 | if (__kernel_text_address(addr)) { |
564 | callchain_store(entry, addr); | 556 | perf_callchain_store(entry, addr); |
565 | if (entry->nr >= PERF_MAX_STACK_DEPTH) | 557 | if (entry->nr >= PERF_MAX_STACK_DEPTH) |
566 | break; | 558 | break; |
567 | } | 559 | } |
568 | } | 560 | } |
569 | } | 561 | } |
570 | 562 | ||
571 | static void | 563 | void perf_callchain_kernel(struct perf_callchain_entry *entry, |
572 | perf_callchain_kernel(struct pt_regs *regs, | 564 | struct pt_regs *regs) |
573 | struct perf_callchain_entry *entry) | ||
574 | { | 565 | { |
575 | unsigned long sp = regs->regs[29]; | 566 | unsigned long sp = regs->regs[29]; |
576 | #ifdef CONFIG_KALLSYMS | 567 | #ifdef CONFIG_KALLSYMS |
577 | unsigned long ra = regs->regs[31]; | 568 | unsigned long ra = regs->regs[31]; |
578 | unsigned long pc = regs->cp0_epc; | 569 | unsigned long pc = regs->cp0_epc; |
579 | 570 | ||
580 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
581 | if (raw_show_trace || !__kernel_text_address(pc)) { | 571 | if (raw_show_trace || !__kernel_text_address(pc)) { |
582 | unsigned long stack_page = | 572 | unsigned long stack_page = |
583 | (unsigned long)task_stack_page(current); | 573 | (unsigned long)task_stack_page(current); |
@@ -587,53 +577,12 @@ perf_callchain_kernel(struct pt_regs *regs, | |||
587 | return; | 577 | return; |
588 | } | 578 | } |
589 | do { | 579 | do { |
590 | callchain_store(entry, pc); | 580 | perf_callchain_store(entry, pc); |
591 | if (entry->nr >= PERF_MAX_STACK_DEPTH) | 581 | if (entry->nr >= PERF_MAX_STACK_DEPTH) |
592 | break; | 582 | break; |
593 | pc = unwind_stack(current, &sp, pc, &ra); | 583 | pc = unwind_stack(current, &sp, pc, &ra); |
594 | } while (pc); | 584 | } while (pc); |
595 | #else | 585 | #else |
596 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
597 | save_raw_perf_callchain(entry, sp); | 586 | save_raw_perf_callchain(entry, sp); |
598 | #endif | 587 | #endif |
599 | } | 588 | } |
600 | |||
601 | static void | ||
602 | perf_do_callchain(struct pt_regs *regs, | ||
603 | struct perf_callchain_entry *entry) | ||
604 | { | ||
605 | int is_user; | ||
606 | |||
607 | if (!regs) | ||
608 | return; | ||
609 | |||
610 | is_user = user_mode(regs); | ||
611 | |||
612 | if (!current || !current->pid) | ||
613 | return; | ||
614 | |||
615 | if (is_user && current->state != TASK_RUNNING) | ||
616 | return; | ||
617 | |||
618 | if (!is_user) { | ||
619 | perf_callchain_kernel(regs, entry); | ||
620 | if (current->mm) | ||
621 | regs = task_pt_regs(current); | ||
622 | else | ||
623 | regs = NULL; | ||
624 | } | ||
625 | if (regs) | ||
626 | perf_callchain_user(regs, entry); | ||
627 | } | ||
628 | |||
629 | static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry); | ||
630 | |||
631 | struct perf_callchain_entry * | ||
632 | perf_callchain(struct pt_regs *regs) | ||
633 | { | ||
634 | struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry); | ||
635 | |||
636 | entry->nr = 0; | ||
637 | perf_do_callchain(regs, entry); | ||
638 | return entry; | ||
639 | } | ||