lkml.org 
[lkml]   [2022]   [Nov]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v6 7/9] LoongArch/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support
    Date
    Ftrace_graph_ret_addr can be called by stack unwinding code to convert
    a found stack return address ('ret') to its original value, in case the
    function graph tracer has modified it to be 'return_to_handler',If the
    hasn't been modified, the unchanged value of 'ret' is returned.

    Signed-off-by: Qing Zhang <zhangqing@loongson.cn>
    ---
    arch/loongarch/include/asm/ftrace.h | 3 +++
    arch/loongarch/include/asm/unwind.h | 1 +
    arch/loongarch/kernel/ftrace_dyn.c | 2 +-
    arch/loongarch/kernel/unwind_guess.c | 4 +++-
    arch/loongarch/kernel/unwind_prologue.c | 11 +++++++++--
    5 files changed, 17 insertions(+), 4 deletions(-)

    diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/asm/ftrace.h
    index 5cc13ae48164..1583ec2171fc 100644
    --- a/arch/loongarch/include/asm/ftrace.h
    +++ b/arch/loongarch/include/asm/ftrace.h
    @@ -6,6 +6,8 @@
    #ifndef _ASM_LOONGARCH_FTRACE_H
    #define _ASM_LOONGARCH_FTRACE_H

    +#define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
    +
    #ifdef CONFIG_FUNCTION_TRACER
    #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */

    @@ -33,6 +35,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
    #endif

    #ifdef CONFIG_DYNAMIC_FTRACE
    +#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
    static inline unsigned long ftrace_call_adjust(unsigned long addr)
    {
    return addr;
    diff --git a/arch/loongarch/include/asm/unwind.h b/arch/loongarch/include/asm/unwind.h
    index a51eec00efb8..f2b52b9ea93d 100644
    --- a/arch/loongarch/include/asm/unwind.h
    +++ b/arch/loongarch/include/asm/unwind.h
    @@ -21,6 +21,7 @@ struct unwind_state {
    struct stack_info stack_info;
    struct task_struct *task;
    bool first, error, is_ftrace;
    + int graph_idx;
    unsigned long sp, pc, ra;
    };

    diff --git a/arch/loongarch/kernel/ftrace_dyn.c b/arch/loongarch/kernel/ftrace_dyn.c
    index f538829312d7..cd64887e26b5 100644
    --- a/arch/loongarch/kernel/ftrace_dyn.c
    +++ b/arch/loongarch/kernel/ftrace_dyn.c
    @@ -140,7 +140,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent)

    old = *parent;

    - if (!function_graph_enter(old, self_addr, 0, NULL))
    + if (!function_graph_enter(old, self_addr, 0, parent))
    *parent = return_hooker;
    }

    diff --git a/arch/loongarch/kernel/unwind_guess.c b/arch/loongarch/kernel/unwind_guess.c
    index 5afa6064d73e..229ba014cea0 100644
    --- a/arch/loongarch/kernel/unwind_guess.c
    +++ b/arch/loongarch/kernel/unwind_guess.c
    @@ -2,6 +2,7 @@
    /*
    * Copyright (C) 2022 Loongson Technology Corporation Limited
    */
    +#include <linux/ftrace.h>
    #include <linux/kernel.h>

    #include <asm/unwind.h>
    @@ -53,7 +54,8 @@ bool unwind_next_frame(struct unwind_state *state)
    state->sp < info->end;
    state->sp += sizeof(unsigned long)) {
    addr = *(unsigned long *)(state->sp);
    -
    + state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
    + addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
    if (__kernel_text_address(addr))
    return true;
    }
    diff --git a/arch/loongarch/kernel/unwind_prologue.c b/arch/loongarch/kernel/unwind_prologue.c
    index c5df4ae73e0d..48f7a120ec27 100644
    --- a/arch/loongarch/kernel/unwind_prologue.c
    +++ b/arch/loongarch/kernel/unwind_prologue.c
    @@ -2,6 +2,7 @@
    /*
    * Copyright (C) 2022 Loongson Technology Corporation Limited
    */
    +#include <linux/ftrace.h>
    #include <linux/kallsyms.h>

    #include <asm/inst.h>
    @@ -30,6 +31,8 @@ static bool unwind_by_guess(struct unwind_state *state)
    state->sp < info->end;
    state->sp += sizeof(unsigned long)) {
    addr = *(unsigned long *)(state->sp);
    + state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
    + addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
    if (__kernel_text_address(addr))
    return true;
    }
    @@ -171,8 +174,11 @@ bool unwind_next_frame(struct unwind_state *state)
    break;

    case UNWINDER_PROLOGUE:
    - if (unwind_by_prologue(state))
    + if (unwind_by_prologue(state)) {
    + state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
    + state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
    return true;
    + }

    if (info->type == STACK_TYPE_IRQ &&
    info->end == state->sp) {
    @@ -182,8 +188,9 @@ bool unwind_next_frame(struct unwind_state *state)
    if (user_mode(regs) || !__kernel_text_address(pc))
    return false;

    - state->pc = pc;
    state->sp = regs->regs[3];
    + state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
    + pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
    state->ra = regs->regs[1];
    state->first = true;
    get_stack_info(state->sp, state->task, info);
    --
    2.36.0
    \
     
     \ /
      Last update: 2022-11-15 03:58    [W:2.760 / U:0.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site