Skip to content

Commit 0788aa6

Browse files
Steven RostedtH. Peter Anvin
authored andcommitted
x86: Prepare removal of previous_esp from i386 thread_info structure
The i386 thread_info contains a previous_esp field that is used to daisy chain the different stacks for dump_stack() (ie. irq, softirq, thread stacks). The goal is to eventual make i386 handling of thread_info the same as x86_64, which means that the thread_info will not be in the stack but as a per_cpu variable. We will no longer depend on thread_info being able to daisy chain different stacks as it will only exist in one location (the thread stack). By moving previous_esp to the end of thread_info and referencing it as an offset instead of using a thread_info field, this becomes a stepping stone to moving the thread_info. The offset to get to the previous stack is rather ugly in this patch, but this is only temporary and the prev_esp will be changed in the next commit. This commit is more for sanity checks of the change. Cc: Andrew Morton <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Robert Richter <[email protected]> Signed-off-by: Steven Rostedt <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: H. Peter Anvin <[email protected]>
1 parent b807902 commit 0788aa6

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

arch/x86/include/asm/thread_info.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,14 @@ struct thread_info {
3232
mm_segment_t addr_limit;
3333
struct restart_block restart_block;
3434
void __user *sysenter_return;
35+
unsigned int sig_on_uaccess_error:1;
36+
unsigned int uaccess_err:1; /* uaccess failed */
3537
#ifdef CONFIG_X86_32
3638
unsigned long previous_esp; /* ESP of the previous stack in
3739
case of nested (IRQ) stacks
40+
(Moved to end, to be removed soon)
3841
*/
3942
#endif
40-
unsigned int sig_on_uaccess_error:1;
41-
unsigned int uaccess_err:1; /* uaccess failed */
4243
};
4344

4445
#define INIT_THREAD_INFO(tsk) \

arch/x86/kernel/dumpstack_32.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
2222
const struct stacktrace_ops *ops, void *data)
2323
{
2424
int graph = 0;
25+
u32 *prev_esp;
2526

2627
if (!task)
2728
task = current;
@@ -44,9 +45,17 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
4445
((unsigned long)stack & (~(THREAD_SIZE - 1)));
4546
bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);
4647

47-
stack = (unsigned long *)context->previous_esp;
48+
/* Stop if not on irq stack */
49+
if (task_stack_page(task) == context)
50+
break;
51+
52+
/* The previous esp is just above the context */
53+
prev_esp = (u32 *) ((char *)context + sizeof(struct thread_info) -
54+
sizeof(long));
55+
stack = (unsigned long *)*prev_esp;
4856
if (!stack)
4957
break;
58+
5059
if (ops->stack(data, "IRQ") < 0)
5160
break;
5261
touch_nmi_watchdog();

arch/x86/kernel/irq_32.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static inline int
8181
execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
8282
{
8383
union irq_ctx *curctx, *irqctx;
84-
u32 *isp, arg1, arg2;
84+
u32 *isp, *prev_esp, arg1, arg2;
8585

8686
curctx = (union irq_ctx *) current_thread_info();
8787
irqctx = __this_cpu_read(hardirq_ctx);
@@ -98,7 +98,10 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
9898
/* build the stack frame on the IRQ stack */
9999
isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
100100
irqctx->tinfo.task = curctx->tinfo.task;
101-
irqctx->tinfo.previous_esp = current_stack_pointer;
101+
/* Save the next esp after thread_info */
102+
prev_esp = (u32 *) ((char *)irqctx + sizeof(struct thread_info) -
103+
sizeof(long));
104+
*prev_esp = current_stack_pointer;
102105

103106
if (unlikely(overflow))
104107
call_on_stack(print_stack_overflow, isp);
@@ -149,16 +152,20 @@ void do_softirq_own_stack(void)
149152
{
150153
struct thread_info *curctx;
151154
union irq_ctx *irqctx;
152-
u32 *isp;
155+
u32 *isp, *prev_esp;
153156

154157
curctx = current_thread_info();
155158
irqctx = __this_cpu_read(softirq_ctx);
156159
irqctx->tinfo.task = curctx->task;
157-
irqctx->tinfo.previous_esp = current_stack_pointer;
158160

159161
/* build the stack frame on the softirq stack */
160162
isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
161163

164+
/* Push the previous esp onto the stack */
165+
prev_esp = (u32 *) ((char *)irqctx + sizeof(struct thread_info) -
166+
sizeof(long));
167+
*prev_esp = current_stack_pointer;
168+
162169
call_on_stack(__do_softirq, isp);
163170
}
164171

arch/x86/kernel/ptrace.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,14 @@ unsigned long kernel_stack_pointer(struct pt_regs *regs)
184184
{
185185
unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
186186
unsigned long sp = (unsigned long)&regs->sp;
187-
struct thread_info *tinfo;
187+
u32 *prev_esp;
188188

189189
if (context == (sp & ~(THREAD_SIZE - 1)))
190190
return sp;
191191

192-
tinfo = (struct thread_info *)context;
193-
if (tinfo->previous_esp)
194-
return tinfo->previous_esp;
192+
prev_esp = (u32 *)(context + sizeof(struct thread_info) - sizeof(long));
193+
if (prev_esp)
194+
return (unsigned long)prev_esp;
195195

196196
return (unsigned long)regs;
197197
}

0 commit comments

Comments
 (0)