Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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, &regs))
^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, &regs))
^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) }