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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Kernel and userspace stack tracing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * License.  See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Copyright (C) 2001 - 2013 Tensilica Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Copyright (C) 2015 Cadence Design Systems Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/stacktrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/stacktrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /* Address of common_exception_return, used to check the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * transition from kernel to user space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) extern int common_exception_return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 			   int (*ufn)(struct stackframe *frame, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 			   void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	unsigned long windowstart = regs->windowstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	unsigned long windowbase = regs->windowbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	unsigned long a0 = regs->areg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned long a1 = regs->areg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	unsigned long pc = regs->pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct stackframe frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (!depth--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	frame.pc = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	frame.sp = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	    (IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	     !(regs->ps & PS_WOE_MASK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	/* Two steps:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	 * 1. Look through the register window for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	 * previous PCs in the call trace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	 * 2. Look on the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	/* Step 1.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	/* Rotate WINDOWSTART to move the bit corresponding to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	 * the current window to the bit #0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	/* Look for bits that are set, they correspond to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	 * valid windows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		if (windowstart & (1 << index)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			/* Get the PC from a0 and a1. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			pc = MAKE_PC_FROM_RA(a0, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			/* Read a0 and a1 from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			 * corresponding position in AREGs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 			a0 = regs->areg[index * 4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			a1 = regs->areg[index * 4 + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			frame.pc = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			frame.sp = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	/* Step 2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	/* We are done with the register window, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * look through the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (!depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/* Start from the a1 register. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	/* a1 = regs->areg[1]; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	while (a0 != 0 && depth--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		pc = MAKE_PC_FROM_RA(a0, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		/* Check if the region is OK to access. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		if (!access_ok(&SPILL_SLOT(a1, 0), 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		/* Copy a1, a0 from user space stack frame. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		    __get_user(a1, &SPILL_SLOT(a1, 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		frame.pc = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		frame.sp = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) EXPORT_SYMBOL(xtensa_backtrace_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			     int (*kfn)(struct stackframe *frame, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			     int (*ufn)(struct stackframe *frame, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			     void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		regs->depc : regs->pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	unsigned long sp_start, sp_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	unsigned long a0 = regs->areg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	unsigned long a1 = regs->areg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	sp_start = a1 & ~(THREAD_SIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	sp_end = sp_start + THREAD_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* Spill the register window to the stack first. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	spill_registers();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/* Read the stack frames one by one and create the PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	 * from the a0 and a1 registers saved there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	while (a1 > sp_start && a1 < sp_end && depth--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		struct stackframe frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		frame.pc = pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		frame.sp = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		if (kernel_text_address(pc) && kfn(&frame, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		if (pc == (unsigned long)&common_exception_return) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			regs = (struct pt_regs *)a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			if (user_mode(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 				if (ufn == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				xtensa_backtrace_user(regs, depth, ufn, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			a0 = regs->areg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			a1 = regs->areg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		sp_start = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		pc = MAKE_PC_FROM_RA(a0, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		a0 = SPILL_SLOT(a1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		a1 = SPILL_SLOT(a1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) EXPORT_SYMBOL(xtensa_backtrace_kernel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) void walk_stackframe(unsigned long *sp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		int (*fn)(struct stackframe *frame, void *data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	unsigned long a0, a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	unsigned long sp_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	a1 = (unsigned long)sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	sp_end = ALIGN(a1, THREAD_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	spill_registers();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	while (a1 < sp_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		struct stackframe frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		sp = (unsigned long *)a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		a0 = SPILL_SLOT(a1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		a1 = SPILL_SLOT(a1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		if (a1 <= (unsigned long)sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		frame.pc = MAKE_PC_FROM_RA(a0, a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		frame.sp = a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (fn(&frame, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #ifdef CONFIG_STACKTRACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct stack_trace_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	struct stack_trace *trace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	unsigned skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int stack_trace_cb(struct stackframe *frame, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct stack_trace_data *trace_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct stack_trace *trace = trace_data->trace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (trace_data->skip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		--trace_data->skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	if (!kernel_text_address(frame->pc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	trace->entries[trace->nr_entries++] = frame->pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	return trace->nr_entries >= trace->max_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	struct stack_trace_data trace_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		.trace = trace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		.skip = trace->skip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void save_stack_trace(struct stack_trace *trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	save_stack_trace_tsk(current, trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) EXPORT_SYMBOL_GPL(save_stack_trace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #ifdef CONFIG_FRAME_POINTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct return_addr_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	unsigned skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int return_address_cb(struct stackframe *frame, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	struct return_addr_data *r = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if (r->skip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		--r->skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	if (!kernel_text_address(frame->pc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	r->addr = frame->pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  * level == 0 is for the return address from the caller of this function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  * not from this function itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned long return_address(unsigned level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	struct return_addr_data r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		.skip = level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	return r.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) EXPORT_SYMBOL(return_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #endif