forked from Minki/linux
aea4c671fb
Cc: Greentime Hu <greentime@andestech.com> Signed-off-by: Alan Kao <alankao@andestech.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
240 lines
4.6 KiB
ArmAsm
240 lines
4.6 KiB
ArmAsm
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright (C) 2017 Andes Technology Corporation */
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/linkage.h>
|
|
#include <asm/asm.h>
|
|
#include <asm/csr.h>
|
|
#include <asm/unistd.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm-generic/export.h>
|
|
#include <asm/ftrace.h>
|
|
|
|
.text
|
|
|
|
.macro SAVE_ABI_STATE
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
addi sp, sp, -48
|
|
sd s0, 32(sp)
|
|
sd ra, 40(sp)
|
|
addi s0, sp, 48
|
|
sd t0, 24(sp)
|
|
sd t1, 16(sp)
|
|
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
|
sd t2, 8(sp)
|
|
#endif
|
|
#else
|
|
addi sp, sp, -16
|
|
sd s0, 0(sp)
|
|
sd ra, 8(sp)
|
|
addi s0, sp, 16
|
|
#endif
|
|
.endm
|
|
|
|
.macro RESTORE_ABI_STATE
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
ld s0, 32(sp)
|
|
ld ra, 40(sp)
|
|
addi sp, sp, 48
|
|
#else
|
|
ld ra, 8(sp)
|
|
ld s0, 0(sp)
|
|
addi sp, sp, 16
|
|
#endif
|
|
.endm
|
|
|
|
.macro RESTORE_GRAPH_ARGS
|
|
ld a0, 24(sp)
|
|
ld a1, 16(sp)
|
|
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
|
ld a2, 8(sp)
|
|
#endif
|
|
.endm
|
|
|
|
ENTRY(ftrace_graph_caller)
|
|
addi sp, sp, -16
|
|
sd s0, 0(sp)
|
|
sd ra, 8(sp)
|
|
addi s0, sp, 16
|
|
ftrace_graph_call:
|
|
.global ftrace_graph_call
|
|
/*
|
|
* Calling ftrace_enable/disable_ftrace_graph_caller would overwrite the
|
|
* call below. Check ftrace_modify_all_code for details.
|
|
*/
|
|
call ftrace_stub
|
|
ld ra, 8(sp)
|
|
ld s0, 0(sp)
|
|
addi sp, sp, 16
|
|
ret
|
|
ENDPROC(ftrace_graph_caller)
|
|
|
|
ENTRY(ftrace_caller)
|
|
/*
|
|
* a0: the address in the caller when calling ftrace_caller
|
|
* a1: the caller's return address
|
|
* a2: the address of global variable function_trace_op
|
|
*/
|
|
ld a1, -8(s0)
|
|
addi a0, ra, -MCOUNT_INSN_SIZE
|
|
la t5, function_trace_op
|
|
ld a2, 0(t5)
|
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
/*
|
|
* the graph tracer (specifically, prepare_ftrace_return) needs these
|
|
* arguments but for now the function tracer occupies the regs, so we
|
|
* save them in temporary regs to recover later.
|
|
*/
|
|
addi t0, s0, -8
|
|
mv t1, a0
|
|
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
|
ld t2, -16(s0)
|
|
#endif
|
|
#endif
|
|
|
|
SAVE_ABI_STATE
|
|
ftrace_call:
|
|
.global ftrace_call
|
|
/*
|
|
* For the dynamic ftrace to work, here we should reserve at least
|
|
* 8 bytes for a functional auipc-jalr pair. The following call
|
|
* serves this purpose.
|
|
*
|
|
* Calling ftrace_update_ftrace_func would overwrite the nops below.
|
|
* Check ftrace_modify_all_code for details.
|
|
*/
|
|
call ftrace_stub
|
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
RESTORE_GRAPH_ARGS
|
|
call ftrace_graph_caller
|
|
#endif
|
|
|
|
RESTORE_ABI_STATE
|
|
ret
|
|
ENDPROC(ftrace_caller)
|
|
|
|
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
|
|
.macro SAVE_ALL
|
|
addi sp, sp, -(PT_SIZE_ON_STACK+16)
|
|
sd s0, (PT_SIZE_ON_STACK)(sp)
|
|
sd ra, (PT_SIZE_ON_STACK+8)(sp)
|
|
addi s0, sp, (PT_SIZE_ON_STACK+16)
|
|
|
|
sd x1, PT_RA(sp)
|
|
sd x2, PT_SP(sp)
|
|
sd x3, PT_GP(sp)
|
|
sd x4, PT_TP(sp)
|
|
sd x5, PT_T0(sp)
|
|
sd x6, PT_T1(sp)
|
|
sd x7, PT_T2(sp)
|
|
sd x8, PT_S0(sp)
|
|
sd x9, PT_S1(sp)
|
|
sd x10, PT_A0(sp)
|
|
sd x11, PT_A1(sp)
|
|
sd x12, PT_A2(sp)
|
|
sd x13, PT_A3(sp)
|
|
sd x14, PT_A4(sp)
|
|
sd x15, PT_A5(sp)
|
|
sd x16, PT_A6(sp)
|
|
sd x17, PT_A7(sp)
|
|
sd x18, PT_S2(sp)
|
|
sd x19, PT_S3(sp)
|
|
sd x20, PT_S4(sp)
|
|
sd x21, PT_S5(sp)
|
|
sd x22, PT_S6(sp)
|
|
sd x23, PT_S7(sp)
|
|
sd x24, PT_S8(sp)
|
|
sd x25, PT_S9(sp)
|
|
sd x26, PT_S10(sp)
|
|
sd x27, PT_S11(sp)
|
|
sd x28, PT_T3(sp)
|
|
sd x29, PT_T4(sp)
|
|
sd x30, PT_T5(sp)
|
|
sd x31, PT_T6(sp)
|
|
.endm
|
|
|
|
.macro RESTORE_ALL
|
|
ld x1, PT_RA(sp)
|
|
ld x2, PT_SP(sp)
|
|
ld x3, PT_GP(sp)
|
|
ld x4, PT_TP(sp)
|
|
ld x5, PT_T0(sp)
|
|
ld x6, PT_T1(sp)
|
|
ld x7, PT_T2(sp)
|
|
ld x8, PT_S0(sp)
|
|
ld x9, PT_S1(sp)
|
|
ld x10, PT_A0(sp)
|
|
ld x11, PT_A1(sp)
|
|
ld x12, PT_A2(sp)
|
|
ld x13, PT_A3(sp)
|
|
ld x14, PT_A4(sp)
|
|
ld x15, PT_A5(sp)
|
|
ld x16, PT_A6(sp)
|
|
ld x17, PT_A7(sp)
|
|
ld x18, PT_S2(sp)
|
|
ld x19, PT_S3(sp)
|
|
ld x20, PT_S4(sp)
|
|
ld x21, PT_S5(sp)
|
|
ld x22, PT_S6(sp)
|
|
ld x23, PT_S7(sp)
|
|
ld x24, PT_S8(sp)
|
|
ld x25, PT_S9(sp)
|
|
ld x26, PT_S10(sp)
|
|
ld x27, PT_S11(sp)
|
|
ld x28, PT_T3(sp)
|
|
ld x29, PT_T4(sp)
|
|
ld x30, PT_T5(sp)
|
|
ld x31, PT_T6(sp)
|
|
|
|
ld s0, (PT_SIZE_ON_STACK)(sp)
|
|
ld ra, (PT_SIZE_ON_STACK+8)(sp)
|
|
addi sp, sp, (PT_SIZE_ON_STACK+16)
|
|
.endm
|
|
|
|
.macro RESTORE_GRAPH_REG_ARGS
|
|
ld a0, PT_T0(sp)
|
|
ld a1, PT_T1(sp)
|
|
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
|
ld a2, PT_T2(sp)
|
|
#endif
|
|
.endm
|
|
|
|
/*
|
|
* Most of the contents are the same as ftrace_caller.
|
|
*/
|
|
ENTRY(ftrace_regs_caller)
|
|
/*
|
|
* a3: the address of all registers in the stack
|
|
*/
|
|
ld a1, -8(s0)
|
|
addi a0, ra, -MCOUNT_INSN_SIZE
|
|
la t5, function_trace_op
|
|
ld a2, 0(t5)
|
|
addi a3, sp, -(PT_SIZE_ON_STACK+16)
|
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
addi t0, s0, -8
|
|
mv t1, a0
|
|
#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
|
|
ld t2, -16(s0)
|
|
#endif
|
|
#endif
|
|
SAVE_ALL
|
|
|
|
ftrace_regs_call:
|
|
.global ftrace_regs_call
|
|
call ftrace_stub
|
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
RESTORE_GRAPH_REG_ARGS
|
|
call ftrace_graph_caller
|
|
#endif
|
|
|
|
RESTORE_ALL
|
|
ret
|
|
ENDPROC(ftrace_regs_caller)
|
|
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
|