1*9251f904SBorislav Petkov /* 2*9251f904SBorislav Petkov * Performance events callchain code, extracted from core.c: 3*9251f904SBorislav Petkov * 4*9251f904SBorislav Petkov * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> 5*9251f904SBorislav Petkov * Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar 6*9251f904SBorislav Petkov * Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 7*9251f904SBorislav Petkov * Copyright � 2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 8*9251f904SBorislav Petkov * 9*9251f904SBorislav Petkov * For licensing details see kernel-base/COPYING 10*9251f904SBorislav Petkov */ 11*9251f904SBorislav Petkov 12*9251f904SBorislav Petkov #include <linux/perf_event.h> 13*9251f904SBorislav Petkov #include <linux/slab.h> 14*9251f904SBorislav Petkov #include "internal.h" 15*9251f904SBorislav Petkov 16*9251f904SBorislav Petkov struct callchain_cpus_entries { 17*9251f904SBorislav Petkov struct rcu_head rcu_head; 18*9251f904SBorislav Petkov struct perf_callchain_entry *cpu_entries[0]; 19*9251f904SBorislav Petkov }; 20*9251f904SBorislav Petkov 21*9251f904SBorislav Petkov static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]); 22*9251f904SBorislav Petkov static atomic_t nr_callchain_events; 23*9251f904SBorislav Petkov static DEFINE_MUTEX(callchain_mutex); 24*9251f904SBorislav Petkov static struct callchain_cpus_entries *callchain_cpus_entries; 25*9251f904SBorislav Petkov 26*9251f904SBorislav Petkov 27*9251f904SBorislav Petkov __weak void perf_callchain_kernel(struct perf_callchain_entry *entry, 28*9251f904SBorislav Petkov struct pt_regs *regs) 29*9251f904SBorislav Petkov { 30*9251f904SBorislav Petkov } 31*9251f904SBorislav Petkov 32*9251f904SBorislav Petkov __weak void perf_callchain_user(struct perf_callchain_entry *entry, 33*9251f904SBorislav Petkov struct pt_regs *regs) 34*9251f904SBorislav Petkov { 35*9251f904SBorislav Petkov } 36*9251f904SBorislav Petkov 37*9251f904SBorislav Petkov static void release_callchain_buffers_rcu(struct rcu_head *head) 38*9251f904SBorislav Petkov { 39*9251f904SBorislav Petkov struct callchain_cpus_entries *entries; 40*9251f904SBorislav Petkov int cpu; 41*9251f904SBorislav Petkov 42*9251f904SBorislav Petkov entries = container_of(head, struct callchain_cpus_entries, rcu_head); 43*9251f904SBorislav Petkov 44*9251f904SBorislav Petkov for_each_possible_cpu(cpu) 45*9251f904SBorislav Petkov kfree(entries->cpu_entries[cpu]); 46*9251f904SBorislav Petkov 47*9251f904SBorislav Petkov kfree(entries); 48*9251f904SBorislav Petkov } 49*9251f904SBorislav Petkov 50*9251f904SBorislav Petkov static void release_callchain_buffers(void) 51*9251f904SBorislav Petkov { 52*9251f904SBorislav Petkov struct callchain_cpus_entries *entries; 53*9251f904SBorislav Petkov 54*9251f904SBorislav Petkov entries = callchain_cpus_entries; 55*9251f904SBorislav Petkov rcu_assign_pointer(callchain_cpus_entries, NULL); 56*9251f904SBorislav Petkov call_rcu(&entries->rcu_head, release_callchain_buffers_rcu); 57*9251f904SBorislav Petkov } 58*9251f904SBorislav Petkov 59*9251f904SBorislav Petkov static int alloc_callchain_buffers(void) 60*9251f904SBorislav Petkov { 61*9251f904SBorislav Petkov int cpu; 62*9251f904SBorislav Petkov int size; 63*9251f904SBorislav Petkov struct callchain_cpus_entries *entries; 64*9251f904SBorislav Petkov 65*9251f904SBorislav Petkov /* 66*9251f904SBorislav Petkov * We can't use the percpu allocation API for data that can be 67*9251f904SBorislav Petkov * accessed from NMI. Use a temporary manual per cpu allocation 68*9251f904SBorislav Petkov * until that gets sorted out. 69*9251f904SBorislav Petkov */ 70*9251f904SBorislav Petkov size = offsetof(struct callchain_cpus_entries, cpu_entries[nr_cpu_ids]); 71*9251f904SBorislav Petkov 72*9251f904SBorislav Petkov entries = kzalloc(size, GFP_KERNEL); 73*9251f904SBorislav Petkov if (!entries) 74*9251f904SBorislav Petkov return -ENOMEM; 75*9251f904SBorislav Petkov 76*9251f904SBorislav Petkov size = sizeof(struct perf_callchain_entry) * PERF_NR_CONTEXTS; 77*9251f904SBorislav Petkov 78*9251f904SBorislav Petkov for_each_possible_cpu(cpu) { 79*9251f904SBorislav Petkov entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL, 80*9251f904SBorislav Petkov cpu_to_node(cpu)); 81*9251f904SBorislav Petkov if (!entries->cpu_entries[cpu]) 82*9251f904SBorislav Petkov goto fail; 83*9251f904SBorislav Petkov } 84*9251f904SBorislav Petkov 85*9251f904SBorislav Petkov rcu_assign_pointer(callchain_cpus_entries, entries); 86*9251f904SBorislav Petkov 87*9251f904SBorislav Petkov return 0; 88*9251f904SBorislav Petkov 89*9251f904SBorislav Petkov fail: 90*9251f904SBorislav Petkov for_each_possible_cpu(cpu) 91*9251f904SBorislav Petkov kfree(entries->cpu_entries[cpu]); 92*9251f904SBorislav Petkov kfree(entries); 93*9251f904SBorislav Petkov 94*9251f904SBorislav Petkov return -ENOMEM; 95*9251f904SBorislav Petkov } 96*9251f904SBorislav Petkov 97*9251f904SBorislav Petkov int get_callchain_buffers(void) 98*9251f904SBorislav Petkov { 99*9251f904SBorislav Petkov int err = 0; 100*9251f904SBorislav Petkov int count; 101*9251f904SBorislav Petkov 102*9251f904SBorislav Petkov mutex_lock(&callchain_mutex); 103*9251f904SBorislav Petkov 104*9251f904SBorislav Petkov count = atomic_inc_return(&nr_callchain_events); 105*9251f904SBorislav Petkov if (WARN_ON_ONCE(count < 1)) { 106*9251f904SBorislav Petkov err = -EINVAL; 107*9251f904SBorislav Petkov goto exit; 108*9251f904SBorislav Petkov } 109*9251f904SBorislav Petkov 110*9251f904SBorislav Petkov if (count > 1) { 111*9251f904SBorislav Petkov /* If the allocation failed, give up */ 112*9251f904SBorislav Petkov if (!callchain_cpus_entries) 113*9251f904SBorislav Petkov err = -ENOMEM; 114*9251f904SBorislav Petkov goto exit; 115*9251f904SBorislav Petkov } 116*9251f904SBorislav Petkov 117*9251f904SBorislav Petkov err = alloc_callchain_buffers(); 118*9251f904SBorislav Petkov if (err) 119*9251f904SBorislav Petkov release_callchain_buffers(); 120*9251f904SBorislav Petkov exit: 121*9251f904SBorislav Petkov mutex_unlock(&callchain_mutex); 122*9251f904SBorislav Petkov 123*9251f904SBorislav Petkov return err; 124*9251f904SBorislav Petkov } 125*9251f904SBorislav Petkov 126*9251f904SBorislav Petkov void put_callchain_buffers(void) 127*9251f904SBorislav Petkov { 128*9251f904SBorislav Petkov if (atomic_dec_and_mutex_lock(&nr_callchain_events, &callchain_mutex)) { 129*9251f904SBorislav Petkov release_callchain_buffers(); 130*9251f904SBorislav Petkov mutex_unlock(&callchain_mutex); 131*9251f904SBorislav Petkov } 132*9251f904SBorislav Petkov } 133*9251f904SBorislav Petkov 134*9251f904SBorislav Petkov static struct perf_callchain_entry *get_callchain_entry(int *rctx) 135*9251f904SBorislav Petkov { 136*9251f904SBorislav Petkov int cpu; 137*9251f904SBorislav Petkov struct callchain_cpus_entries *entries; 138*9251f904SBorislav Petkov 139*9251f904SBorislav Petkov *rctx = get_recursion_context(__get_cpu_var(callchain_recursion)); 140*9251f904SBorislav Petkov if (*rctx == -1) 141*9251f904SBorislav Petkov return NULL; 142*9251f904SBorislav Petkov 143*9251f904SBorislav Petkov entries = rcu_dereference(callchain_cpus_entries); 144*9251f904SBorislav Petkov if (!entries) 145*9251f904SBorislav Petkov return NULL; 146*9251f904SBorislav Petkov 147*9251f904SBorislav Petkov cpu = smp_processor_id(); 148*9251f904SBorislav Petkov 149*9251f904SBorislav Petkov return &entries->cpu_entries[cpu][*rctx]; 150*9251f904SBorislav Petkov } 151*9251f904SBorislav Petkov 152*9251f904SBorislav Petkov static void 153*9251f904SBorislav Petkov put_callchain_entry(int rctx) 154*9251f904SBorislav Petkov { 155*9251f904SBorislav Petkov put_recursion_context(__get_cpu_var(callchain_recursion), rctx); 156*9251f904SBorislav Petkov } 157*9251f904SBorislav Petkov 158*9251f904SBorislav Petkov struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) 159*9251f904SBorislav Petkov { 160*9251f904SBorislav Petkov int rctx; 161*9251f904SBorislav Petkov struct perf_callchain_entry *entry; 162*9251f904SBorislav Petkov 163*9251f904SBorislav Petkov 164*9251f904SBorislav Petkov entry = get_callchain_entry(&rctx); 165*9251f904SBorislav Petkov if (rctx == -1) 166*9251f904SBorislav Petkov return NULL; 167*9251f904SBorislav Petkov 168*9251f904SBorislav Petkov if (!entry) 169*9251f904SBorislav Petkov goto exit_put; 170*9251f904SBorislav Petkov 171*9251f904SBorislav Petkov entry->nr = 0; 172*9251f904SBorislav Petkov 173*9251f904SBorislav Petkov if (!user_mode(regs)) { 174*9251f904SBorislav Petkov perf_callchain_store(entry, PERF_CONTEXT_KERNEL); 175*9251f904SBorislav Petkov perf_callchain_kernel(entry, regs); 176*9251f904SBorislav Petkov if (current->mm) 177*9251f904SBorislav Petkov regs = task_pt_regs(current); 178*9251f904SBorislav Petkov else 179*9251f904SBorislav Petkov regs = NULL; 180*9251f904SBorislav Petkov } 181*9251f904SBorislav Petkov 182*9251f904SBorislav Petkov if (regs) { 183*9251f904SBorislav Petkov perf_callchain_store(entry, PERF_CONTEXT_USER); 184*9251f904SBorislav Petkov perf_callchain_user(entry, regs); 185*9251f904SBorislav Petkov } 186*9251f904SBorislav Petkov 187*9251f904SBorislav Petkov exit_put: 188*9251f904SBorislav Petkov put_callchain_entry(rctx); 189*9251f904SBorislav Petkov 190*9251f904SBorislav Petkov return entry; 191*9251f904SBorislav Petkov } 192