Skip to content

Commit cfeeed2

Browse files
jpoimboeIngo Molnar
authored andcommitted
x86/dumpstack: Allow preemption in show_stack_log_lvl() and dump_trace()
show_stack_log_lvl() and dump_trace() are already preemption safe: - If they're running in irq or exception context, preemption is already disabled and the percpu stack pointers can be trusted. - If they're running with preemption enabled, they must be running on the task stack anyway, so it doesn't matter if they're comparing the stack pointer against a percpu stack pointer from this CPU or another one: either way it won't match. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Byungchul Park <byungchul.park@lge.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: H. Peter Anvin <hpa@zytor.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/a0ca0b1044eca97d4f0ec7c1619cf80b3b65560d.1473371307.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 85063fa commit cfeeed2

File tree

2 files changed

+15
-25
lines changed

2 files changed

+15
-25
lines changed

arch/x86/kernel/dumpstack_32.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ static void *is_irq_stack(void *p, void *irq)
2424
}
2525

2626

27-
static void *is_hardirq_stack(unsigned long *stack, int cpu)
27+
static void *is_hardirq_stack(unsigned long *stack)
2828
{
29-
void *irq = per_cpu(hardirq_stack, cpu);
29+
void *irq = this_cpu_read(hardirq_stack);
3030

3131
return is_irq_stack(stack, irq);
3232
}
3333

34-
static void *is_softirq_stack(unsigned long *stack, int cpu)
34+
static void *is_softirq_stack(unsigned long *stack)
3535
{
36-
void *irq = per_cpu(softirq_stack, cpu);
36+
void *irq = this_cpu_read(softirq_stack);
3737

3838
return is_irq_stack(stack, irq);
3939
}
@@ -42,7 +42,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
4242
unsigned long *stack, unsigned long bp,
4343
const struct stacktrace_ops *ops, void *data)
4444
{
45-
const unsigned cpu = get_cpu();
4645
int graph = 0;
4746
u32 *prev_esp;
4847

@@ -53,9 +52,9 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
5352
for (;;) {
5453
void *end_stack;
5554

56-
end_stack = is_hardirq_stack(stack, cpu);
55+
end_stack = is_hardirq_stack(stack);
5756
if (!end_stack)
58-
end_stack = is_softirq_stack(stack, cpu);
57+
end_stack = is_softirq_stack(stack);
5958

6059
bp = ops->walk_stack(task, stack, bp, ops, data,
6160
end_stack, &graph);
@@ -74,7 +73,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
7473
break;
7574
touch_nmi_watchdog();
7675
}
77-
put_cpu();
7876
}
7977
EXPORT_SYMBOL(dump_trace);
8078

arch/x86/kernel/dumpstack_64.c

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ static char x86_stack_ids[][8] = {
3131
#endif
3232
};
3333

34-
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
35-
unsigned *usedp, char **idp)
34+
static unsigned long *in_exception_stack(unsigned long stack, unsigned *usedp,
35+
char **idp)
3636
{
3737
unsigned k;
3838

@@ -41,7 +41,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
4141
* 'stack' is in one of them:
4242
*/
4343
for (k = 0; k < N_EXCEPTION_STACKS; k++) {
44-
unsigned long end = per_cpu(orig_ist, cpu).ist[k];
44+
unsigned long end = raw_cpu_ptr(&orig_ist)->ist[k];
4545
/*
4646
* Is 'stack' above this exception frame's end?
4747
* If yes then skip to the next frame.
@@ -111,7 +111,7 @@ enum stack_type {
111111
};
112112

113113
static enum stack_type
114-
analyze_stack(int cpu, struct task_struct *task, unsigned long *stack,
114+
analyze_stack(struct task_struct *task, unsigned long *stack,
115115
unsigned long **stack_end, unsigned long *irq_stack,
116116
unsigned *used, char **id)
117117
{
@@ -121,8 +121,7 @@ analyze_stack(int cpu, struct task_struct *task, unsigned long *stack,
121121
if ((unsigned long)task_stack_page(task) == addr)
122122
return STACK_IS_NORMAL;
123123

124-
*stack_end = in_exception_stack(cpu, (unsigned long)stack,
125-
used, id);
124+
*stack_end = in_exception_stack((unsigned long)stack, used, id);
126125
if (*stack_end)
127126
return STACK_IS_EXCEPTION;
128127

@@ -149,8 +148,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
149148
unsigned long *stack, unsigned long bp,
150149
const struct stacktrace_ops *ops, void *data)
151150
{
152-
const unsigned cpu = get_cpu();
153-
unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
151+
unsigned long *irq_stack = (unsigned long *)this_cpu_read(irq_stack_ptr);
154152
unsigned used = 0;
155153
int graph = 0;
156154
int done = 0;
@@ -169,8 +167,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
169167
enum stack_type stype;
170168
char *id;
171169

172-
stype = analyze_stack(cpu, task, stack, &stack_end,
173-
irq_stack, &used, &id);
170+
stype = analyze_stack(task, stack, &stack_end, irq_stack, &used,
171+
&id);
174172

175173
/* Default finish unless specified to continue */
176174
done = 1;
@@ -225,7 +223,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
225223
* This handles the process stack:
226224
*/
227225
bp = ops->walk_stack(task, stack, bp, ops, data, NULL, &graph);
228-
put_cpu();
229226
}
230227
EXPORT_SYMBOL(dump_trace);
231228

@@ -236,13 +233,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
236233
unsigned long *irq_stack_end;
237234
unsigned long *irq_stack;
238235
unsigned long *stack;
239-
int cpu;
240236
int i;
241237

242-
preempt_disable();
243-
cpu = smp_processor_id();
244-
245-
irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
238+
irq_stack_end = (unsigned long *)this_cpu_read(irq_stack_ptr);
246239
irq_stack = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
247240

248241
sp = sp ? : get_stack_pointer(task, regs);
@@ -274,7 +267,6 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
274267
stack++;
275268
touch_nmi_watchdog();
276269
}
277-
preempt_enable();
278270

279271
pr_cont("\n");
280272
show_trace_log_lvl(task, regs, sp, bp, log_lvl);

0 commit comments

Comments
 (0)