aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2016-08-24 12:50:17 -0400
committerIngo Molnar <mingo@kernel.org>2016-09-08 02:58:40 -0400
commit4b8afafbe743be1a81c96ddcd75b19c534d5e262 (patch)
treeb54d1bae9c6aac036566ff9c6bb330812aad810a
parentd438f5fda30ec087512355e405e9c8955d8bd337 (diff)
x86/dumpstack: Add get_stack_pointer() and get_frame_pointer()
The various functions involved in dumping the stack all do similar things with regard to getting the stack pointer and the frame pointer based on the regs and task arguments. Create helper functions to do that instead. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Andy Lutomirski <luto@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Brian Gerst <brgerst@gmail.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Nilay Vaish <nilayvaish@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/f448914885a35f333fe04da1b97a6c2cc1f80974.1472057064.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/stacktrace.h41
-rw-r--r--arch/x86/kernel/dumpstack.c5
-rw-r--r--arch/x86/kernel/dumpstack_32.c25
-rw-r--r--arch/x86/kernel/dumpstack_64.c30
4 files changed, 33 insertions, 68 deletions
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 7646fb2772f8..3552f5e7189e 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -50,36 +50,41 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
50 50
51#ifdef CONFIG_X86_32 51#ifdef CONFIG_X86_32
52#define STACKSLOTS_PER_LINE 8 52#define STACKSLOTS_PER_LINE 8
53#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :)
54#else 53#else
55#define STACKSLOTS_PER_LINE 4 54#define STACKSLOTS_PER_LINE 4
56#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
57#endif 55#endif
58 56
59#ifdef CONFIG_FRAME_POINTER 57#ifdef CONFIG_FRAME_POINTER
60static inline unsigned long 58static inline unsigned long *
61stack_frame(struct task_struct *task, struct pt_regs *regs) 59get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
62{ 60{
63 unsigned long bp;
64
65 if (regs) 61 if (regs)
66 return regs->bp; 62 return (unsigned long *)regs->bp;
67 63
68 if (task == current) { 64 if (!task || task == current)
69 /* Grab bp right from our regs */ 65 return __builtin_frame_address(0);
70 get_bp(bp);
71 return bp;
72 }
73 66
74 return ((struct inactive_task_frame *)task->thread.sp)->bp; 67 return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
75} 68}
76#else 69#else
77static inline unsigned long 70static inline unsigned long *
78stack_frame(struct task_struct *task, struct pt_regs *regs) 71get_frame_pointer(struct task_struct *task, struct pt_regs *regs)
79{ 72{
80 return 0; 73 return NULL;
74}
75#endif /* CONFIG_FRAME_POINTER */
76
77static inline unsigned long *
78get_stack_pointer(struct task_struct *task, struct pt_regs *regs)
79{
80 if (regs)
81 return (unsigned long *)kernel_stack_pointer(regs);
82
83 if (!task || task == current)
84 return __builtin_frame_address(0);
85
86 return (unsigned long *)task->thread.sp;
81} 87}
82#endif
83 88
84extern void 89extern void
85show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, 90show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
@@ -106,7 +111,7 @@ static inline unsigned long caller_frame_pointer(void)
106{ 111{
107 struct stack_frame *frame; 112 struct stack_frame *frame;
108 113
109 get_bp(frame); 114 frame = __builtin_frame_address(0);
110 115
111#ifdef CONFIG_FRAME_POINTER 116#ifdef CONFIG_FRAME_POINTER
112 frame = frame->next_frame; 117 frame = frame->next_frame;
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index f0ddf855957e..6d6f46837eea 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -170,15 +170,14 @@ show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
170void show_stack(struct task_struct *task, unsigned long *sp) 170void show_stack(struct task_struct *task, unsigned long *sp)
171{ 171{
172 unsigned long bp = 0; 172 unsigned long bp = 0;
173 unsigned long stack;
174 173
175 /* 174 /*
176 * Stack frames below this one aren't interesting. Don't show them 175 * Stack frames below this one aren't interesting. Don't show them
177 * if we're printing for %current. 176 * if we're printing for %current.
178 */ 177 */
179 if (!sp && (!task || task == current)) { 178 if (!sp && (!task || task == current)) {
180 sp = &stack; 179 sp = get_stack_pointer(current, NULL);
181 bp = stack_frame(current, NULL); 180 bp = (unsigned long)get_frame_pointer(current, NULL);
182 } 181 }
183 182
184 show_stack_log_lvl(task, NULL, sp, bp, ""); 183 show_stack_log_lvl(task, NULL, sp, bp, "");
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 09675712eba8..358fe1cd4e5b 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -46,19 +46,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
46 int graph = 0; 46 int graph = 0;
47 u32 *prev_esp; 47 u32 *prev_esp;
48 48
49 if (!task) 49 task = task ? : current;
50 task = current; 50 stack = stack ? : get_stack_pointer(task, regs);
51 51 bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
52 if (!stack) {
53 unsigned long dummy;
54
55 stack = &dummy;
56 if (task != current)
57 stack = (unsigned long *)task->thread.sp;
58 }
59
60 if (!bp)
61 bp = stack_frame(task, regs);
62 52
63 for (;;) { 53 for (;;) {
64 void *end_stack; 54 void *end_stack;
@@ -95,14 +85,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
95 unsigned long *stack; 85 unsigned long *stack;
96 int i; 86 int i;
97 87
98 if (sp == NULL) { 88 sp = sp ? : get_stack_pointer(task, regs);
99 if (regs)
100 sp = (unsigned long *)regs->sp;
101 else if (task)
102 sp = (unsigned long *)task->thread.sp;
103 else
104 sp = (unsigned long *)&sp;
105 }
106 89
107 stack = sp; 90 stack = sp;
108 for (i = 0; i < kstack_depth_to_print; i++) { 91 for (i = 0; i < kstack_depth_to_print; i++) {
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 066eb5c77fd6..7f3b8066f719 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -151,25 +151,14 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
151{ 151{
152 const unsigned cpu = get_cpu(); 152 const unsigned cpu = get_cpu();
153 unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu); 153 unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
154 unsigned long dummy;
155 unsigned used = 0; 154 unsigned used = 0;
156 int graph = 0; 155 int graph = 0;
157 int done = 0; 156 int done = 0;
158 157
159 if (!task) 158 task = task ? : current;
160 task = current; 159 stack = stack ? : get_stack_pointer(task, regs);
160 bp = bp ? : (unsigned long)get_frame_pointer(task, regs);
161 161
162 if (!stack) {
163 if (regs)
164 stack = (unsigned long *)regs->sp;
165 else if (task != current)
166 stack = (unsigned long *)task->thread.sp;
167 else
168 stack = &dummy;
169 }
170
171 if (!bp)
172 bp = stack_frame(task, regs);
173 /* 162 /*
174 * Print function call entries in all stacks, starting at the 163 * Print function call entries in all stacks, starting at the
175 * current stack address. If the stacks consist of nested 164 * current stack address. If the stacks consist of nested
@@ -256,18 +245,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
256 irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu)); 245 irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
257 irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long)); 246 irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
258 247
259 /* 248 sp = sp ? : get_stack_pointer(task, regs);
260 * Debugging aid: "show_stack(NULL, NULL);" prints the
261 * back trace for this cpu:
262 */
263 if (sp == NULL) {
264 if (regs)
265 sp = (unsigned long *)regs->sp;
266 else if (task)
267 sp = (unsigned long *)task->thread.sp;
268 else
269 sp = (unsigned long *)&sp;
270 }
271 249
272 stack = sp; 250 stack = sp;
273 for (i = 0; i < kstack_depth_to_print; i++) { 251 for (i = 0; i < kstack_depth_to_print; i++) {