lkml.org 
[lkml]   [2022]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v15 1/6] arm64: Split unwind_init()
    Date
    From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com>

    unwind_init() is currently a single function that initializes all of the
    unwind state. Split it into the following functions and call them
    appropriately:

    - unwind_init_from_regs() - initialize from regs passed by caller.

    - unwind_init_from_caller() - initialize for the current task
    from the caller of arch_stack_walk().

    - unwind_init_from_task() - initialize from the saved state of a
    task other than the current task. In this case, the other
    task must not be running.

    This is done for two reasons:

    - the different ways of initializing are clear

    - specialized code can be added to each initializer in the future.

    Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
    Reviewed-by: Mark Brown <broonie@kernel.org>
    ---
    arch/arm64/kernel/stacktrace.c | 66 ++++++++++++++++++++++++++++------
    1 file changed, 55 insertions(+), 11 deletions(-)

    diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
    index 0467cb79f080..e44f93ff25f0 100644
    --- a/arch/arm64/kernel/stacktrace.c
    +++ b/arch/arm64/kernel/stacktrace.c
    @@ -50,11 +50,8 @@ struct unwind_state {
    #endif
    };

    -static notrace void unwind_init(struct unwind_state *state, unsigned long fp,
    - unsigned long pc)
    +static void unwind_init_common(struct unwind_state *state)
    {
    - state->fp = fp;
    - state->pc = pc;
    #ifdef CONFIG_KRETPROBES
    state->kr_cur = NULL;
    #endif
    @@ -72,7 +69,57 @@ static notrace void unwind_init(struct unwind_state *state, unsigned long fp,
    state->prev_fp = 0;
    state->prev_type = STACK_TYPE_UNKNOWN;
    }
    -NOKPROBE_SYMBOL(unwind_init);
    +
    +/*
    + * Start an unwind from a pt_regs.
    + *
    + * The unwind will begin at the PC within the regs.
    + *
    + * The regs must be on a stack currently owned by the calling task.
    + */
    +static inline void unwind_init_from_regs(struct unwind_state *state,
    + struct pt_regs *regs)
    +{
    + unwind_init_common(state);
    +
    + state->fp = regs->regs[29];
    + state->pc = regs->pc;
    +}
    +
    +/*
    + * Start an unwind from a caller.
    + *
    + * The unwind will begin at the caller of whichever function this is inlined
    + * into.
    + *
    + * The function which invokes this must be noinline.
    + */
    +static __always_inline void unwind_init_from_caller(struct unwind_state *state)
    +{
    + unwind_init_common(state);
    +
    + state->fp = (unsigned long)__builtin_frame_address(1);
    + state->pc = (unsigned long)__builtin_return_address(0);
    +}
    +
    +/*
    + * Start an unwind from a blocked task.
    + *
    + * The unwind will begin at the blocked tasks saved PC (i.e. the caller of
    + * cpu_switch_to()).
    + *
    + * The caller should ensure the task is blocked in cpu_switch_to() for the
    + * duration of the unwind, or the unwind will be bogus. It is never valid to
    + * call this for the current task.
    + */
    +static inline void unwind_init_from_task(struct unwind_state *state,
    + struct task_struct *task)
    +{
    + unwind_init_common(state);
    +
    + state->fp = thread_saved_fp(task);
    + state->pc = thread_saved_pc(task);
    +}

    /*
    * Unwind from one frame record (A) to the next frame record (B).
    @@ -213,14 +260,11 @@ noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
    struct unwind_state state;

    if (regs)
    - unwind_init(&state, regs->regs[29], regs->pc);
    + unwind_init_from_regs(&state, regs);
    else if (task == current)
    - unwind_init(&state,
    - (unsigned long)__builtin_frame_address(1),
    - (unsigned long)__builtin_return_address(0));
    + unwind_init_from_caller(&state);
    else
    - unwind_init(&state, thread_saved_fp(task),
    - thread_saved_pc(task));
    + unwind_init_from_task(&state, task);

    unwind(task, &state, consume_entry, cookie);
    }
    --
    2.25.1
    \
     
     \ /
      Last update: 2022-06-17 23:08    [W:4.199 / U:0.292 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site