LoongArch/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support
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> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
This commit is contained in:
parent
ac7127e1cc
commit
a51ac5246d
|
@ -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 */
|
||||
|
@ -24,6 +26,7 @@ struct dyn_ftrace;
|
|||
struct dyn_arch_ftrace { };
|
||||
|
||||
#define ARCH_SUPPORTS_FTRACE_OPS 1
|
||||
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
|
||||
|
||||
#define ftrace_init_nop ftrace_init_nop
|
||||
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -135,7 +135,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ftrace.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;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Loongson Technology Corporation Limited
|
||||
*/
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kallsyms.h>
|
||||
|
||||
#include <asm/inst.h>
|
||||
|
@ -42,6 +43,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;
|
||||
}
|
||||
|
@ -174,8 +177,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) {
|
||||
|
@ -185,10 +191,11 @@ 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->ra = regs->regs[1];
|
||||
state->first = true;
|
||||
state->ra = regs->regs[1];
|
||||
state->sp = regs->regs[3];
|
||||
state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
|
||||
pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET));
|
||||
get_stack_info(state->sp, state->task, info);
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue