1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Performance counter callchain support - powerpc architecture code 4 * 5 * Copyright © 2009 Paul Mackerras, IBM Corporation. 6 */ 7 #include <linux/kernel.h> 8 #include <linux/sched.h> 9 #include <linux/perf_event.h> 10 #include <linux/percpu.h> 11 #include <linux/uaccess.h> 12 #include <linux/mm.h> 13 #include <asm/ptrace.h> 14 #include <asm/sigcontext.h> 15 #include <asm/ucontext.h> 16 #include <asm/vdso.h> 17 #include <asm/pte-walk.h> 18 19 #include "callchain.h" 20 21 /* 22 * On 64-bit we don't want to invoke hash_page on user addresses from 23 * interrupt context, so if the access faults, we read the page tables 24 * to find which page (if any) is mapped and access it directly. 25 */ 26 int read_user_stack_slow(void __user *ptr, void *buf, int nb) 27 { 28 29 unsigned long addr = (unsigned long) ptr; 30 unsigned long offset; 31 struct page *page; 32 void *kaddr; 33 34 if (get_user_page_fast_only(addr, FOLL_WRITE, &page)) { 35 kaddr = page_address(page); 36 37 /* align address to page boundary */ 38 offset = addr & ~PAGE_MASK; 39 40 memcpy(buf, kaddr + offset, nb); 41 put_page(page); 42 return 0; 43 } 44 return -EFAULT; 45 } 46 47 static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) 48 { 49 if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned long) || 50 ((unsigned long)ptr & 7)) 51 return -EFAULT; 52 53 if (!copy_from_user_nofault(ret, ptr, sizeof(*ret))) 54 return 0; 55 56 return read_user_stack_slow(ptr, ret, 8); 57 } 58 59 /* 60 * 64-bit user processes use the same stack frame for RT and non-RT signals. 61 */ 62 struct signal_frame_64 { 63 char dummy[__SIGNAL_FRAMESIZE]; 64 struct ucontext uc; 65 unsigned long unused[2]; 66 unsigned int tramp[6]; 67 struct siginfo *pinfo; 68 void *puc; 69 struct siginfo info; 70 char abigap[288]; 71 }; 72 73 static int is_sigreturn_64_address(unsigned long nip, unsigned long fp) 74 { 75 if (nip == fp + offsetof(struct signal_frame_64, tramp)) 76 return 1; 77 if (vdso64_rt_sigtramp && current->mm->context.vdso_base && 78 nip == current->mm->context.vdso_base + vdso64_rt_sigtramp) 79 return 1; 80 return 0; 81 } 82 83 /* 84 * Do some sanity checking on the signal frame pointed to by sp. 85 * We check the pinfo and puc pointers in the frame. 86 */ 87 static int sane_signal_64_frame(unsigned long sp) 88 { 89 struct signal_frame_64 __user *sf; 90 unsigned long pinfo, puc; 91 92 sf = (struct signal_frame_64 __user *) sp; 93 if (read_user_stack_64((unsigned long __user *) &sf->pinfo, &pinfo) || 94 read_user_stack_64((unsigned long __user *) &sf->puc, &puc)) 95 return 0; 96 return pinfo == (unsigned long) &sf->info && 97 puc == (unsigned long) &sf->uc; 98 } 99 100 void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, 101 struct pt_regs *regs) 102 { 103 unsigned long sp, next_sp; 104 unsigned long next_ip; 105 unsigned long lr; 106 long level = 0; 107 struct signal_frame_64 __user *sigframe; 108 unsigned long __user *fp, *uregs; 109 110 next_ip = perf_instruction_pointer(regs); 111 lr = regs->link; 112 sp = regs->gpr[1]; 113 perf_callchain_store(entry, next_ip); 114 115 while (entry->nr < entry->max_stack) { 116 fp = (unsigned long __user *) sp; 117 if (invalid_user_sp(sp) || read_user_stack_64(fp, &next_sp)) 118 return; 119 if (level > 0 && read_user_stack_64(&fp[2], &next_ip)) 120 return; 121 122 /* 123 * Note: the next_sp - sp >= signal frame size check 124 * is true when next_sp < sp, which can happen when 125 * transitioning from an alternate signal stack to the 126 * normal stack. 127 */ 128 if (next_sp - sp >= sizeof(struct signal_frame_64) && 129 (is_sigreturn_64_address(next_ip, sp) || 130 (level <= 1 && is_sigreturn_64_address(lr, sp))) && 131 sane_signal_64_frame(sp)) { 132 /* 133 * This looks like an signal frame 134 */ 135 sigframe = (struct signal_frame_64 __user *) sp; 136 uregs = sigframe->uc.uc_mcontext.gp_regs; 137 if (read_user_stack_64(&uregs[PT_NIP], &next_ip) || 138 read_user_stack_64(&uregs[PT_LNK], &lr) || 139 read_user_stack_64(&uregs[PT_R1], &sp)) 140 return; 141 level = 0; 142 perf_callchain_store_context(entry, PERF_CONTEXT_USER); 143 perf_callchain_store(entry, next_ip); 144 continue; 145 } 146 147 if (level == 0) 148 next_ip = lr; 149 perf_callchain_store(entry, next_ip); 150 ++level; 151 sp = next_sp; 152 } 153 } 154