Commit a51ac524 authored by Qing Zhang's avatar Qing Zhang Committed by Huacai Chen
Browse files

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: default avatarQing Zhang <zhangqing@loongson.cn>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent ac7127e1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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;
};

+1 −1
Original line number Diff line number Diff line
@@ -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 −1
Original line number Diff line number Diff line
@@ -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;
		}
+11 −4
Original line number Diff line number Diff line
@@ -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;