lkml.org 
[lkml]   [2011]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 2/4 v2] x86: Remove previous_esp from i386 thread_info structure
    From: Steven Rostedt <srostedt@redhat.com>

    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 out of thread_info, and just placing it
    above the thread_info of the current stack, we can still use
    the stacks to daisy chain which stack was in use when preempted by
    an interrupt.

    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
    ---
    arch/x86/include/asm/thread_info.h | 5 -----
    arch/x86/kernel/dumpstack_32.c | 10 +++++++++-
    arch/x86/kernel/irq_32.c | 13 +++++++++----
    3 files changed, 18 insertions(+), 10 deletions(-)

    diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
    index 625910f..8f2b249 100644
    --- a/arch/x86/include/asm/thread_info.h
    +++ b/arch/x86/include/asm/thread_info.h
    @@ -34,11 +34,6 @@ struct thread_info {
    mm_segment_t addr_limit;
    struct restart_block restart_block;
    void __user *sysenter_return;
    -#ifdef CONFIG_X86_32
    - unsigned long previous_esp; /* ESP of the previous stack in
    - case of nested (IRQ) stacks
    - */
    -#endif
    int uaccess_err;
    };

    diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
    index 3b97a80..8955e25 100644
    --- a/arch/x86/kernel/dumpstack_32.c
    +++ b/arch/x86/kernel/dumpstack_32.c
    @@ -22,6 +22,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
    const struct stacktrace_ops *ops, void *data)
    {
    int graph = 0;
    + u32 *prev_esp;

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

    - stack = (unsigned long *)context->previous_esp;
    + /* Stop if not on irq stack */
    + if (task_stack_page(task) == context)
    + break;
    +
    + /* The previous esp is just above the context */
    + prev_esp = (u32 *) ((char *)context + sizeof(struct thread_info));
    + stack = (unsigned long *)*prev_esp;
    if (!stack)
    break;
    +
    if (ops->stack(data, "IRQ") < 0)
    break;
    touch_nmi_watchdog();
    diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
    index 7209070..47909a0 100644
    --- a/arch/x86/kernel/irq_32.c
    +++ b/arch/x86/kernel/irq_32.c
    @@ -76,7 +76,7 @@ static inline int
    execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
    {
    union irq_ctx *curctx, *irqctx;
    - u32 *isp, arg1, arg2;
    + u32 *isp, *prev_esp, arg1, arg2;

    curctx = (union irq_ctx *) current_thread_info();
    irqctx = __this_cpu_read(hardirq_ctx);
    @@ -93,7 +93,9 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
    /* build the stack frame on the IRQ stack */
    isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
    irqctx->tinfo.task = curctx->tinfo.task;
    - irqctx->tinfo.previous_esp = current_stack_pointer;
    + /* Save the next esp after thread_info */
    + prev_esp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
    + *prev_esp = current_stack_pointer;

    /*
    * Copy the softirq bits in preempt_count so that the
    @@ -154,7 +156,7 @@ asmlinkage void do_softirq(void)
    unsigned long flags;
    struct thread_info *curctx;
    union irq_ctx *irqctx;
    - u32 *isp;
    + u32 *isp, *prev_esp;

    if (in_interrupt())
    return;
    @@ -165,11 +167,14 @@ asmlinkage void do_softirq(void)
    curctx = current_thread_info();
    irqctx = __this_cpu_read(softirq_ctx);
    irqctx->tinfo.task = curctx->task;
    - irqctx->tinfo.previous_esp = current_stack_pointer;

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

    + /* Push the previous esp onto the stack */
    + prev_esp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
    + *prev_esp = current_stack_pointer;
    +
    call_on_stack(__do_softirq, isp);
    /*
    * Shouldn't happen, we returned above if in_interrupt():
    --
    1.7.5.4



    \
     
     \ /
      Last update: 2011-08-06 03:27    [W:0.090 / U:0.092 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site