diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 19:13:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 19:13:28 -0400 |
commit | 1a4a2bc460721bc8f91e4c1294d39b38e5af132f (patch) | |
tree | fe646d05f6e17f05601e0a32cc796bec718ab6e7 /arch/x86/kernel/dumpstack.c | |
parent | 110a9e42b68719f584879c5c5c727bbae90d15f9 (diff) | |
parent | 1ef55be16ed69538f89e0a6508be5e62fdc9851c (diff) |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull low-level x86 updates from Ingo Molnar:
"In this cycle this topic tree has become one of those 'super topics'
that accumulated a lot of changes:
- Add CONFIG_VMAP_STACK=y support to the core kernel and enable it on
x86 - preceded by an array of changes. v4.8 saw preparatory changes
in this area already - this is the rest of the work. Includes the
thread stack caching performance optimization. (Andy Lutomirski)
- switch_to() cleanups and all around enhancements. (Brian Gerst)
- A large number of dumpstack infrastructure enhancements and an
unwinder abstraction. The secret long term plan is safe(r) live
patching plus maybe another attempt at debuginfo based unwinding -
but all these current bits are standalone enhancements in a frame
pointer based debug environment as well. (Josh Poimboeuf)
- More __ro_after_init and const annotations. (Kees Cook)
- Enable KASLR for the vmemmap memory region. (Thomas Garnier)"
[ The virtually mapped stack changes are pretty fundamental, and not
x86-specific per se, even if they are only used on x86 right now. ]
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (70 commits)
x86/asm: Get rid of __read_cr4_safe()
thread_info: Use unsigned long for flags
x86/alternatives: Add stack frame dependency to alternative_call_2()
x86/dumpstack: Fix show_stack() task pointer regression
x86/dumpstack: Remove dump_trace() and related callbacks
x86/dumpstack: Convert show_trace_log_lvl() to use the new unwinder
oprofile/x86: Convert x86_backtrace() to use the new unwinder
x86/stacktrace: Convert save_stack_trace_*() to use the new unwinder
perf/x86: Convert perf_callchain_kernel() to use the new unwinder
x86/unwind: Add new unwind interface and implementations
x86/dumpstack: Remove NULL task pointer convention
fork: Optimize task creation by caching two thread stacks per CPU if CONFIG_VMAP_STACK=y
sched/core: Free the stack early if CONFIG_THREAD_INFO_IN_TASK
lib/syscall: Pin the task stack in collect_syscall()
x86/process: Pin the target stack in get_wchan()
x86/dumpstack: Pin the target stack when dumping it
kthread: Pin the stack via try_get_task_stack()/put_task_stack() in to_live_kthread() function
sched/core: Add try_get_task_stack() and put_task_stack()
x86/entry/64: Fix a minor comment rebase error
iommu/amd: Don't put completion-wait semaphore on stack
...
Diffstat (limited to 'arch/x86/kernel/dumpstack.c')
-rw-r--r-- | arch/x86/kernel/dumpstack.c | 258 |
1 files changed, 110 insertions, 148 deletions
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 92e8f0a7159c..9b7cf5c28f5f 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
18 | 18 | ||
19 | #include <asm/stacktrace.h> | 19 | #include <asm/stacktrace.h> |
20 | 20 | #include <asm/unwind.h> | |
21 | 21 | ||
22 | int panic_on_unrecovered_nmi; | 22 | int panic_on_unrecovered_nmi; |
23 | int panic_on_io_nmi; | 23 | int panic_on_io_nmi; |
@@ -25,11 +25,29 @@ unsigned int code_bytes = 64; | |||
25 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; | 25 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; |
26 | static int die_counter; | 26 | static int die_counter; |
27 | 27 | ||
28 | bool in_task_stack(unsigned long *stack, struct task_struct *task, | ||
29 | struct stack_info *info) | ||
30 | { | ||
31 | unsigned long *begin = task_stack_page(task); | ||
32 | unsigned long *end = task_stack_page(task) + THREAD_SIZE; | ||
33 | |||
34 | if (stack < begin || stack >= end) | ||
35 | return false; | ||
36 | |||
37 | info->type = STACK_TYPE_TASK; | ||
38 | info->begin = begin; | ||
39 | info->end = end; | ||
40 | info->next_sp = NULL; | ||
41 | |||
42 | return true; | ||
43 | } | ||
44 | |||
28 | static void printk_stack_address(unsigned long address, int reliable, | 45 | static void printk_stack_address(unsigned long address, int reliable, |
29 | void *data) | 46 | char *log_lvl) |
30 | { | 47 | { |
48 | touch_nmi_watchdog(); | ||
31 | printk("%s [<%p>] %s%pB\n", | 49 | printk("%s [<%p>] %s%pB\n", |
32 | (char *)data, (void *)address, reliable ? "" : "? ", | 50 | log_lvl, (void *)address, reliable ? "" : "? ", |
33 | (void *)address); | 51 | (void *)address); |
34 | } | 52 | } |
35 | 53 | ||
@@ -38,176 +56,120 @@ void printk_address(unsigned long address) | |||
38 | pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address); | 56 | pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address); |
39 | } | 57 | } |
40 | 58 | ||
41 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 59 | void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, |
42 | static void | 60 | unsigned long *stack, char *log_lvl) |
43 | print_ftrace_graph_addr(unsigned long addr, void *data, | ||
44 | const struct stacktrace_ops *ops, | ||
45 | struct task_struct *task, int *graph) | ||
46 | { | 61 | { |
47 | unsigned long ret_addr; | 62 | struct unwind_state state; |
48 | int index; | 63 | struct stack_info stack_info = {0}; |
49 | 64 | unsigned long visit_mask = 0; | |
50 | if (addr != (unsigned long)return_to_handler) | 65 | int graph_idx = 0; |
51 | return; | ||
52 | |||
53 | index = task->curr_ret_stack; | ||
54 | |||
55 | if (!task->ret_stack || index < *graph) | ||
56 | return; | ||
57 | |||
58 | index -= *graph; | ||
59 | ret_addr = task->ret_stack[index].ret; | ||
60 | |||
61 | ops->address(data, ret_addr, 1); | ||
62 | 66 | ||
63 | (*graph)++; | 67 | printk("%sCall Trace:\n", log_lvl); |
64 | } | ||
65 | #else | ||
66 | static inline void | ||
67 | print_ftrace_graph_addr(unsigned long addr, void *data, | ||
68 | const struct stacktrace_ops *ops, | ||
69 | struct task_struct *task, int *graph) | ||
70 | { } | ||
71 | #endif | ||
72 | |||
73 | /* | ||
74 | * x86-64 can have up to three kernel stacks: | ||
75 | * process stack | ||
76 | * interrupt stack | ||
77 | * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack | ||
78 | */ | ||
79 | |||
80 | static inline int valid_stack_ptr(struct task_struct *task, | ||
81 | void *p, unsigned int size, void *end) | ||
82 | { | ||
83 | void *t = task_stack_page(task); | ||
84 | if (end) { | ||
85 | if (p < end && p >= (end-THREAD_SIZE)) | ||
86 | return 1; | ||
87 | else | ||
88 | return 0; | ||
89 | } | ||
90 | return p >= t && p < t + THREAD_SIZE - size; | ||
91 | } | ||
92 | 68 | ||
93 | unsigned long | 69 | unwind_start(&state, task, regs, stack); |
94 | print_context_stack(struct task_struct *task, | ||
95 | unsigned long *stack, unsigned long bp, | ||
96 | const struct stacktrace_ops *ops, void *data, | ||
97 | unsigned long *end, int *graph) | ||
98 | { | ||
99 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
100 | 70 | ||
101 | /* | 71 | /* |
102 | * If we overflowed the stack into a guard page, jump back to the | 72 | * Iterate through the stacks, starting with the current stack pointer. |
103 | * bottom of the usable stack. | 73 | * Each stack has a pointer to the next one. |
74 | * | ||
75 | * x86-64 can have several stacks: | ||
76 | * - task stack | ||
77 | * - interrupt stack | ||
78 | * - HW exception stacks (double fault, nmi, debug, mce) | ||
79 | * | ||
80 | * x86-32 can have up to three stacks: | ||
81 | * - task stack | ||
82 | * - softirq stack | ||
83 | * - hardirq stack | ||
104 | */ | 84 | */ |
105 | if ((unsigned long)task_stack_page(task) - (unsigned long)stack < | 85 | for (; stack; stack = stack_info.next_sp) { |
106 | PAGE_SIZE) | 86 | const char *str_begin, *str_end; |
107 | stack = (unsigned long *)task_stack_page(task); | ||
108 | |||
109 | while (valid_stack_ptr(task, stack, sizeof(*stack), end)) { | ||
110 | unsigned long addr; | ||
111 | |||
112 | addr = *stack; | ||
113 | if (__kernel_text_address(addr)) { | ||
114 | if ((unsigned long) stack == bp + sizeof(long)) { | ||
115 | ops->address(data, addr, 1); | ||
116 | frame = frame->next_frame; | ||
117 | bp = (unsigned long) frame; | ||
118 | } else { | ||
119 | ops->address(data, addr, 0); | ||
120 | } | ||
121 | print_ftrace_graph_addr(addr, data, ops, task, graph); | ||
122 | } | ||
123 | stack++; | ||
124 | } | ||
125 | return bp; | ||
126 | } | ||
127 | EXPORT_SYMBOL_GPL(print_context_stack); | ||
128 | |||
129 | unsigned long | ||
130 | print_context_stack_bp(struct task_struct *task, | ||
131 | unsigned long *stack, unsigned long bp, | ||
132 | const struct stacktrace_ops *ops, void *data, | ||
133 | unsigned long *end, int *graph) | ||
134 | { | ||
135 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
136 | unsigned long *ret_addr = &frame->return_address; | ||
137 | 87 | ||
138 | while (valid_stack_ptr(task, ret_addr, sizeof(*ret_addr), end)) { | 88 | /* |
139 | unsigned long addr = *ret_addr; | 89 | * If we overflowed the task stack into a guard page, jump back |
90 | * to the bottom of the usable stack. | ||
91 | */ | ||
92 | if (task_stack_page(task) - (void *)stack < PAGE_SIZE) | ||
93 | stack = task_stack_page(task); | ||
140 | 94 | ||
141 | if (!__kernel_text_address(addr)) | 95 | if (get_stack_info(stack, task, &stack_info, &visit_mask)) |
142 | break; | 96 | break; |
143 | 97 | ||
144 | if (ops->address(data, addr, 1)) | 98 | stack_type_str(stack_info.type, &str_begin, &str_end); |
145 | break; | 99 | if (str_begin) |
146 | frame = frame->next_frame; | 100 | printk("%s <%s> ", log_lvl, str_begin); |
147 | ret_addr = &frame->return_address; | 101 | |
148 | print_ftrace_graph_addr(addr, data, ops, task, graph); | 102 | /* |
149 | } | 103 | * Scan the stack, printing any text addresses we find. At the |
150 | 104 | * same time, follow proper stack frames with the unwinder. | |
151 | return (unsigned long)frame; | 105 | * |
152 | } | 106 | * Addresses found during the scan which are not reported by |
153 | EXPORT_SYMBOL_GPL(print_context_stack_bp); | 107 | * the unwinder are considered to be additional clues which are |
154 | 108 | * sometimes useful for debugging and are prefixed with '?'. | |
155 | static int print_trace_stack(void *data, char *name) | 109 | * This also serves as a failsafe option in case the unwinder |
156 | { | 110 | * goes off in the weeds. |
157 | printk("%s <%s> ", (char *)data, name); | 111 | */ |
158 | return 0; | 112 | for (; stack < stack_info.end; stack++) { |
159 | } | 113 | unsigned long real_addr; |
160 | 114 | int reliable = 0; | |
161 | /* | 115 | unsigned long addr = *stack; |
162 | * Print one address/symbol entries per line. | 116 | unsigned long *ret_addr_p = |
163 | */ | 117 | unwind_get_return_address_ptr(&state); |
164 | static int print_trace_address(void *data, unsigned long addr, int reliable) | 118 | |
165 | { | 119 | if (!__kernel_text_address(addr)) |
166 | touch_nmi_watchdog(); | 120 | continue; |
167 | printk_stack_address(addr, reliable, data); | 121 | |
168 | return 0; | 122 | if (stack == ret_addr_p) |
169 | } | 123 | reliable = 1; |
170 | 124 | ||
171 | static const struct stacktrace_ops print_trace_ops = { | 125 | /* |
172 | .stack = print_trace_stack, | 126 | * When function graph tracing is enabled for a |
173 | .address = print_trace_address, | 127 | * function, its return address on the stack is |
174 | .walk_stack = print_context_stack, | 128 | * replaced with the address of an ftrace handler |
175 | }; | 129 | * (return_to_handler). In that case, before printing |
176 | 130 | * the "real" address, we want to print the handler | |
177 | void | 131 | * address as an "unreliable" hint that function graph |
178 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | 132 | * tracing was involved. |
179 | unsigned long *stack, unsigned long bp, char *log_lvl) | 133 | */ |
180 | { | 134 | real_addr = ftrace_graph_ret_addr(task, &graph_idx, |
181 | printk("%sCall Trace:\n", log_lvl); | 135 | addr, stack); |
182 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); | 136 | if (real_addr != addr) |
183 | } | 137 | printk_stack_address(addr, 0, log_lvl); |
138 | printk_stack_address(real_addr, reliable, log_lvl); | ||
139 | |||
140 | if (!reliable) | ||
141 | continue; | ||
142 | |||
143 | /* | ||
144 | * Get the next frame from the unwinder. No need to | ||
145 | * check for an error: if anything goes wrong, the rest | ||
146 | * of the addresses will just be printed as unreliable. | ||
147 | */ | ||
148 | unwind_next_frame(&state); | ||
149 | } | ||
184 | 150 | ||
185 | void show_trace(struct task_struct *task, struct pt_regs *regs, | 151 | if (str_end) |
186 | unsigned long *stack, unsigned long bp) | 152 | printk("%s <%s> ", log_lvl, str_end); |
187 | { | 153 | } |
188 | show_trace_log_lvl(task, regs, stack, bp, ""); | ||
189 | } | 154 | } |
190 | 155 | ||
191 | void show_stack(struct task_struct *task, unsigned long *sp) | 156 | void show_stack(struct task_struct *task, unsigned long *sp) |
192 | { | 157 | { |
193 | unsigned long bp = 0; | 158 | task = task ? : current; |
194 | unsigned long stack; | ||
195 | 159 | ||
196 | /* | 160 | /* |
197 | * Stack frames below this one aren't interesting. Don't show them | 161 | * Stack frames below this one aren't interesting. Don't show them |
198 | * if we're printing for %current. | 162 | * if we're printing for %current. |
199 | */ | 163 | */ |
200 | if (!sp && (!task || task == current)) { | 164 | if (!sp && task == current) |
201 | sp = &stack; | 165 | sp = get_stack_pointer(current, NULL); |
202 | bp = stack_frame(current, NULL); | ||
203 | } | ||
204 | 166 | ||
205 | show_stack_log_lvl(task, NULL, sp, bp, ""); | 167 | show_stack_log_lvl(task, NULL, sp, ""); |
206 | } | 168 | } |
207 | 169 | ||
208 | void show_stack_regs(struct pt_regs *regs) | 170 | void show_stack_regs(struct pt_regs *regs) |
209 | { | 171 | { |
210 | show_stack_log_lvl(current, regs, (unsigned long *)regs->sp, regs->bp, ""); | 172 | show_stack_log_lvl(current, regs, NULL, ""); |
211 | } | 173 | } |
212 | 174 | ||
213 | static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; | 175 | static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; |