xref: /openbmc/linux/arch/x86/kernel/dumpstack_32.c (revision fcd709ef20a9d83bdb7524d27cd6719dac8690a0)
12bc5f927SAlexander van Heukelum /*
22bc5f927SAlexander van Heukelum  *  Copyright (C) 1991, 1992  Linus Torvalds
32bc5f927SAlexander van Heukelum  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
42bc5f927SAlexander van Heukelum  */
52bc5f927SAlexander van Heukelum #include <linux/kallsyms.h>
62bc5f927SAlexander van Heukelum #include <linux/kprobes.h>
72bc5f927SAlexander van Heukelum #include <linux/uaccess.h>
82bc5f927SAlexander van Heukelum #include <linux/hardirq.h>
92bc5f927SAlexander van Heukelum #include <linux/kdebug.h>
10186f4360SPaul Gortmaker #include <linux/export.h>
112bc5f927SAlexander van Heukelum #include <linux/ptrace.h>
122bc5f927SAlexander van Heukelum #include <linux/kexec.h>
13b8030906SIngo Molnar #include <linux/sysfs.h>
142bc5f927SAlexander van Heukelum #include <linux/bug.h>
152bc5f927SAlexander van Heukelum #include <linux/nmi.h>
162bc5f927SAlexander van Heukelum 
172bc5f927SAlexander van Heukelum #include <asm/stacktrace.h>
182bc5f927SAlexander van Heukelum 
19cb76c939SJosh Poimboeuf void stack_type_str(enum stack_type type, const char **begin, const char **end)
20198d208dSSteven Rostedt {
21cb76c939SJosh Poimboeuf 	switch (type) {
22cb76c939SJosh Poimboeuf 	case STACK_TYPE_IRQ:
23cb76c939SJosh Poimboeuf 	case STACK_TYPE_SOFTIRQ:
24cb76c939SJosh Poimboeuf 		*begin = "IRQ";
25cb76c939SJosh Poimboeuf 		*end   = "EOI";
26cb76c939SJosh Poimboeuf 		break;
27cb76c939SJosh Poimboeuf 	default:
28cb76c939SJosh Poimboeuf 		*begin = NULL;
29cb76c939SJosh Poimboeuf 		*end   = NULL;
30cb76c939SJosh Poimboeuf 	}
31198d208dSSteven Rostedt }
32198d208dSSteven Rostedt 
33cb76c939SJosh Poimboeuf static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
34198d208dSSteven Rostedt {
35cb76c939SJosh Poimboeuf 	unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack);
36cb76c939SJosh Poimboeuf 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
37198d208dSSteven Rostedt 
385fe599e0SJosh Poimboeuf 	/*
395fe599e0SJosh Poimboeuf 	 * This is a software stack, so 'end' can be a valid stack pointer.
405fe599e0SJosh Poimboeuf 	 * It just means the stack is empty.
415fe599e0SJosh Poimboeuf 	 */
425fe599e0SJosh Poimboeuf 	if (stack < begin || stack > end)
43cb76c939SJosh Poimboeuf 		return false;
44cb76c939SJosh Poimboeuf 
45cb76c939SJosh Poimboeuf 	info->type	= STACK_TYPE_IRQ;
46cb76c939SJosh Poimboeuf 	info->begin	= begin;
47cb76c939SJosh Poimboeuf 	info->end	= end;
48cb76c939SJosh Poimboeuf 
49cb76c939SJosh Poimboeuf 	/*
50cb76c939SJosh Poimboeuf 	 * See irq_32.c -- the next stack pointer is stored at the beginning of
51cb76c939SJosh Poimboeuf 	 * the stack.
52cb76c939SJosh Poimboeuf 	 */
53cb76c939SJosh Poimboeuf 	info->next_sp	= (unsigned long *)*begin;
54cb76c939SJosh Poimboeuf 
55cb76c939SJosh Poimboeuf 	return true;
56198d208dSSteven Rostedt }
57198d208dSSteven Rostedt 
58cb76c939SJosh Poimboeuf static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
59198d208dSSteven Rostedt {
60cb76c939SJosh Poimboeuf 	unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack);
61cb76c939SJosh Poimboeuf 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
62198d208dSSteven Rostedt 
635fe599e0SJosh Poimboeuf 	/*
645fe599e0SJosh Poimboeuf 	 * This is a software stack, so 'end' can be a valid stack pointer.
655fe599e0SJosh Poimboeuf 	 * It just means the stack is empty.
665fe599e0SJosh Poimboeuf 	 */
675fe599e0SJosh Poimboeuf 	if (stack < begin || stack > end)
68cb76c939SJosh Poimboeuf 		return false;
69cb76c939SJosh Poimboeuf 
70cb76c939SJosh Poimboeuf 	info->type	= STACK_TYPE_SOFTIRQ;
71cb76c939SJosh Poimboeuf 	info->begin	= begin;
72cb76c939SJosh Poimboeuf 	info->end	= end;
73cb76c939SJosh Poimboeuf 
74cb76c939SJosh Poimboeuf 	/*
75cb76c939SJosh Poimboeuf 	 * The next stack pointer is stored at the beginning of the stack.
76cb76c939SJosh Poimboeuf 	 * See irq_32.c.
77cb76c939SJosh Poimboeuf 	 */
78cb76c939SJosh Poimboeuf 	info->next_sp	= (unsigned long *)*begin;
79cb76c939SJosh Poimboeuf 
80cb76c939SJosh Poimboeuf 	return true;
81cb76c939SJosh Poimboeuf }
82cb76c939SJosh Poimboeuf 
83cb76c939SJosh Poimboeuf int get_stack_info(unsigned long *stack, struct task_struct *task,
84cb76c939SJosh Poimboeuf 		   struct stack_info *info, unsigned long *visit_mask)
85cb76c939SJosh Poimboeuf {
86cb76c939SJosh Poimboeuf 	if (!stack)
87cb76c939SJosh Poimboeuf 		goto unknown;
88cb76c939SJosh Poimboeuf 
89cb76c939SJosh Poimboeuf 	task = task ? : current;
90cb76c939SJosh Poimboeuf 
91cb76c939SJosh Poimboeuf 	if (in_task_stack(stack, task, info))
92*fcd709efSJosh Poimboeuf 		goto recursion_check;
93cb76c939SJosh Poimboeuf 
94cb76c939SJosh Poimboeuf 	if (task != current)
95cb76c939SJosh Poimboeuf 		goto unknown;
96cb76c939SJosh Poimboeuf 
97cb76c939SJosh Poimboeuf 	if (in_hardirq_stack(stack, info))
98*fcd709efSJosh Poimboeuf 		goto recursion_check;
99cb76c939SJosh Poimboeuf 
100cb76c939SJosh Poimboeuf 	if (in_softirq_stack(stack, info))
101*fcd709efSJosh Poimboeuf 		goto recursion_check;
102*fcd709efSJosh Poimboeuf 
103*fcd709efSJosh Poimboeuf 	goto unknown;
104*fcd709efSJosh Poimboeuf 
105*fcd709efSJosh Poimboeuf recursion_check:
106*fcd709efSJosh Poimboeuf 	/*
107*fcd709efSJosh Poimboeuf 	 * Make sure we don't iterate through any given stack more than once.
108*fcd709efSJosh Poimboeuf 	 * If it comes up a second time then there's something wrong going on:
109*fcd709efSJosh Poimboeuf 	 * just break out and report an unknown stack type.
110*fcd709efSJosh Poimboeuf 	 */
111*fcd709efSJosh Poimboeuf 	if (visit_mask) {
112*fcd709efSJosh Poimboeuf 		if (*visit_mask & (1UL << info->type))
113*fcd709efSJosh Poimboeuf 			goto unknown;
114*fcd709efSJosh Poimboeuf 		*visit_mask |= 1UL << info->type;
115*fcd709efSJosh Poimboeuf 	}
116*fcd709efSJosh Poimboeuf 
117cb76c939SJosh Poimboeuf 	return 0;
118cb76c939SJosh Poimboeuf 
119cb76c939SJosh Poimboeuf unknown:
120cb76c939SJosh Poimboeuf 	info->type = STACK_TYPE_UNKNOWN;
121cb76c939SJosh Poimboeuf 	return -EINVAL;
122198d208dSSteven Rostedt }
1230406ca6dSFrederic Weisbecker 
124e8e999cfSNamhyung Kim void dump_trace(struct task_struct *task, struct pt_regs *regs,
125e8e999cfSNamhyung Kim 		unsigned long *stack, unsigned long bp,
1262bc5f927SAlexander van Heukelum 		const struct stacktrace_ops *ops, void *data)
1272bc5f927SAlexander van Heukelum {
128cb76c939SJosh Poimboeuf 	unsigned long visit_mask = 0;
1297ee991fbSSteven Rostedt 	int graph = 0;
1307ee991fbSSteven Rostedt 
1314b8afafbSJosh Poimboeuf 	task = task ? : current;
1324b8afafbSJosh Poimboeuf 	stack = stack ? : get_stack_pointer(task, regs);
1334b8afafbSJosh Poimboeuf 	bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
134e8e999cfSNamhyung Kim 
1352bc5f927SAlexander van Heukelum 	for (;;) {
136cb76c939SJosh Poimboeuf 		const char *begin_str, *end_str;
137cb76c939SJosh Poimboeuf 		struct stack_info info;
1382bc5f927SAlexander van Heukelum 
139cb76c939SJosh Poimboeuf 		if (get_stack_info(stack, task, &info, &visit_mask))
1400788aa6aSSteven Rostedt 			break;
1410788aa6aSSteven Rostedt 
142cb76c939SJosh Poimboeuf 		stack_type_str(info.type, &begin_str, &end_str);
143cb76c939SJosh Poimboeuf 
144cb76c939SJosh Poimboeuf 		if (begin_str && ops->stack(data, begin_str) < 0)
1452bc5f927SAlexander van Heukelum 			break;
1460788aa6aSSteven Rostedt 
147cb76c939SJosh Poimboeuf 		bp = ops->walk_stack(task, stack, bp, ops, data, &info, &graph);
148cb76c939SJosh Poimboeuf 
149cb76c939SJosh Poimboeuf 		if (end_str && ops->stack(data, end_str) < 0)
1502ac53721SAlexander van Heukelum 			break;
151cb76c939SJosh Poimboeuf 
152cb76c939SJosh Poimboeuf 		stack = info.next_sp;
153cb76c939SJosh Poimboeuf 
1542bc5f927SAlexander van Heukelum 		touch_nmi_watchdog();
1552bc5f927SAlexander van Heukelum 	}
1562bc5f927SAlexander van Heukelum }
1572bc5f927SAlexander van Heukelum EXPORT_SYMBOL(dump_trace);
1582bc5f927SAlexander van Heukelum 
159878719e8SNeil Horman void
1602bc5f927SAlexander van Heukelum show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
161e8e999cfSNamhyung Kim 		   unsigned long *sp, unsigned long bp, char *log_lvl)
1622bc5f927SAlexander van Heukelum {
1632bc5f927SAlexander van Heukelum 	unsigned long *stack;
1642bc5f927SAlexander van Heukelum 	int i;
1652bc5f927SAlexander van Heukelum 
1664b8afafbSJosh Poimboeuf 	sp = sp ? : get_stack_pointer(task, regs);
1672bc5f927SAlexander van Heukelum 
1682bc5f927SAlexander van Heukelum 	stack = sp;
1692bc5f927SAlexander van Heukelum 	for (i = 0; i < kstack_depth_to_print; i++) {
1702bc5f927SAlexander van Heukelum 		if (kstack_end(stack))
1712bc5f927SAlexander van Heukelum 			break;
1721fc7f61cSAdrien Schildknecht 		if ((i % STACKSLOTS_PER_LINE) == 0) {
1731fc7f61cSAdrien Schildknecht 			if (i != 0)
174c767a54bSJoe Perches 				pr_cont("\n");
1751fc7f61cSAdrien Schildknecht 			printk("%s %08lx", log_lvl, *stack++);
1761fc7f61cSAdrien Schildknecht 		} else
177c767a54bSJoe Perches 			pr_cont(" %08lx", *stack++);
178ca0a8164SAlexander van Heukelum 		touch_nmi_watchdog();
1792bc5f927SAlexander van Heukelum 	}
180c767a54bSJoe Perches 	pr_cont("\n");
181e8e999cfSNamhyung Kim 	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
1822bc5f927SAlexander van Heukelum }
1832bc5f927SAlexander van Heukelum 
1842bc5f927SAlexander van Heukelum 
18557da8b96SJan Beulich void show_regs(struct pt_regs *regs)
1862bc5f927SAlexander van Heukelum {
1872bc5f927SAlexander van Heukelum 	int i;
1882bc5f927SAlexander van Heukelum 
189a43cb95dSTejun Heo 	show_regs_print_info(KERN_EMERG);
190f39b6f0eSAndy Lutomirski 	__show_regs(regs, !user_mode(regs));
1912bc5f927SAlexander van Heukelum 
1922bc5f927SAlexander van Heukelum 	/*
1932bc5f927SAlexander van Heukelum 	 * When in-kernel, we also print out the stack and code at the
1942bc5f927SAlexander van Heukelum 	 * time of the fault..
1952bc5f927SAlexander van Heukelum 	 */
196f39b6f0eSAndy Lutomirski 	if (!user_mode(regs)) {
1972bc5f927SAlexander van Heukelum 		unsigned int code_prologue = code_bytes * 43 / 64;
1982bc5f927SAlexander van Heukelum 		unsigned int code_len = code_bytes;
1992bc5f927SAlexander van Heukelum 		unsigned char c;
2002bc5f927SAlexander van Heukelum 		u8 *ip;
2012bc5f927SAlexander van Heukelum 
202c767a54bSJoe Perches 		pr_emerg("Stack:\n");
2035a8ff54cSJosh Poimboeuf 		show_stack_log_lvl(NULL, regs, NULL, 0, KERN_EMERG);
2042bc5f927SAlexander van Heukelum 
205c767a54bSJoe Perches 		pr_emerg("Code:");
2062bc5f927SAlexander van Heukelum 
2072bc5f927SAlexander van Heukelum 		ip = (u8 *)regs->ip - code_prologue;
2082bc5f927SAlexander van Heukelum 		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
2098a541665SAlexander van Heukelum 			/* try starting at IP */
2102bc5f927SAlexander van Heukelum 			ip = (u8 *)regs->ip;
2112bc5f927SAlexander van Heukelum 			code_len = code_len - code_prologue + 1;
2122bc5f927SAlexander van Heukelum 		}
2132bc5f927SAlexander van Heukelum 		for (i = 0; i < code_len; i++, ip++) {
2142bc5f927SAlexander van Heukelum 			if (ip < (u8 *)PAGE_OFFSET ||
2152bc5f927SAlexander van Heukelum 					probe_kernel_address(ip, c)) {
216c767a54bSJoe Perches 				pr_cont("  Bad EIP value.");
2172bc5f927SAlexander van Heukelum 				break;
2182bc5f927SAlexander van Heukelum 			}
2192bc5f927SAlexander van Heukelum 			if (ip == (u8 *)regs->ip)
220c767a54bSJoe Perches 				pr_cont(" <%02x>", c);
2212bc5f927SAlexander van Heukelum 			else
222c767a54bSJoe Perches 				pr_cont(" %02x", c);
2232bc5f927SAlexander van Heukelum 		}
2242bc5f927SAlexander van Heukelum 	}
225c767a54bSJoe Perches 	pr_cont("\n");
2262bc5f927SAlexander van Heukelum }
2272bc5f927SAlexander van Heukelum 
2282bc5f927SAlexander van Heukelum int is_valid_bugaddr(unsigned long ip)
2292bc5f927SAlexander van Heukelum {
2302bc5f927SAlexander van Heukelum 	unsigned short ud2;
2312bc5f927SAlexander van Heukelum 
2322bc5f927SAlexander van Heukelum 	if (ip < PAGE_OFFSET)
2332bc5f927SAlexander van Heukelum 		return 0;
2342bc5f927SAlexander van Heukelum 	if (probe_kernel_address((unsigned short *)ip, ud2))
2352bc5f927SAlexander van Heukelum 		return 0;
2362bc5f927SAlexander van Heukelum 
2372bc5f927SAlexander van Heukelum 	return ud2 == 0x0b0f;
2382bc5f927SAlexander van Heukelum }
239