xref: /openbmc/linux/arch/x86/kernel/dumpstack_32.c (revision 3d02a9c48d479eb58841805baaf93c5a084b6010)
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 
19*3d02a9c4SJosh Poimboeuf const char *stack_type_name(enum stack_type type)
20198d208dSSteven Rostedt {
21*3d02a9c4SJosh Poimboeuf 	if (type == STACK_TYPE_IRQ)
22*3d02a9c4SJosh Poimboeuf 		return "IRQ";
23*3d02a9c4SJosh Poimboeuf 
24*3d02a9c4SJosh Poimboeuf 	if (type == STACK_TYPE_SOFTIRQ)
25*3d02a9c4SJosh Poimboeuf 		return "SOFTIRQ";
26*3d02a9c4SJosh Poimboeuf 
27*3d02a9c4SJosh Poimboeuf 	return NULL;
28198d208dSSteven Rostedt }
29198d208dSSteven Rostedt 
30cb76c939SJosh Poimboeuf static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
31198d208dSSteven Rostedt {
32cb76c939SJosh Poimboeuf 	unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack);
33cb76c939SJosh Poimboeuf 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
34198d208dSSteven Rostedt 
355fe599e0SJosh Poimboeuf 	/*
365fe599e0SJosh Poimboeuf 	 * This is a software stack, so 'end' can be a valid stack pointer.
375fe599e0SJosh Poimboeuf 	 * It just means the stack is empty.
385fe599e0SJosh Poimboeuf 	 */
395fe599e0SJosh Poimboeuf 	if (stack < begin || stack > end)
40cb76c939SJosh Poimboeuf 		return false;
41cb76c939SJosh Poimboeuf 
42cb76c939SJosh Poimboeuf 	info->type	= STACK_TYPE_IRQ;
43cb76c939SJosh Poimboeuf 	info->begin	= begin;
44cb76c939SJosh Poimboeuf 	info->end	= end;
45cb76c939SJosh Poimboeuf 
46cb76c939SJosh Poimboeuf 	/*
47cb76c939SJosh Poimboeuf 	 * See irq_32.c -- the next stack pointer is stored at the beginning of
48cb76c939SJosh Poimboeuf 	 * the stack.
49cb76c939SJosh Poimboeuf 	 */
50cb76c939SJosh Poimboeuf 	info->next_sp	= (unsigned long *)*begin;
51cb76c939SJosh Poimboeuf 
52cb76c939SJosh Poimboeuf 	return true;
53198d208dSSteven Rostedt }
54198d208dSSteven Rostedt 
55cb76c939SJosh Poimboeuf static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
56198d208dSSteven Rostedt {
57cb76c939SJosh Poimboeuf 	unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack);
58cb76c939SJosh Poimboeuf 	unsigned long *end   = begin + (THREAD_SIZE / sizeof(long));
59198d208dSSteven Rostedt 
605fe599e0SJosh Poimboeuf 	/*
615fe599e0SJosh Poimboeuf 	 * This is a software stack, so 'end' can be a valid stack pointer.
625fe599e0SJosh Poimboeuf 	 * It just means the stack is empty.
635fe599e0SJosh Poimboeuf 	 */
645fe599e0SJosh Poimboeuf 	if (stack < begin || stack > end)
65cb76c939SJosh Poimboeuf 		return false;
66cb76c939SJosh Poimboeuf 
67cb76c939SJosh Poimboeuf 	info->type	= STACK_TYPE_SOFTIRQ;
68cb76c939SJosh Poimboeuf 	info->begin	= begin;
69cb76c939SJosh Poimboeuf 	info->end	= end;
70cb76c939SJosh Poimboeuf 
71cb76c939SJosh Poimboeuf 	/*
72cb76c939SJosh Poimboeuf 	 * The next stack pointer is stored at the beginning of the stack.
73cb76c939SJosh Poimboeuf 	 * See irq_32.c.
74cb76c939SJosh Poimboeuf 	 */
75cb76c939SJosh Poimboeuf 	info->next_sp	= (unsigned long *)*begin;
76cb76c939SJosh Poimboeuf 
77cb76c939SJosh Poimboeuf 	return true;
78cb76c939SJosh Poimboeuf }
79cb76c939SJosh Poimboeuf 
80cb76c939SJosh Poimboeuf int get_stack_info(unsigned long *stack, struct task_struct *task,
81cb76c939SJosh Poimboeuf 		   struct stack_info *info, unsigned long *visit_mask)
82cb76c939SJosh Poimboeuf {
83cb76c939SJosh Poimboeuf 	if (!stack)
84cb76c939SJosh Poimboeuf 		goto unknown;
85cb76c939SJosh Poimboeuf 
86cb76c939SJosh Poimboeuf 	task = task ? : current;
87cb76c939SJosh Poimboeuf 
88cb76c939SJosh Poimboeuf 	if (in_task_stack(stack, task, info))
89fcd709efSJosh Poimboeuf 		goto recursion_check;
90cb76c939SJosh Poimboeuf 
91cb76c939SJosh Poimboeuf 	if (task != current)
92cb76c939SJosh Poimboeuf 		goto unknown;
93cb76c939SJosh Poimboeuf 
94cb76c939SJosh Poimboeuf 	if (in_hardirq_stack(stack, info))
95fcd709efSJosh Poimboeuf 		goto recursion_check;
96cb76c939SJosh Poimboeuf 
97cb76c939SJosh Poimboeuf 	if (in_softirq_stack(stack, info))
98fcd709efSJosh Poimboeuf 		goto recursion_check;
99fcd709efSJosh Poimboeuf 
100fcd709efSJosh Poimboeuf 	goto unknown;
101fcd709efSJosh Poimboeuf 
102fcd709efSJosh Poimboeuf recursion_check:
103fcd709efSJosh Poimboeuf 	/*
104fcd709efSJosh Poimboeuf 	 * Make sure we don't iterate through any given stack more than once.
105fcd709efSJosh Poimboeuf 	 * If it comes up a second time then there's something wrong going on:
106fcd709efSJosh Poimboeuf 	 * just break out and report an unknown stack type.
107fcd709efSJosh Poimboeuf 	 */
108fcd709efSJosh Poimboeuf 	if (visit_mask) {
1090d2b8579SJosh Poimboeuf 		if (*visit_mask & (1UL << info->type)) {
1100d2b8579SJosh Poimboeuf 			printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
111fcd709efSJosh Poimboeuf 			goto unknown;
1120d2b8579SJosh Poimboeuf 		}
113fcd709efSJosh Poimboeuf 		*visit_mask |= 1UL << info->type;
114fcd709efSJosh Poimboeuf 	}
115fcd709efSJosh Poimboeuf 
116cb76c939SJosh Poimboeuf 	return 0;
117cb76c939SJosh Poimboeuf 
118cb76c939SJosh Poimboeuf unknown:
119cb76c939SJosh Poimboeuf 	info->type = STACK_TYPE_UNKNOWN;
120cb76c939SJosh Poimboeuf 	return -EINVAL;
121198d208dSSteven Rostedt }
1220406ca6dSFrederic Weisbecker 
12357da8b96SJan Beulich void show_regs(struct pt_regs *regs)
1242bc5f927SAlexander van Heukelum {
1252bc5f927SAlexander van Heukelum 	int i;
1262bc5f927SAlexander van Heukelum 
127a43cb95dSTejun Heo 	show_regs_print_info(KERN_EMERG);
128f39b6f0eSAndy Lutomirski 	__show_regs(regs, !user_mode(regs));
1292bc5f927SAlexander van Heukelum 
1302bc5f927SAlexander van Heukelum 	/*
1312bc5f927SAlexander van Heukelum 	 * When in-kernel, we also print out the stack and code at the
1322bc5f927SAlexander van Heukelum 	 * time of the fault..
1332bc5f927SAlexander van Heukelum 	 */
134f39b6f0eSAndy Lutomirski 	if (!user_mode(regs)) {
1352bc5f927SAlexander van Heukelum 		unsigned int code_prologue = code_bytes * 43 / 64;
1362bc5f927SAlexander van Heukelum 		unsigned int code_len = code_bytes;
1372bc5f927SAlexander van Heukelum 		unsigned char c;
1382bc5f927SAlexander van Heukelum 		u8 *ip;
1392bc5f927SAlexander van Heukelum 
1400ee1dd9fSJosh Poimboeuf 		show_trace_log_lvl(current, regs, NULL, KERN_EMERG);
1412bc5f927SAlexander van Heukelum 
142c767a54bSJoe Perches 		pr_emerg("Code:");
1432bc5f927SAlexander van Heukelum 
1442bc5f927SAlexander van Heukelum 		ip = (u8 *)regs->ip - code_prologue;
1452bc5f927SAlexander van Heukelum 		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
1468a541665SAlexander van Heukelum 			/* try starting at IP */
1472bc5f927SAlexander van Heukelum 			ip = (u8 *)regs->ip;
1482bc5f927SAlexander van Heukelum 			code_len = code_len - code_prologue + 1;
1492bc5f927SAlexander van Heukelum 		}
1502bc5f927SAlexander van Heukelum 		for (i = 0; i < code_len; i++, ip++) {
1512bc5f927SAlexander van Heukelum 			if (ip < (u8 *)PAGE_OFFSET ||
1522bc5f927SAlexander van Heukelum 					probe_kernel_address(ip, c)) {
153c767a54bSJoe Perches 				pr_cont("  Bad EIP value.");
1542bc5f927SAlexander van Heukelum 				break;
1552bc5f927SAlexander van Heukelum 			}
1562bc5f927SAlexander van Heukelum 			if (ip == (u8 *)regs->ip)
157c767a54bSJoe Perches 				pr_cont(" <%02x>", c);
1582bc5f927SAlexander van Heukelum 			else
159c767a54bSJoe Perches 				pr_cont(" %02x", c);
1602bc5f927SAlexander van Heukelum 		}
1612bc5f927SAlexander van Heukelum 	}
162c767a54bSJoe Perches 	pr_cont("\n");
1632bc5f927SAlexander van Heukelum }
1642bc5f927SAlexander van Heukelum 
1652bc5f927SAlexander van Heukelum int is_valid_bugaddr(unsigned long ip)
1662bc5f927SAlexander van Heukelum {
1672bc5f927SAlexander van Heukelum 	unsigned short ud2;
1682bc5f927SAlexander van Heukelum 
1692bc5f927SAlexander van Heukelum 	if (ip < PAGE_OFFSET)
1702bc5f927SAlexander van Heukelum 		return 0;
1712bc5f927SAlexander van Heukelum 	if (probe_kernel_address((unsigned short *)ip, ud2))
1722bc5f927SAlexander van Heukelum 		return 0;
1732bc5f927SAlexander van Heukelum 
1742bc5f927SAlexander van Heukelum 	return ud2 == 0x0b0f;
1752bc5f927SAlexander van Heukelum }
176