| // SPDX-License-Identifier: GPL-2.0 | 
 | // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. | 
 |  | 
 | #include <linux/ptrace.h> | 
 |  | 
 | int kstack_depth_to_print = 48; | 
 |  | 
 | void show_trace(unsigned long *stack) | 
 | { | 
 | 	unsigned long *endstack; | 
 | 	unsigned long addr; | 
 | 	int i; | 
 |  | 
 | 	pr_info("Call Trace:\n"); | 
 | 	addr = (unsigned long)stack + THREAD_SIZE - 1; | 
 | 	endstack = (unsigned long *)(addr & -THREAD_SIZE); | 
 | 	i = 0; | 
 | 	while (stack + 1 <= endstack) { | 
 | 		addr = *stack++; | 
 | 		/* | 
 | 		 * If the address is either in the text segment of the | 
 | 		 * kernel, or in the region which contains vmalloc'ed | 
 | 		 * memory, it *may* be the address of a calling | 
 | 		 * routine; if so, print it so that someone tracing | 
 | 		 * down the cause of the crash will be able to figure | 
 | 		 * out the call path that was taken. | 
 | 		 */ | 
 | 		if (__kernel_text_address(addr)) { | 
 | #ifndef CONFIG_KALLSYMS | 
 | 			if (i % 5 == 0) | 
 | 				pr_cont("\n       "); | 
 | #endif | 
 | 			pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr); | 
 | 			i++; | 
 | 		} | 
 | 	} | 
 | 	pr_cont("\n"); | 
 | } | 
 |  | 
 | void show_stack(struct task_struct *task, unsigned long *stack) | 
 | { | 
 | 	unsigned long *p; | 
 | 	unsigned long *endstack; | 
 | 	int i; | 
 |  | 
 | 	if (!stack) { | 
 | 		if (task) | 
 | 			stack = (unsigned long *)task->thread.esp0; | 
 | 		else | 
 | 			stack = (unsigned long *)&stack; | 
 | 	} | 
 | 	endstack = (unsigned long *) | 
 | 		(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); | 
 |  | 
 | 	pr_info("Stack from %08lx:", (unsigned long)stack); | 
 | 	p = stack; | 
 | 	for (i = 0; i < kstack_depth_to_print; i++) { | 
 | 		if (p + 1 > endstack) | 
 | 			break; | 
 | 		if (i % 8 == 0) | 
 | 			pr_cont("\n       "); | 
 | 		pr_cont(" %08lx", *p++); | 
 | 	} | 
 | 	pr_cont("\n"); | 
 | 	show_trace(stack); | 
 | } |