fgraph: Replace fgraph_ret_regs with ftrace_regs
Use ftrace_regs instead of fgraph_ret_regs for tracing return value on function_graph tracer because of simplifying the callback interface. The CONFIG_HAVE_FUNCTION_GRAPH_RETVAL is also replaced by CONFIG_HAVE_FUNCTION_GRAPH_FREGS. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Acked-by: Heiko Carstens <hca@linux.ibm.com> Acked-by: Will Deacon <will@kernel.org> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Alexei Starovoitov <alexei.starovoitov@gmail.com> Cc: Florent Revest <revest@chromium.org> Cc: Martin KaFai Lau <martin.lau@linux.dev> Cc: bpf <bpf@vger.kernel.org> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Alan Maguire <alan.maguire@oracle.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: WANG Xuerui <kernel@xen0n.name> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Alexander Gordeev <agordeev@linux.ibm.com> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Christian Borntraeger <borntraeger@linux.ibm.com> Cc: Sven Schnelle <svens@linux.ibm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: x86@kernel.org Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lore.kernel.org/173518991508.391279.16635322774382197642.stgit@devnote2 Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
41705c4262
commit
a3ed4157b7
24 changed files with 119 additions and 207 deletions
|
@ -219,6 +219,7 @@ config ARM64
|
|||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_FREGS
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL
|
||||
select HAVE_GCC_PLUGINS
|
||||
|
|
|
@ -129,6 +129,12 @@ ftrace_override_function_with_return(struct ftrace_regs *fregs)
|
|||
arch_ftrace_regs(fregs)->pc = arch_ftrace_regs(fregs)->lr;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return arch_ftrace_regs(fregs)->fp;
|
||||
}
|
||||
|
||||
int ftrace_regs_query_register_offset(const char *name);
|
||||
|
||||
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
|
||||
|
@ -186,23 +192,6 @@ static inline bool arch_syscall_match_sym_name(const char *sym,
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
/* x0 - x7 */
|
||||
unsigned long regs[8];
|
||||
|
||||
unsigned long fp;
|
||||
unsigned long __unused;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->regs[0];
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->fp;
|
||||
}
|
||||
|
||||
void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
|
||||
unsigned long frame_pointer);
|
||||
|
|
|
@ -179,18 +179,6 @@ int main(void)
|
|||
DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func));
|
||||
#endif
|
||||
BLANK();
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
DEFINE(FGRET_REGS_X0, offsetof(struct fgraph_ret_regs, regs[0]));
|
||||
DEFINE(FGRET_REGS_X1, offsetof(struct fgraph_ret_regs, regs[1]));
|
||||
DEFINE(FGRET_REGS_X2, offsetof(struct fgraph_ret_regs, regs[2]));
|
||||
DEFINE(FGRET_REGS_X3, offsetof(struct fgraph_ret_regs, regs[3]));
|
||||
DEFINE(FGRET_REGS_X4, offsetof(struct fgraph_ret_regs, regs[4]));
|
||||
DEFINE(FGRET_REGS_X5, offsetof(struct fgraph_ret_regs, regs[5]));
|
||||
DEFINE(FGRET_REGS_X6, offsetof(struct fgraph_ret_regs, regs[6]));
|
||||
DEFINE(FGRET_REGS_X7, offsetof(struct fgraph_ret_regs, regs[7]));
|
||||
DEFINE(FGRET_REGS_FP, offsetof(struct fgraph_ret_regs, fp));
|
||||
DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
#endif
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
DEFINE(FTRACE_OPS_DIRECT_CALL, offsetof(struct ftrace_ops, direct_call));
|
||||
#endif
|
||||
|
|
|
@ -329,24 +329,28 @@ SYM_FUNC_END(ftrace_stub_graph)
|
|||
* @fp is checked against the value passed by ftrace_graph_caller().
|
||||
*/
|
||||
SYM_CODE_START(return_to_handler)
|
||||
/* save return value regs */
|
||||
sub sp, sp, #FGRET_REGS_SIZE
|
||||
stp x0, x1, [sp, #FGRET_REGS_X0]
|
||||
stp x2, x3, [sp, #FGRET_REGS_X2]
|
||||
stp x4, x5, [sp, #FGRET_REGS_X4]
|
||||
stp x6, x7, [sp, #FGRET_REGS_X6]
|
||||
str x29, [sp, #FGRET_REGS_FP] // parent's fp
|
||||
/* Make room for ftrace_regs */
|
||||
sub sp, sp, #FREGS_SIZE
|
||||
|
||||
/* Save return value regs */
|
||||
stp x0, x1, [sp, #FREGS_X0]
|
||||
stp x2, x3, [sp, #FREGS_X2]
|
||||
stp x4, x5, [sp, #FREGS_X4]
|
||||
stp x6, x7, [sp, #FREGS_X6]
|
||||
|
||||
/* Save the callsite's FP */
|
||||
str x29, [sp, #FREGS_FP]
|
||||
|
||||
mov x0, sp
|
||||
bl ftrace_return_to_handler // addr = ftrace_return_to_hander(regs);
|
||||
bl ftrace_return_to_handler // addr = ftrace_return_to_hander(fregs);
|
||||
mov x30, x0 // restore the original return address
|
||||
|
||||
/* restore return value regs */
|
||||
ldp x0, x1, [sp, #FGRET_REGS_X0]
|
||||
ldp x2, x3, [sp, #FGRET_REGS_X2]
|
||||
ldp x4, x5, [sp, #FGRET_REGS_X4]
|
||||
ldp x6, x7, [sp, #FGRET_REGS_X6]
|
||||
add sp, sp, #FGRET_REGS_SIZE
|
||||
/* Restore return value regs */
|
||||
ldp x0, x1, [sp, #FREGS_X0]
|
||||
ldp x2, x3, [sp, #FREGS_X2]
|
||||
ldp x4, x5, [sp, #FREGS_X4]
|
||||
ldp x6, x7, [sp, #FREGS_X6]
|
||||
add sp, sp, #FREGS_SIZE
|
||||
|
||||
ret
|
||||
SYM_CODE_END(return_to_handler)
|
||||
|
|
|
@ -137,7 +137,7 @@ config LOONGARCH
|
|||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_FREGS
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GCC_PLUGINS
|
||||
|
|
|
@ -57,6 +57,10 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip)
|
|||
instruction_pointer_set(&arch_ftrace_regs(fregs)->regs, ip);
|
||||
}
|
||||
|
||||
#undef ftrace_regs_get_frame_pointer
|
||||
#define ftrace_regs_get_frame_pointer(fregs) \
|
||||
(arch_ftrace_regs(fregs)->regs.regs[22])
|
||||
|
||||
#define ftrace_graph_func ftrace_graph_func
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs);
|
||||
|
@ -78,26 +82,4 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
|
|||
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
/* a0 - a1 */
|
||||
unsigned long regs[2];
|
||||
|
||||
unsigned long fp;
|
||||
unsigned long __unused;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->regs[0];
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->fp;
|
||||
}
|
||||
#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_LOONGARCH_FTRACE_H */
|
||||
|
|
|
@ -280,18 +280,6 @@ static void __used output_pbe_defines(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
static void __used output_fgraph_ret_regs_defines(void)
|
||||
{
|
||||
COMMENT("LoongArch fgraph_ret_regs offsets.");
|
||||
OFFSET(FGRET_REGS_A0, fgraph_ret_regs, regs[0]);
|
||||
OFFSET(FGRET_REGS_A1, fgraph_ret_regs, regs[1]);
|
||||
OFFSET(FGRET_REGS_FP, fgraph_ret_regs, fp);
|
||||
DEFINE(FGRET_REGS_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
BLANK();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __used output_kvm_defines(void)
|
||||
{
|
||||
COMMENT("KVM/LoongArch Specific offsets.");
|
||||
|
|
|
@ -79,10 +79,11 @@ SYM_FUNC_START(ftrace_graph_caller)
|
|||
SYM_FUNC_END(ftrace_graph_caller)
|
||||
|
||||
SYM_FUNC_START(return_to_handler)
|
||||
PTR_ADDI sp, sp, -FGRET_REGS_SIZE
|
||||
PTR_S a0, sp, FGRET_REGS_A0
|
||||
PTR_S a1, sp, FGRET_REGS_A1
|
||||
PTR_S zero, sp, FGRET_REGS_FP
|
||||
/* Save return value regs */
|
||||
PTR_ADDI sp, sp, -PT_SIZE
|
||||
PTR_S a0, sp, PT_R4
|
||||
PTR_S a1, sp, PT_R5
|
||||
PTR_S zero, sp, PT_R22
|
||||
|
||||
move a0, sp
|
||||
bl ftrace_return_to_handler
|
||||
|
@ -90,9 +91,11 @@ SYM_FUNC_START(return_to_handler)
|
|||
/* Restore the real parent address: a0 -> ra */
|
||||
move ra, a0
|
||||
|
||||
PTR_L a0, sp, FGRET_REGS_A0
|
||||
PTR_L a1, sp, FGRET_REGS_A1
|
||||
PTR_ADDI sp, sp, FGRET_REGS_SIZE
|
||||
/* Restore return value regs */
|
||||
PTR_L a0, sp, PT_R4
|
||||
PTR_L a1, sp, PT_R5
|
||||
PTR_ADDI sp, sp, PT_SIZE
|
||||
|
||||
jr ra
|
||||
SYM_FUNC_END(return_to_handler)
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
|
|
@ -140,19 +140,19 @@ SYM_CODE_END(ftrace_graph_caller)
|
|||
SYM_CODE_START(return_to_handler)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
/* Save return value regs */
|
||||
PTR_ADDI sp, sp, -FGRET_REGS_SIZE
|
||||
PTR_S a0, sp, FGRET_REGS_A0
|
||||
PTR_S a1, sp, FGRET_REGS_A1
|
||||
PTR_S zero, sp, FGRET_REGS_FP
|
||||
PTR_ADDI sp, sp, -PT_SIZE
|
||||
PTR_S a0, sp, PT_R4
|
||||
PTR_S a1, sp, PT_R5
|
||||
PTR_S zero, sp, PT_R22
|
||||
|
||||
move a0, sp
|
||||
bl ftrace_return_to_handler
|
||||
move ra, a0
|
||||
|
||||
/* Restore return value regs */
|
||||
PTR_L a0, sp, FGRET_REGS_A0
|
||||
PTR_L a1, sp, FGRET_REGS_A1
|
||||
PTR_ADDI sp, sp, FGRET_REGS_SIZE
|
||||
PTR_L a0, sp, PT_R4
|
||||
PTR_L a1, sp, PT_R5
|
||||
PTR_ADDI sp, sp, PT_SIZE
|
||||
|
||||
jr ra
|
||||
SYM_CODE_END(return_to_handler)
|
||||
|
|
|
@ -148,7 +148,7 @@ config RISCV
|
|||
select HAVE_DYNAMIC_FTRACE_WITH_ARGS if HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_FREGS
|
||||
select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION
|
||||
select HAVE_EBPF_JIT if MMU
|
||||
select HAVE_GUP_FAST if MMU
|
||||
|
|
|
@ -168,6 +168,11 @@ static __always_inline unsigned long ftrace_regs_get_stack_pointer(const struct
|
|||
return arch_ftrace_regs(fregs)->sp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return arch_ftrace_regs(fregs)->s0;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs,
|
||||
unsigned int n)
|
||||
{
|
||||
|
@ -208,25 +213,4 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsi
|
|||
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
unsigned long a1;
|
||||
unsigned long a0;
|
||||
unsigned long s0;
|
||||
unsigned long ra;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->a0;
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->s0;
|
||||
}
|
||||
#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_RISCV_FTRACE_H */
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <asm/asm-offsets.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
||||
#define ABI_SIZE_ON_STACK 80
|
||||
|
||||
.text
|
||||
|
||||
.macro SAVE_ABI_STATE
|
||||
|
@ -26,12 +28,12 @@
|
|||
* register if a0 was not saved.
|
||||
*/
|
||||
.macro SAVE_RET_ABI_STATE
|
||||
addi sp, sp, -4*SZREG
|
||||
REG_S s0, 2*SZREG(sp)
|
||||
REG_S ra, 3*SZREG(sp)
|
||||
REG_S a0, 1*SZREG(sp)
|
||||
REG_S a1, 0*SZREG(sp)
|
||||
addi s0, sp, 4*SZREG
|
||||
addi sp, sp, -ABI_SIZE_ON_STACK
|
||||
REG_S ra, 1*SZREG(sp)
|
||||
REG_S s0, 8*SZREG(sp)
|
||||
REG_S a0, 10*SZREG(sp)
|
||||
REG_S a1, 11*SZREG(sp)
|
||||
addi s0, sp, ABI_SIZE_ON_STACK
|
||||
.endm
|
||||
|
||||
.macro RESTORE_ABI_STATE
|
||||
|
@ -41,11 +43,11 @@
|
|||
.endm
|
||||
|
||||
.macro RESTORE_RET_ABI_STATE
|
||||
REG_L ra, 3*SZREG(sp)
|
||||
REG_L s0, 2*SZREG(sp)
|
||||
REG_L a0, 1*SZREG(sp)
|
||||
REG_L a1, 0*SZREG(sp)
|
||||
addi sp, sp, 4*SZREG
|
||||
REG_L ra, 1*SZREG(sp)
|
||||
REG_L s0, 8*SZREG(sp)
|
||||
REG_L a0, 10*SZREG(sp)
|
||||
REG_L a1, 11*SZREG(sp)
|
||||
addi sp, sp, ABI_SIZE_ON_STACK
|
||||
.endm
|
||||
|
||||
SYM_TYPED_FUNC_START(ftrace_stub)
|
||||
|
|
|
@ -192,7 +192,7 @@ config S390
|
|||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL
|
||||
select HAVE_FUNCTION_GRAPH_FREGS
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GCC_PLUGINS
|
||||
|
|
|
@ -62,23 +62,6 @@ static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
unsigned long gpr2;
|
||||
unsigned long fp;
|
||||
};
|
||||
|
||||
static __always_inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->gpr2;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->fp;
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
unsigned long ip)
|
||||
|
@ -86,6 +69,13 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
|||
arch_ftrace_regs(fregs)->regs.psw.addr = ip;
|
||||
}
|
||||
|
||||
#undef ftrace_regs_get_frame_pointer
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_frame_pointer(struct ftrace_regs *fregs)
|
||||
{
|
||||
return ftrace_regs_get_stack_pointer(fregs);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
/*
|
||||
* When an ftrace registered caller is tracing a function that is
|
||||
|
|
|
@ -175,12 +175,6 @@ int main(void)
|
|||
DEFINE(OLDMEM_SIZE, PARMAREA + offsetof(struct parmarea, oldmem_size));
|
||||
DEFINE(COMMAND_LINE, PARMAREA + offsetof(struct parmarea, command_line));
|
||||
DEFINE(MAX_COMMAND_LINE_SIZE, PARMAREA + offsetof(struct parmarea, max_command_line_size));
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/* function graph return value tracing */
|
||||
OFFSET(__FGRAPH_RET_GPR2, fgraph_ret_regs, gpr2);
|
||||
OFFSET(__FGRAPH_RET_FP, fgraph_ret_regs, fp);
|
||||
DEFINE(__FGRAPH_RET_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
#endif
|
||||
OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs);
|
||||
DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs));
|
||||
|
||||
|
|
|
@ -134,14 +134,14 @@ SYM_CODE_END(ftrace_common)
|
|||
SYM_FUNC_START(return_to_handler)
|
||||
stmg %r2,%r5,32(%r15)
|
||||
lgr %r1,%r15
|
||||
aghi %r15,-(STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE)
|
||||
# allocate ftrace_regs and stack frame for ftrace_return_to_handler
|
||||
aghi %r15,-STACK_FRAME_SIZE_FREGS
|
||||
stg %r1,__SF_BACKCHAIN(%r15)
|
||||
la %r3,STACK_FRAME_OVERHEAD(%r15)
|
||||
stg %r1,__FGRAPH_RET_FP(%r3)
|
||||
stg %r2,__FGRAPH_RET_GPR2(%r3)
|
||||
lgr %r2,%r3
|
||||
stg %r2,(STACK_FREGS_PTREGS_GPRS+2*8)(%r15)
|
||||
stg %r1,(STACK_FREGS_PTREGS_GPRS+15*8)(%r15)
|
||||
la %r2,STACK_FRAME_OVERHEAD(%r15)
|
||||
brasl %r14,ftrace_return_to_handler
|
||||
aghi %r15,STACK_FRAME_OVERHEAD+__FGRAPH_RET_SIZE
|
||||
aghi %r15,STACK_FRAME_SIZE_FREGS
|
||||
lgr %r14,%r2
|
||||
lmg %r2,%r5,32(%r15)
|
||||
BR_EX %r14
|
||||
|
|
|
@ -235,7 +235,7 @@ config X86
|
|||
select HAVE_GUP_FAST
|
||||
select HAVE_FENTRY if X86_64 || DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_FREGS if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER if X86_32 || (X86_64 && DYNAMIC_FTRACE)
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_GCC_PLUGINS
|
||||
|
|
|
@ -134,24 +134,4 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
|
|||
#endif /* !COMPILE_OFFSETS */
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
struct fgraph_ret_regs {
|
||||
unsigned long ax;
|
||||
unsigned long dx;
|
||||
unsigned long bp;
|
||||
};
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->ax;
|
||||
}
|
||||
|
||||
static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs)
|
||||
{
|
||||
return ret_regs->bp;
|
||||
}
|
||||
#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_FTRACE_H */
|
||||
|
|
|
@ -187,14 +187,15 @@ SYM_CODE_END(ftrace_graph_caller)
|
|||
|
||||
.globl return_to_handler
|
||||
return_to_handler:
|
||||
pushl $0
|
||||
pushl %edx
|
||||
pushl %eax
|
||||
subl $(PTREGS_SIZE), %esp
|
||||
movl $0, PT_EBP(%esp)
|
||||
movl %edx, PT_EDX(%esp)
|
||||
movl %eax, PT_EAX(%esp)
|
||||
movl %esp, %eax
|
||||
call ftrace_return_to_handler
|
||||
movl %eax, %ecx
|
||||
popl %eax
|
||||
popl %edx
|
||||
addl $4, %esp # skip ebp
|
||||
movl PT_EAX(%esp), %eax
|
||||
movl PT_EDX(%esp), %edx
|
||||
addl $(PTREGS_SIZE), %esp
|
||||
JMP_NOSPEC ecx
|
||||
#endif
|
||||
|
|
|
@ -348,21 +348,22 @@ STACK_FRAME_NON_STANDARD_FP(__fentry__)
|
|||
SYM_CODE_START(return_to_handler)
|
||||
UNWIND_HINT_UNDEFINED
|
||||
ANNOTATE_NOENDBR
|
||||
subq $24, %rsp
|
||||
|
||||
/* Save the return values */
|
||||
movq %rax, (%rsp)
|
||||
movq %rdx, 8(%rsp)
|
||||
movq %rbp, 16(%rsp)
|
||||
/* Save ftrace_regs for function exit context */
|
||||
subq $(FRAME_SIZE), %rsp
|
||||
|
||||
movq %rax, RAX(%rsp)
|
||||
movq %rdx, RDX(%rsp)
|
||||
movq %rbp, RBP(%rsp)
|
||||
movq %rsp, %rdi
|
||||
|
||||
call ftrace_return_to_handler
|
||||
|
||||
movq %rax, %rdi
|
||||
movq 8(%rsp), %rdx
|
||||
movq (%rsp), %rax
|
||||
movq RDX(%rsp), %rdx
|
||||
movq RAX(%rsp), %rax
|
||||
|
||||
addq $24, %rsp
|
||||
addq $(FRAME_SIZE), %rsp
|
||||
/*
|
||||
* Jump back to the old return address. This cannot be JMP_NOSPEC rdi
|
||||
* since IBT would demand that contain ENDBR, which simply isn't so for
|
||||
|
|
|
@ -43,9 +43,8 @@ struct dyn_ftrace;
|
|||
|
||||
char *arch_ftrace_match_adjust(char *str, const char *search);
|
||||
|
||||
#ifdef CONFIG_HAVE_FUNCTION_GRAPH_RETVAL
|
||||
struct fgraph_ret_regs;
|
||||
unsigned long ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs);
|
||||
#ifdef CONFIG_HAVE_FUNCTION_GRAPH_FREGS
|
||||
unsigned long ftrace_return_to_handler(struct ftrace_regs *fregs);
|
||||
#else
|
||||
unsigned long ftrace_return_to_handler(unsigned long frame_pointer);
|
||||
#endif
|
||||
|
@ -134,6 +133,13 @@ extern int ftrace_enabled;
|
|||
* Also, architecture dependent fields can be used for internal process.
|
||||
* (e.g. orig_ax on x86_64)
|
||||
*
|
||||
* Basically, ftrace_regs stores the registers related to the context.
|
||||
* On function entry, registers for function parameters and hooking the
|
||||
* function call are stored, and on function exit, registers for function
|
||||
* return value and frame pointers are stored.
|
||||
*
|
||||
* And also, it dpends on the context that which registers are restored
|
||||
* from the ftrace_regs.
|
||||
* On the function entry, those registers will be restored except for
|
||||
* the stack pointer, so that user can change the function parameters
|
||||
* and instruction pointer (e.g. live patching.)
|
||||
|
|
|
@ -30,6 +30,8 @@ struct ftrace_regs;
|
|||
override_function_with_return(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_query_register_offset(name) \
|
||||
regs_query_register_offset(name)
|
||||
#define ftrace_regs_get_frame_pointer(fregs) \
|
||||
frame_pointer(&arch_ftrace_regs(fregs)->regs)
|
||||
|
||||
#endif /* HAVE_ARCH_FTRACE_REGS */
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ config HAVE_FUNCTION_GRAPH_TRACER
|
|||
help
|
||||
See Documentation/trace/ftrace-design.rst
|
||||
|
||||
config HAVE_FUNCTION_GRAPH_RETVAL
|
||||
config HAVE_FUNCTION_GRAPH_FREGS
|
||||
bool
|
||||
|
||||
config HAVE_DYNAMIC_FTRACE
|
||||
|
@ -232,7 +232,7 @@ config FUNCTION_GRAPH_TRACER
|
|||
|
||||
config FUNCTION_GRAPH_RETVAL
|
||||
bool "Kernel Function Graph Return Value"
|
||||
depends on HAVE_FUNCTION_GRAPH_RETVAL
|
||||
depends on HAVE_FUNCTION_GRAPH_FREGS
|
||||
depends on FUNCTION_GRAPH_TRACER
|
||||
default n
|
||||
help
|
||||
|
|
|
@ -801,15 +801,12 @@ static struct notifier_block ftrace_suspend_notifier = {
|
|||
.notifier_call = ftrace_suspend_notifier_call,
|
||||
};
|
||||
|
||||
/* fgraph_ret_regs is not defined without CONFIG_FUNCTION_GRAPH_RETVAL */
|
||||
struct fgraph_ret_regs;
|
||||
|
||||
/*
|
||||
* Send the trace to the ring-buffer.
|
||||
* @return the original return address.
|
||||
*/
|
||||
static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs,
|
||||
unsigned long frame_pointer)
|
||||
static inline unsigned long
|
||||
__ftrace_return_to_handler(struct ftrace_regs *fregs, unsigned long frame_pointer)
|
||||
{
|
||||
struct ftrace_ret_stack *ret_stack;
|
||||
struct ftrace_graph_ret trace;
|
||||
|
@ -829,7 +826,7 @@ static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs
|
|||
|
||||
trace.rettime = trace_clock_local();
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_RETVAL
|
||||
trace.retval = fgraph_ret_regs_return_value(ret_regs);
|
||||
trace.retval = ftrace_regs_get_return_value(fregs);
|
||||
#endif
|
||||
|
||||
bitmap = get_bitmap_bits(current, offset);
|
||||
|
@ -864,14 +861,14 @@ static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs
|
|||
}
|
||||
|
||||
/*
|
||||
* After all architecures have selected HAVE_FUNCTION_GRAPH_RETVAL, we can
|
||||
* leave only ftrace_return_to_handler(ret_regs).
|
||||
* After all architecures have selected HAVE_FUNCTION_GRAPH_FREGS, we can
|
||||
* leave only ftrace_return_to_handler(fregs).
|
||||
*/
|
||||
#ifdef CONFIG_HAVE_FUNCTION_GRAPH_RETVAL
|
||||
unsigned long ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs)
|
||||
#ifdef CONFIG_HAVE_FUNCTION_GRAPH_FREGS
|
||||
unsigned long ftrace_return_to_handler(struct ftrace_regs *fregs)
|
||||
{
|
||||
return __ftrace_return_to_handler(ret_regs,
|
||||
fgraph_ret_regs_frame_pointer(ret_regs));
|
||||
return __ftrace_return_to_handler(fregs,
|
||||
ftrace_regs_get_frame_pointer(fregs));
|
||||
}
|
||||
#else
|
||||
unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
|
||||
|
|
Loading…
Add table
Reference in a new issue