root/arch/mips/kernel/perf_event.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. save_raw_perf_callchain
  2. perf_callchain_kernel

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Linux performance counter support for MIPS.
   4  *
   5  * Copyright (C) 2010 MIPS Technologies, Inc.
   6  * Author: Deng-Cheng Zhu
   7  *
   8  * This code is based on the implementation for ARM, which is in turn
   9  * based on the sparc64 perf event code and the x86 code. Performance
  10  * counter access is based on the MIPS Oprofile code. And the callchain
  11  * support references the code of MIPS stacktrace.c.
  12  */
  13 
  14 #include <linux/perf_event.h>
  15 #include <linux/sched/task_stack.h>
  16 
  17 #include <asm/stacktrace.h>
  18 
  19 /* Callchain handling code. */
  20 
  21 /*
  22  * Leave userspace callchain empty for now. When we find a way to trace
  23  * the user stack callchains, we will add it here.
  24  */
  25 
  26 static void save_raw_perf_callchain(struct perf_callchain_entry_ctx *entry,
  27                                     unsigned long reg29)
  28 {
  29         unsigned long *sp = (unsigned long *)reg29;
  30         unsigned long addr;
  31 
  32         while (!kstack_end(sp)) {
  33                 addr = *sp++;
  34                 if (__kernel_text_address(addr)) {
  35                         perf_callchain_store(entry, addr);
  36                         if (entry->nr >= entry->max_stack)
  37                                 break;
  38                 }
  39         }
  40 }
  41 
  42 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
  43                            struct pt_regs *regs)
  44 {
  45         unsigned long sp = regs->regs[29];
  46 #ifdef CONFIG_KALLSYMS
  47         unsigned long ra = regs->regs[31];
  48         unsigned long pc = regs->cp0_epc;
  49 
  50         if (raw_show_trace || !__kernel_text_address(pc)) {
  51                 unsigned long stack_page =
  52                         (unsigned long)task_stack_page(current);
  53                 if (stack_page && sp >= stack_page &&
  54                     sp <= stack_page + THREAD_SIZE - 32)
  55                         save_raw_perf_callchain(entry, sp);
  56                 return;
  57         }
  58         do {
  59                 perf_callchain_store(entry, pc);
  60                 if (entry->nr >= entry->max_stack)
  61                         break;
  62                 pc = unwind_stack(current, &sp, pc, &ra);
  63         } while (pc);
  64 #else
  65         save_raw_perf_callchain(entry, sp);
  66 #endif
  67 }

/* [<][>][^][v][top][bottom][index][help] */