1/** 2 * @file common.c 3 * 4 * @remark Copyright 2004 Oprofile Authors 5 * @remark Copyright 2010 ARM Ltd. 6 * @remark Read the file COPYING 7 * 8 * @author Zwane Mwaikambo 9 * @author Will Deacon [move to perf] 10 */ 11 12#include <linux/cpumask.h> 13#include <linux/init.h> 14#include <linux/mutex.h> 15#include <linux/oprofile.h> 16#include <linux/perf_event.h> 17#include <linux/platform_device.h> 18#include <linux/slab.h> 19#include <asm/stacktrace.h> 20#include <linux/uaccess.h> 21 22#include <asm/perf_event.h> 23#include <asm/ptrace.h> 24 25#ifdef CONFIG_HW_PERF_EVENTS 26 27/* 28 * OProfile has a curious naming scheme for the ARM PMUs, but they are 29 * part of the user ABI so we need to map from the perf PMU name for 30 * supported PMUs. 31 */ 32static struct op_perf_name { 33 char *perf_name; 34 char *op_name; 35} op_perf_name_map[] = { 36 { "armv5_xscale1", "arm/xscale1" }, 37 { "armv5_xscale2", "arm/xscale2" }, 38 { "armv6_1136", "arm/armv6" }, 39 { "armv6_1156", "arm/armv6" }, 40 { "armv6_1176", "arm/armv6" }, 41 { "armv6_11mpcore", "arm/mpcore" }, 42 { "armv7_cortex_a8", "arm/armv7" }, 43 { "armv7_cortex_a9", "arm/armv7-ca9" }, 44}; 45 46char *op_name_from_perf_id(void) 47{ 48 int i; 49 struct op_perf_name names; 50 const char *perf_name = perf_pmu_name(); 51 52 for (i = 0; i < ARRAY_SIZE(op_perf_name_map); ++i) { 53 names = op_perf_name_map[i]; 54 if (!strcmp(names.perf_name, perf_name)) 55 return names.op_name; 56 } 57 58 return NULL; 59} 60#endif 61 62static int report_trace(struct stackframe *frame, void *d) 63{ 64 unsigned int *depth = d; 65 66 if (*depth) { 67 oprofile_add_trace(frame->pc); 68 (*depth)--; 69 } 70 71 return *depth == 0; 72} 73 74/* 75 * The registers we're interested in are at the end of the variable 76 * length saved register structure. The fp points at the end of this 77 * structure so the address of this struct is: 78 * (struct frame_tail *)(xxx->fp)-1 79 */ 80struct frame_tail { 81 struct frame_tail *fp; 82 unsigned long sp; 83 unsigned long lr; 84} __attribute__((packed)); 85 86static struct frame_tail* user_backtrace(struct frame_tail *tail) 87{ 88 struct frame_tail buftail[2]; 89 90 /* Also check accessibility of one struct frame_tail beyond */ 91 if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) 92 return NULL; 93 if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) 94 return NULL; 95 96 oprofile_add_trace(buftail[0].lr); 97 98 /* frame pointers should strictly progress back up the stack 99 * (towards higher addresses) */ 100 if (tail + 1 >= buftail[0].fp) 101 return NULL; 102 103 return buftail[0].fp-1; 104} 105 106static void arm_backtrace(struct pt_regs * const regs, unsigned int depth) 107{ 108 struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1; 109 110 if (!user_mode(regs)) { 111 struct stackframe frame; 112 arm_get_current_stackframe(regs, &frame); 113 walk_stackframe(&frame, report_trace, &depth); 114 return; 115 } 116 117 while (depth-- && tail && !((unsigned long) tail & 3)) 118 tail = user_backtrace(tail); 119} 120 121int __init oprofile_arch_init(struct oprofile_operations *ops) 122{ 123 /* provide backtrace support also in timer mode: */ 124 ops->backtrace = arm_backtrace; 125 126 return oprofile_perf_init(ops); 127} 128 129void oprofile_arch_exit(void) 130{ 131 oprofile_perf_exit(); 132} 133