^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Performance counter callchain support - powerpc architecture code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright © 2009 Paul Mackerras, IBM Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/sigcontext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/ucontext.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/vdso.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/pte-walk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "callchain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "../kernel/ppc32.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #else /* CONFIG_PPC64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define __SIGNAL_FRAMESIZE32 __SIGNAL_FRAMESIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define sigcontext32 sigcontext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define mcontext32 mcontext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define ucontext32 ucontext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define compat_siginfo_t struct siginfo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #endif /* CONFIG_PPC64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static int read_user_stack_32(const unsigned int __user *ptr, unsigned int *ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return __read_user_stack(ptr, ret, sizeof(*ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Layout for non-RT signal frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct signal_frame_32 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) char dummy[__SIGNAL_FRAMESIZE32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct sigcontext32 sctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct mcontext32 mctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int abigap[56];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Layout for RT signal frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct rt_signal_frame_32 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) char dummy[__SIGNAL_FRAMESIZE32 + 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) compat_siginfo_t info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct ucontext32 uc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int abigap[56];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int is_sigreturn_32_address(unsigned int nip, unsigned int fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (nip == fp + offsetof(struct signal_frame_32, mctx.mc_pad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (vdso32_sigtramp && current->mm->context.vdso_base &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) nip == current->mm->context.vdso_base + vdso32_sigtramp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int is_rt_sigreturn_32_address(unsigned int nip, unsigned int fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (nip == fp + offsetof(struct rt_signal_frame_32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) uc.uc_mcontext.mc_pad))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (vdso32_rt_sigtramp && current->mm->context.vdso_base &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) nip == current->mm->context.vdso_base + vdso32_rt_sigtramp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int sane_signal_32_frame(unsigned int sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct signal_frame_32 __user *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sf = (struct signal_frame_32 __user *) (unsigned long) sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (read_user_stack_32((unsigned int __user *) &sf->sctx.regs, ®s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return regs == (unsigned long) &sf->mctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int sane_rt_signal_32_frame(unsigned int sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct rt_signal_frame_32 __user *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned int regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) sf = (struct rt_signal_frame_32 __user *) (unsigned long) sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (read_user_stack_32((unsigned int __user *) &sf->uc.uc_regs, ®s))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return regs == (unsigned long) &sf->uc.uc_mcontext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static unsigned int __user *signal_frame_32_regs(unsigned int sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int next_sp, unsigned int next_ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct mcontext32 __user *mctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct signal_frame_32 __user *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct rt_signal_frame_32 __user *rt_sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * Note: the next_sp - sp >= signal frame size check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * is true when next_sp < sp, for example, when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * transitioning from an alternate signal stack to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * normal stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (next_sp - sp >= sizeof(struct signal_frame_32) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) is_sigreturn_32_address(next_ip, sp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) sane_signal_32_frame(sp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sf = (struct signal_frame_32 __user *) (unsigned long) sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) mctx = &sf->mctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!mctx && next_sp - sp >= sizeof(struct rt_signal_frame_32) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) is_rt_sigreturn_32_address(next_ip, sp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) sane_rt_signal_32_frame(sp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rt_sf = (struct rt_signal_frame_32 __user *) (unsigned long) sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mctx = &rt_sf->uc.uc_mcontext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!mctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return mctx->mc_gregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned int sp, next_sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) unsigned int next_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned int lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) long level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned int __user *fp, *uregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) next_ip = perf_instruction_pointer(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) lr = regs->link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) sp = regs->gpr[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) perf_callchain_store(entry, next_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) while (entry->nr < entry->max_stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fp = (unsigned int __user *) (unsigned long) sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (invalid_user_sp(sp) || read_user_stack_32(fp, &next_sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (level > 0 && read_user_stack_32(&fp[1], &next_ip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) uregs = signal_frame_32_regs(sp, next_sp, next_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!uregs && level <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) uregs = signal_frame_32_regs(sp, next_sp, lr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (uregs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * This looks like an signal frame, so restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * the stack trace with the values in it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (read_user_stack_32(&uregs[PT_NIP], &next_ip) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) read_user_stack_32(&uregs[PT_LNK], &lr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) read_user_stack_32(&uregs[PT_R1], &sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) perf_callchain_store_context(entry, PERF_CONTEXT_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) perf_callchain_store(entry, next_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (level == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) next_ip = lr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) perf_callchain_store(entry, next_ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ++level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) sp = next_sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }