ASoC: soc-core: snd_soc_rtdcom_lookup() cares component driver name
[sfrench/cifs-2.6.git] / arch / x86 / kernel / dumpstack_64.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Copyright (C) 1991, 1992  Linus Torvalds
4  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
5  */
6 #include <linux/sched/debug.h>
7 #include <linux/kallsyms.h>
8 #include <linux/kprobes.h>
9 #include <linux/uaccess.h>
10 #include <linux/hardirq.h>
11 #include <linux/kdebug.h>
12 #include <linux/export.h>
13 #include <linux/ptrace.h>
14 #include <linux/kexec.h>
15 #include <linux/sysfs.h>
16 #include <linux/bug.h>
17 #include <linux/nmi.h>
18
19 #include <asm/stacktrace.h>
20
21 static char *exception_stack_names[N_EXCEPTION_STACKS] = {
22                 [ DOUBLEFAULT_STACK-1   ]       = "#DF",
23                 [ NMI_STACK-1           ]       = "NMI",
24                 [ DEBUG_STACK-1         ]       = "#DB",
25                 [ MCE_STACK-1           ]       = "#MC",
26 };
27
28 static unsigned long exception_stack_sizes[N_EXCEPTION_STACKS] = {
29         [0 ... N_EXCEPTION_STACKS - 1]          = EXCEPTION_STKSZ,
30         [DEBUG_STACK - 1]                       = DEBUG_STKSZ
31 };
32
33 const char *stack_type_name(enum stack_type type)
34 {
35         BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
36
37         if (type == STACK_TYPE_IRQ)
38                 return "IRQ";
39
40         if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
41                 return exception_stack_names[type - STACK_TYPE_EXCEPTION];
42
43         return NULL;
44 }
45
46 static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
47 {
48         unsigned long *begin, *end;
49         struct pt_regs *regs;
50         unsigned k;
51
52         BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
53
54         for (k = 0; k < N_EXCEPTION_STACKS; k++) {
55                 end   = (unsigned long *)raw_cpu_ptr(&orig_ist)->ist[k];
56                 begin = end - (exception_stack_sizes[k] / sizeof(long));
57                 regs  = (struct pt_regs *)end - 1;
58
59                 if (stack <= begin || stack >= end)
60                         continue;
61
62                 info->type      = STACK_TYPE_EXCEPTION + k;
63                 info->begin     = begin;
64                 info->end       = end;
65                 info->next_sp   = (unsigned long *)regs->sp;
66
67                 return true;
68         }
69
70         return false;
71 }
72
73 static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
74 {
75         unsigned long *end   = (unsigned long *)this_cpu_read(irq_stack_ptr);
76         unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
77
78         /*
79          * This is a software stack, so 'end' can be a valid stack pointer.
80          * It just means the stack is empty.
81          */
82         if (stack <= begin || stack > end)
83                 return false;
84
85         info->type      = STACK_TYPE_IRQ;
86         info->begin     = begin;
87         info->end       = end;
88
89         /*
90          * The next stack pointer is the first thing pushed by the entry code
91          * after switching to the irq stack.
92          */
93         info->next_sp = (unsigned long *)*(end - 1);
94
95         return true;
96 }
97
98 int get_stack_info(unsigned long *stack, struct task_struct *task,
99                    struct stack_info *info, unsigned long *visit_mask)
100 {
101         if (!stack)
102                 goto unknown;
103
104         task = task ? : current;
105
106         if (in_task_stack(stack, task, info))
107                 goto recursion_check;
108
109         if (task != current)
110                 goto unknown;
111
112         if (in_exception_stack(stack, info))
113                 goto recursion_check;
114
115         if (in_irq_stack(stack, info))
116                 goto recursion_check;
117
118         goto unknown;
119
120 recursion_check:
121         /*
122          * Make sure we don't iterate through any given stack more than once.
123          * If it comes up a second time then there's something wrong going on:
124          * just break out and report an unknown stack type.
125          */
126         if (visit_mask) {
127                 if (*visit_mask & (1UL << info->type)) {
128                         printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
129                         goto unknown;
130                 }
131                 *visit_mask |= 1UL << info->type;
132         }
133
134         return 0;
135
136 unknown:
137         info->type = STACK_TYPE_UNKNOWN;
138         return -EINVAL;
139 }
140
141 void show_regs(struct pt_regs *regs)
142 {
143         int i;
144
145         show_regs_print_info(KERN_DEFAULT);
146         __show_regs(regs, 1);
147
148         /*
149          * When in-kernel, we also print out the stack and code at the
150          * time of the fault..
151          */
152         if (!user_mode(regs)) {
153                 unsigned int code_prologue = code_bytes * 43 / 64;
154                 unsigned int code_len = code_bytes;
155                 unsigned char c;
156                 u8 *ip;
157
158                 show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
159
160                 printk(KERN_DEFAULT "Code: ");
161
162                 ip = (u8 *)regs->ip - code_prologue;
163                 if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
164                         /* try starting at IP */
165                         ip = (u8 *)regs->ip;
166                         code_len = code_len - code_prologue + 1;
167                 }
168                 for (i = 0; i < code_len; i++, ip++) {
169                         if (ip < (u8 *)PAGE_OFFSET ||
170                                         probe_kernel_address(ip, c)) {
171                                 pr_cont(" Bad RIP value.");
172                                 break;
173                         }
174                         if (ip == (u8 *)regs->ip)
175                                 pr_cont("<%02x> ", c);
176                         else
177                                 pr_cont("%02x ", c);
178                 }
179         }
180         pr_cont("\n");
181 }