/* SPDX-License-Identifier: GPL-2.0 */1/* Copyright (C) 2017 Andes Technology Corporation */23#include <linux/init.h>4#include <linux/linkage.h>5#include <linux/cfi_types.h>6#include <linux/export.h>7#include <asm/asm.h>8#include <asm/csr.h>9#include <asm/unistd.h>10#include <asm/thread_info.h>11#include <asm/asm-offsets.h>12#include <asm/ftrace.h>1314.text1516.macro SAVE_ABI_STATE17addi sp, sp, -1618REG_S s0, 0*SZREG(sp)19REG_S ra, 1*SZREG(sp)20addi s0, sp, 1621.endm2223/*24* The call to ftrace_return_to_handler would overwrite the return25* register if a0 was not saved.26*/27.macro SAVE_RET_ABI_STATE28addi sp, sp, -FREGS_SIZE_ON_STACK29REG_S ra, FREGS_RA(sp)30REG_S s0, FREGS_S0(sp)31REG_S a0, FREGS_A0(sp)32REG_S a1, FREGS_A1(sp)33addi s0, sp, FREGS_SIZE_ON_STACK34.endm3536.macro RESTORE_ABI_STATE37REG_L ra, 1*SZREG(sp)38REG_L s0, 0*SZREG(sp)39addi sp, sp, 1640.endm4142.macro RESTORE_RET_ABI_STATE43REG_L ra, FREGS_RA(sp)44REG_L s0, FREGS_S0(sp)45REG_L a0, FREGS_A0(sp)46REG_L a1, FREGS_A1(sp)47addi sp, sp, FREGS_SIZE_ON_STACK48.endm4950SYM_TYPED_FUNC_START(ftrace_stub)51#ifdef CONFIG_DYNAMIC_FTRACE52.global _mcount53.set _mcount, ftrace_stub54#endif55ret56SYM_FUNC_END(ftrace_stub)5758#ifdef CONFIG_FUNCTION_GRAPH_TRACER59SYM_TYPED_FUNC_START(ftrace_stub_graph)60ret61SYM_FUNC_END(ftrace_stub_graph)6263SYM_FUNC_START(return_to_handler)64/*65* On implementing the frame point test, the ideal way is to compare the66* s0 (frame pointer, if enabled) on entry and the sp (stack pointer) on return.67* However, the psABI of variable-length-argument functions does not allow this.68*69* So alternatively we check the *old* frame pointer position, that is, the70* value stored in -16(s0) on entry, and the s0 on return.71*/72SAVE_RET_ABI_STATE73mv a0, sp74call ftrace_return_to_handler75mv a2, a076RESTORE_RET_ABI_STATE77jalr a278SYM_FUNC_END(return_to_handler)79#endif8081#ifndef CONFIG_DYNAMIC_FTRACE82SYM_FUNC_START(_mcount)83la t4, ftrace_stub84#ifdef CONFIG_FUNCTION_GRAPH_TRACER85la t0, ftrace_graph_return86REG_L t1, 0(t0)87bne t1, t4, .Ldo_ftrace_graph_caller8889la t3, ftrace_graph_entry90REG_L t2, 0(t3)91la t6, ftrace_graph_entry_stub92bne t2, t6, .Ldo_ftrace_graph_caller93#endif94la t3, ftrace_trace_function95REG_L t5, 0(t3)96bne t5, t4, .Ldo_trace97ret9899#ifdef CONFIG_FUNCTION_GRAPH_TRACER100/*101* A pseudo representation for the function graph tracer:102* prepare_to_return(&ra_to_caller_of_caller, ra_to_caller)103*/104.Ldo_ftrace_graph_caller:105addi a0, s0, -SZREG106mv a1, ra107#ifdef HAVE_FUNCTION_GRAPH_FP_TEST108REG_L a2, -2*SZREG(s0)109#endif110SAVE_ABI_STATE111call prepare_ftrace_return112RESTORE_ABI_STATE113ret114#endif115116/*117* A pseudo representation for the function tracer:118* (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller)119*/120.Ldo_trace:121REG_L a1, -SZREG(s0)122mv a0, ra123124SAVE_ABI_STATE125jalr t5126RESTORE_ABI_STATE127ret128SYM_FUNC_END(_mcount)129#endif130EXPORT_SYMBOL(_mcount)131132133