]>
Commit | Line | Data |
---|---|---|
2bc5f927 AH |
1 | /* |
2 | * Copyright (C) 1991, 1992 Linus Torvalds | |
3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | |
4 | */ | |
b17b0153 | 5 | #include <linux/sched/debug.h> |
2bc5f927 AH |
6 | #include <linux/kallsyms.h> |
7 | #include <linux/kprobes.h> | |
8 | #include <linux/uaccess.h> | |
2bc5f927 AH |
9 | #include <linux/hardirq.h> |
10 | #include <linux/kdebug.h> | |
186f4360 | 11 | #include <linux/export.h> |
2bc5f927 AH |
12 | #include <linux/ptrace.h> |
13 | #include <linux/kexec.h> | |
b8030906 | 14 | #include <linux/sysfs.h> |
2bc5f927 AH |
15 | #include <linux/bug.h> |
16 | #include <linux/nmi.h> | |
17 | ||
18 | #include <asm/stacktrace.h> | |
19 | ||
3d02a9c4 | 20 | const char *stack_type_name(enum stack_type type) |
198d208d | 21 | { |
3d02a9c4 JP |
22 | if (type == STACK_TYPE_IRQ) |
23 | return "IRQ"; | |
24 | ||
25 | if (type == STACK_TYPE_SOFTIRQ) | |
26 | return "SOFTIRQ"; | |
27 | ||
e0437c47 DH |
28 | if (type == STACK_TYPE_ENTRY) |
29 | return "ENTRY_TRAMPOLINE"; | |
72e90cc5 | 30 | |
3d02a9c4 | 31 | return NULL; |
198d208d SR |
32 | } |
33 | ||
cb76c939 JP |
34 | static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info) |
35 | { | |
36 | unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack); | |
37 | unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); | |
38 | ||
5fe599e0 JP |
39 | /* |
40 | * This is a software stack, so 'end' can be a valid stack pointer. | |
41 | * It just means the stack is empty. | |
42 | */ | |
43 | if (stack < begin || stack > end) | |
cb76c939 JP |
44 | return false; |
45 | ||
46 | info->type = STACK_TYPE_IRQ; | |
47 | info->begin = begin; | |
48 | info->end = end; | |
49 | ||
50 | /* | |
51 | * See irq_32.c -- the next stack pointer is stored at the beginning of | |
52 | * the stack. | |
53 | */ | |
54 | info->next_sp = (unsigned long *)*begin; | |
198d208d | 55 | |
cb76c939 JP |
56 | return true; |
57 | } | |
58 | ||
59 | static bool in_softirq_stack(unsigned long *stack, struct stack_info *info) | |
198d208d | 60 | { |
cb76c939 JP |
61 | unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack); |
62 | unsigned long *end = begin + (THREAD_SIZE / sizeof(long)); | |
63 | ||
5fe599e0 JP |
64 | /* |
65 | * This is a software stack, so 'end' can be a valid stack pointer. | |
66 | * It just means the stack is empty. | |
67 | */ | |
68 | if (stack < begin || stack > end) | |
cb76c939 JP |
69 | return false; |
70 | ||
71 | info->type = STACK_TYPE_SOFTIRQ; | |
72 | info->begin = begin; | |
73 | info->end = end; | |
74 | ||
75 | /* | |
76 | * The next stack pointer is stored at the beginning of the stack. | |
77 | * See irq_32.c. | |
78 | */ | |
79 | info->next_sp = (unsigned long *)*begin; | |
198d208d | 80 | |
cb76c939 | 81 | return true; |
198d208d SR |
82 | } |
83 | ||
cb76c939 JP |
84 | int get_stack_info(unsigned long *stack, struct task_struct *task, |
85 | struct stack_info *info, unsigned long *visit_mask) | |
198d208d | 86 | { |
cb76c939 JP |
87 | if (!stack) |
88 | goto unknown; | |
198d208d | 89 | |
cb76c939 JP |
90 | task = task ? : current; |
91 | ||
92 | if (in_task_stack(stack, task, info)) | |
fcd709ef | 93 | goto recursion_check; |
cb76c939 JP |
94 | |
95 | if (task != current) | |
96 | goto unknown; | |
97 | ||
e0437c47 | 98 | if (in_entry_stack(stack, info)) |
72e90cc5 AL |
99 | goto recursion_check; |
100 | ||
cb76c939 | 101 | if (in_hardirq_stack(stack, info)) |
fcd709ef | 102 | goto recursion_check; |
cb76c939 JP |
103 | |
104 | if (in_softirq_stack(stack, info)) | |
fcd709ef JP |
105 | goto recursion_check; |
106 | ||
107 | goto unknown; | |
108 | ||
109 | recursion_check: | |
110 | /* | |
111 | * Make sure we don't iterate through any given stack more than once. | |
112 | * If it comes up a second time then there's something wrong going on: | |
113 | * just break out and report an unknown stack type. | |
114 | */ | |
115 | if (visit_mask) { | |
0d2b8579 JP |
116 | if (*visit_mask & (1UL << info->type)) { |
117 | printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type); | |
fcd709ef | 118 | goto unknown; |
0d2b8579 | 119 | } |
fcd709ef JP |
120 | *visit_mask |= 1UL << info->type; |
121 | } | |
122 | ||
123 | return 0; | |
cb76c939 JP |
124 | |
125 | unknown: | |
126 | info->type = STACK_TYPE_UNKNOWN; | |
127 | return -EINVAL; | |
198d208d | 128 | } |
0406ca6d | 129 | |
57da8b96 | 130 | void show_regs(struct pt_regs *regs) |
2bc5f927 AH |
131 | { |
132 | int i; | |
133 | ||
a43cb95d | 134 | show_regs_print_info(KERN_EMERG); |
f39b6f0e | 135 | __show_regs(regs, !user_mode(regs)); |
2bc5f927 | 136 | |
2bc5f927 AH |
137 | /* |
138 | * When in-kernel, we also print out the stack and code at the | |
139 | * time of the fault.. | |
140 | */ | |
f39b6f0e | 141 | if (!user_mode(regs)) { |
2bc5f927 AH |
142 | unsigned int code_prologue = code_bytes * 43 / 64; |
143 | unsigned int code_len = code_bytes; | |
144 | unsigned char c; | |
145 | u8 *ip; | |
146 | ||
0ee1dd9f | 147 | show_trace_log_lvl(current, regs, NULL, KERN_EMERG); |
2bc5f927 | 148 | |
c767a54b | 149 | pr_emerg("Code:"); |
2bc5f927 AH |
150 | |
151 | ip = (u8 *)regs->ip - code_prologue; | |
152 | if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { | |
8a541665 | 153 | /* try starting at IP */ |
2bc5f927 AH |
154 | ip = (u8 *)regs->ip; |
155 | code_len = code_len - code_prologue + 1; | |
156 | } | |
157 | for (i = 0; i < code_len; i++, ip++) { | |
158 | if (ip < (u8 *)PAGE_OFFSET || | |
159 | probe_kernel_address(ip, c)) { | |
c767a54b | 160 | pr_cont(" Bad EIP value."); |
2bc5f927 AH |
161 | break; |
162 | } | |
163 | if (ip == (u8 *)regs->ip) | |
c767a54b | 164 | pr_cont(" <%02x>", c); |
2bc5f927 | 165 | else |
c767a54b | 166 | pr_cont(" %02x", c); |
2bc5f927 AH |
167 | } |
168 | } | |
c767a54b | 169 | pr_cont("\n"); |
2bc5f927 | 170 | } |