mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
ftrace: Make ftrace_regs abstract from direct use
ftrace_regs was created to hold registers that store information to save function parameters, return value and stack. Since it is a subset of pt_regs, it should only be used by its accessor functions. But because pt_regs can easily be taken from ftrace_regs (on most archs), it is tempting to use it directly. But when running on other architectures, it may fail to build or worse, build but crash the kernel! Instead, make struct ftrace_regs an empty structure and have the architectures define __arch_ftrace_regs and all the accessor functions will typecast to it to get to the actual fields. This will help avoid usage of ftrace_regs directly. Link: https://lore.kernel.org/all/20241007171027.629bdafd@gandalf.local.home/ Cc: "linux-arch@vger.kernel.org" <linux-arch@vger.kernel.org> Cc: "x86@kernel.org" <x86@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: WANG Xuerui <kernel@xen0n.name> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Nicholas Piggin <npiggin@gmail.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Naveen N Rao <naveen@kernel.org> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Paul Walmsley <paul.walmsley@sifive.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Albert Ou <aou@eecs.berkeley.edu> Cc: Heiko Carstens <hca@linux.ibm.com> Cc: Vasily Gorbik <gor@linux.ibm.com> Cc: Alexander Gordeev <agordeev@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@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Link: https://lore.kernel.org/20241008230628.958778821@goodmis.org Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Acked-by: Heiko Carstens <hca@linux.ibm.com> # s390 Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
c73eb02a47
commit
7888af4166
@ -56,6 +56,8 @@ unsigned long ftrace_call_adjust(unsigned long addr);
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
struct dyn_ftrace;
|
||||
struct ftrace_ops;
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
#define arch_ftrace_get_regs(regs) NULL
|
||||
|
||||
@ -63,7 +65,7 @@ struct ftrace_ops;
|
||||
* Note: sizeof(struct ftrace_regs) must be a multiple of 16 to ensure correct
|
||||
* stack alignment
|
||||
*/
|
||||
struct ftrace_regs {
|
||||
struct __arch_ftrace_regs {
|
||||
/* x0 - x8 */
|
||||
unsigned long regs[9];
|
||||
|
||||
@ -83,47 +85,47 @@ struct ftrace_regs {
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->pc;
|
||||
return arch_ftrace_regs(fregs)->pc;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
unsigned long pc)
|
||||
{
|
||||
fregs->pc = pc;
|
||||
arch_ftrace_regs(fregs)->pc = pc;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->sp;
|
||||
return arch_ftrace_regs(fregs)->sp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n)
|
||||
{
|
||||
if (n < 8)
|
||||
return fregs->regs[n];
|
||||
return arch_ftrace_regs(fregs)->regs[n];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->regs[0];
|
||||
return arch_ftrace_regs(fregs)->regs[0];
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_return_value(struct ftrace_regs *fregs,
|
||||
unsigned long ret)
|
||||
{
|
||||
fregs->regs[0] = ret;
|
||||
arch_ftrace_regs(fregs)->regs[0] = ret;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_override_function_with_return(struct ftrace_regs *fregs)
|
||||
{
|
||||
fregs->pc = fregs->lr;
|
||||
arch_ftrace_regs(fregs)->pc = arch_ftrace_regs(fregs)->lr;
|
||||
}
|
||||
|
||||
int ftrace_regs_query_register_offset(const char *name);
|
||||
@ -143,7 +145,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs,
|
||||
* The ftrace trampoline will return to this address instead of the
|
||||
* instrumented function.
|
||||
*/
|
||||
fregs->direct_tramp = addr;
|
||||
arch_ftrace_regs(fregs)->direct_tramp = addr;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
||||
|
@ -84,19 +84,19 @@ int main(void)
|
||||
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
|
||||
BLANK();
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
DEFINE(FREGS_X0, offsetof(struct ftrace_regs, regs[0]));
|
||||
DEFINE(FREGS_X2, offsetof(struct ftrace_regs, regs[2]));
|
||||
DEFINE(FREGS_X4, offsetof(struct ftrace_regs, regs[4]));
|
||||
DEFINE(FREGS_X6, offsetof(struct ftrace_regs, regs[6]));
|
||||
DEFINE(FREGS_X8, offsetof(struct ftrace_regs, regs[8]));
|
||||
DEFINE(FREGS_FP, offsetof(struct ftrace_regs, fp));
|
||||
DEFINE(FREGS_LR, offsetof(struct ftrace_regs, lr));
|
||||
DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp));
|
||||
DEFINE(FREGS_PC, offsetof(struct ftrace_regs, pc));
|
||||
DEFINE(FREGS_X0, offsetof(struct __arch_ftrace_regs, regs[0]));
|
||||
DEFINE(FREGS_X2, offsetof(struct __arch_ftrace_regs, regs[2]));
|
||||
DEFINE(FREGS_X4, offsetof(struct __arch_ftrace_regs, regs[4]));
|
||||
DEFINE(FREGS_X6, offsetof(struct __arch_ftrace_regs, regs[6]));
|
||||
DEFINE(FREGS_X8, offsetof(struct __arch_ftrace_regs, regs[8]));
|
||||
DEFINE(FREGS_FP, offsetof(struct __arch_ftrace_regs, fp));
|
||||
DEFINE(FREGS_LR, offsetof(struct __arch_ftrace_regs, lr));
|
||||
DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp));
|
||||
DEFINE(FREGS_PC, offsetof(struct __arch_ftrace_regs, pc));
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct ftrace_regs, direct_tramp));
|
||||
DEFINE(FREGS_DIRECT_TRAMP, offsetof(struct __arch_ftrace_regs, direct_tramp));
|
||||
#endif
|
||||
DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs));
|
||||
DEFINE(FREGS_SIZE, sizeof(struct __arch_ftrace_regs));
|
||||
BLANK();
|
||||
#endif
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -23,10 +23,10 @@ struct fregs_offset {
|
||||
int offset;
|
||||
};
|
||||
|
||||
#define FREGS_OFFSET(n, field) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.offset = offsetof(struct ftrace_regs, field), \
|
||||
#define FREGS_OFFSET(n, field) \
|
||||
{ \
|
||||
.name = n, \
|
||||
.offset = offsetof(struct __arch_ftrace_regs, field), \
|
||||
}
|
||||
|
||||
static const struct fregs_offset fregs_offsets[] = {
|
||||
@ -481,7 +481,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
prepare_ftrace_return(ip, &fregs->lr, fregs->fp);
|
||||
prepare_ftrace_return(ip, &arch_ftrace_regs(fregs)->lr, arch_ftrace_regs(fregs)->fp);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
|
@ -43,38 +43,40 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent);
|
||||
|
||||
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
struct ftrace_ops;
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
struct ftrace_regs {
|
||||
struct __arch_ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
return &fregs->regs;
|
||||
return &arch_ftrace_regs(fregs)->regs;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs)
|
||||
{
|
||||
return instruction_pointer(&fregs->regs);
|
||||
return instruction_pointer(&arch_ftrace_regs(fregs)->regs);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip)
|
||||
{
|
||||
instruction_pointer_set(&fregs->regs, ip);
|
||||
instruction_pointer_set(&arch_ftrace_regs(fregs)->regs, ip);
|
||||
}
|
||||
|
||||
#define ftrace_regs_get_argument(fregs, n) \
|
||||
regs_get_kernel_argument(&(fregs)->regs, n)
|
||||
regs_get_kernel_argument(&arch_ftrace_regs(fregs)->regs, n)
|
||||
#define ftrace_regs_get_stack_pointer(fregs) \
|
||||
kernel_stack_pointer(&(fregs)->regs)
|
||||
kernel_stack_pointer(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_return_value(fregs) \
|
||||
regs_return_value(&(fregs)->regs)
|
||||
regs_return_value(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_set_return_value(fregs, ret) \
|
||||
regs_set_return_value(&(fregs)->regs, ret)
|
||||
regs_set_return_value(&arch_ftrace_regs(fregs)->regs, ret)
|
||||
#define ftrace_override_function_with_return(fregs) \
|
||||
override_function_with_return(&(fregs)->regs)
|
||||
override_function_with_return(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_query_register_offset(name) \
|
||||
regs_query_register_offset(name)
|
||||
|
||||
@ -90,7 +92,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
|
||||
}
|
||||
|
||||
#define arch_ftrace_set_direct_caller(fregs, addr) \
|
||||
__arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
|
||||
__arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr)
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
||||
#endif
|
||||
|
@ -241,7 +241,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent)
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
struct pt_regs *regs = &fregs->regs;
|
||||
struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
|
||||
unsigned long *parent = (unsigned long *)®s->regs[1];
|
||||
|
||||
prepare_ftrace_return(ip, (unsigned long *)parent);
|
||||
|
@ -32,39 +32,42 @@ struct dyn_arch_ftrace {
|
||||
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
|
||||
#define ftrace_init_nop ftrace_init_nop
|
||||
|
||||
struct ftrace_regs {
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
struct __arch_ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
/* We clear regs.msr in ftrace_call */
|
||||
return fregs->regs.msr ? &fregs->regs : NULL;
|
||||
return arch_ftrace_regs(fregs)->regs.msr ? &arch_ftrace_regs(fregs)->regs : NULL;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
unsigned long ip)
|
||||
{
|
||||
regs_set_return_ip(&fregs->regs, ip);
|
||||
regs_set_return_ip(&arch_ftrace_regs(fregs)->regs, ip);
|
||||
}
|
||||
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs)
|
||||
{
|
||||
return instruction_pointer(&fregs->regs);
|
||||
return instruction_pointer(&arch_ftrace_regs(fregs)->regs);
|
||||
}
|
||||
|
||||
#define ftrace_regs_get_argument(fregs, n) \
|
||||
regs_get_kernel_argument(&(fregs)->regs, n)
|
||||
regs_get_kernel_argument(&arch_ftrace_regs(fregs)->regs, n)
|
||||
#define ftrace_regs_get_stack_pointer(fregs) \
|
||||
kernel_stack_pointer(&(fregs)->regs)
|
||||
kernel_stack_pointer(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_return_value(fregs) \
|
||||
regs_return_value(&(fregs)->regs)
|
||||
regs_return_value(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_set_return_value(fregs, ret) \
|
||||
regs_set_return_value(&(fregs)->regs, ret)
|
||||
regs_set_return_value(&arch_ftrace_regs(fregs)->regs, ret)
|
||||
#define ftrace_override_function_with_return(fregs) \
|
||||
override_function_with_return(&(fregs)->regs)
|
||||
override_function_with_return(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_query_register_offset(name) \
|
||||
regs_query_register_offset(name)
|
||||
|
||||
|
@ -421,7 +421,7 @@ int __init ftrace_dyn_arch_init(void)
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
unsigned long sp = fregs->regs.gpr[1];
|
||||
unsigned long sp = arch_ftrace_regs(fregs)->regs.gpr[1];
|
||||
int bit;
|
||||
|
||||
if (unlikely(ftrace_graph_is_dead()))
|
||||
@ -439,6 +439,6 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
out:
|
||||
fregs->regs.link = parent_ip;
|
||||
arch_ftrace_regs(fregs)->regs.link = parent_ip;
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
@ -829,7 +829,7 @@ __prepare_ftrace_return(unsigned long parent, unsigned long ip, unsigned long sp
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
fregs->regs.link = __prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]);
|
||||
arch_ftrace_regs(fregs)->regs.link = __prepare_ftrace_return(parent_ip, ip, arch_ftrace_regs(fregs)->regs.gpr[1]);
|
||||
}
|
||||
#else
|
||||
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip,
|
||||
|
@ -126,7 +126,10 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
#define arch_ftrace_get_regs(regs) NULL
|
||||
struct ftrace_ops;
|
||||
struct ftrace_regs {
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
struct __arch_ftrace_regs {
|
||||
unsigned long epc;
|
||||
unsigned long ra;
|
||||
unsigned long sp;
|
||||
@ -150,42 +153,42 @@ struct ftrace_regs {
|
||||
static __always_inline unsigned long ftrace_regs_get_instruction_pointer(const struct ftrace_regs
|
||||
*fregs)
|
||||
{
|
||||
return fregs->epc;
|
||||
return arch_ftrace_regs(fregs)->epc;
|
||||
}
|
||||
|
||||
static __always_inline void ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
unsigned long pc)
|
||||
{
|
||||
fregs->epc = pc;
|
||||
arch_ftrace_regs(fregs)->epc = pc;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->sp;
|
||||
return arch_ftrace_regs(fregs)->sp;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long ftrace_regs_get_argument(struct ftrace_regs *fregs,
|
||||
unsigned int n)
|
||||
{
|
||||
if (n < 8)
|
||||
return fregs->args[n];
|
||||
return arch_ftrace_regs(fregs)->args[n];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->a0;
|
||||
return arch_ftrace_regs(fregs)->a0;
|
||||
}
|
||||
|
||||
static __always_inline void ftrace_regs_set_return_value(struct ftrace_regs *fregs,
|
||||
unsigned long ret)
|
||||
{
|
||||
fregs->a0 = ret;
|
||||
arch_ftrace_regs(fregs)->a0 = ret;
|
||||
}
|
||||
|
||||
static __always_inline void ftrace_override_function_with_return(struct ftrace_regs *fregs)
|
||||
{
|
||||
fregs->epc = fregs->ra;
|
||||
arch_ftrace_regs(fregs)->epc = arch_ftrace_regs(fregs)->ra;
|
||||
}
|
||||
|
||||
int ftrace_regs_query_register_offset(const char *name);
|
||||
@ -196,7 +199,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
|
||||
static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
|
||||
{
|
||||
fregs->t1 = addr;
|
||||
arch_ftrace_regs(fregs)->t1 = addr;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
|
||||
|
||||
|
@ -498,19 +498,19 @@ void asm_offsets(void)
|
||||
OFFSET(STACKFRAME_RA, stackframe, ra);
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
|
||||
DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct ftrace_regs), STACK_ALIGN));
|
||||
DEFINE(FREGS_EPC, offsetof(struct ftrace_regs, epc));
|
||||
DEFINE(FREGS_RA, offsetof(struct ftrace_regs, ra));
|
||||
DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp));
|
||||
DEFINE(FREGS_S0, offsetof(struct ftrace_regs, s0));
|
||||
DEFINE(FREGS_T1, offsetof(struct ftrace_regs, t1));
|
||||
DEFINE(FREGS_A0, offsetof(struct ftrace_regs, a0));
|
||||
DEFINE(FREGS_A1, offsetof(struct ftrace_regs, a1));
|
||||
DEFINE(FREGS_A2, offsetof(struct ftrace_regs, a2));
|
||||
DEFINE(FREGS_A3, offsetof(struct ftrace_regs, a3));
|
||||
DEFINE(FREGS_A4, offsetof(struct ftrace_regs, a4));
|
||||
DEFINE(FREGS_A5, offsetof(struct ftrace_regs, a5));
|
||||
DEFINE(FREGS_A6, offsetof(struct ftrace_regs, a6));
|
||||
DEFINE(FREGS_A7, offsetof(struct ftrace_regs, a7));
|
||||
DEFINE(FREGS_SIZE_ON_STACK, ALIGN(sizeof(struct __arch_ftrace_regs), STACK_ALIGN));
|
||||
DEFINE(FREGS_EPC, offsetof(struct __arch_ftrace_regs, epc));
|
||||
DEFINE(FREGS_RA, offsetof(struct __arch_ftrace_regs, ra));
|
||||
DEFINE(FREGS_SP, offsetof(struct __arch_ftrace_regs, sp));
|
||||
DEFINE(FREGS_S0, offsetof(struct __arch_ftrace_regs, s0));
|
||||
DEFINE(FREGS_T1, offsetof(struct __arch_ftrace_regs, t1));
|
||||
DEFINE(FREGS_A0, offsetof(struct __arch_ftrace_regs, a0));
|
||||
DEFINE(FREGS_A1, offsetof(struct __arch_ftrace_regs, a1));
|
||||
DEFINE(FREGS_A2, offsetof(struct __arch_ftrace_regs, a2));
|
||||
DEFINE(FREGS_A3, offsetof(struct __arch_ftrace_regs, a3));
|
||||
DEFINE(FREGS_A4, offsetof(struct __arch_ftrace_regs, a4));
|
||||
DEFINE(FREGS_A5, offsetof(struct __arch_ftrace_regs, a5));
|
||||
DEFINE(FREGS_A6, offsetof(struct __arch_ftrace_regs, a6));
|
||||
DEFINE(FREGS_A7, offsetof(struct __arch_ftrace_regs, a7));
|
||||
#endif
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
prepare_ftrace_return(&fregs->ra, ip, fregs->s0);
|
||||
prepare_ftrace_return(&arch_ftrace_regs(fregs)->ra, ip, arch_ftrace_regs(fregs)->s0);
|
||||
}
|
||||
#else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
|
||||
extern void ftrace_graph_call(void);
|
||||
|
@ -51,13 +51,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct ftrace_regs {
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
struct __arch_ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
struct pt_regs *regs = &fregs->regs;
|
||||
struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
|
||||
|
||||
if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
|
||||
return regs;
|
||||
@ -84,26 +87,26 @@ static __always_inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph
|
||||
static __always_inline unsigned long
|
||||
ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
|
||||
{
|
||||
return fregs->regs.psw.addr;
|
||||
return arch_ftrace_regs(fregs)->regs.psw.addr;
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
unsigned long ip)
|
||||
{
|
||||
fregs->regs.psw.addr = ip;
|
||||
arch_ftrace_regs(fregs)->regs.psw.addr = ip;
|
||||
}
|
||||
|
||||
#define ftrace_regs_get_argument(fregs, n) \
|
||||
regs_get_kernel_argument(&(fregs)->regs, n)
|
||||
regs_get_kernel_argument(&arch_ftrace_regs(fregs)->regs, n)
|
||||
#define ftrace_regs_get_stack_pointer(fregs) \
|
||||
kernel_stack_pointer(&(fregs)->regs)
|
||||
kernel_stack_pointer(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_return_value(fregs) \
|
||||
regs_return_value(&(fregs)->regs)
|
||||
regs_return_value(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_set_return_value(fregs, ret) \
|
||||
regs_set_return_value(&(fregs)->regs, ret)
|
||||
regs_set_return_value(&arch_ftrace_regs(fregs)->regs, ret)
|
||||
#define ftrace_override_function_with_return(fregs) \
|
||||
override_function_with_return(&(fregs)->regs)
|
||||
override_function_with_return(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_query_register_offset(name) \
|
||||
regs_query_register_offset(name)
|
||||
|
||||
@ -117,7 +120,7 @@ ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
|
||||
*/
|
||||
static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
|
||||
{
|
||||
struct pt_regs *regs = &fregs->regs;
|
||||
struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
|
||||
regs->orig_gpr2 = addr;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
@ -184,8 +184,8 @@ int main(void)
|
||||
OFFSET(__FGRAPH_RET_FP, fgraph_ret_regs, fp);
|
||||
DEFINE(__FGRAPH_RET_SIZE, sizeof(struct fgraph_ret_regs));
|
||||
#endif
|
||||
OFFSET(__FTRACE_REGS_PT_REGS, ftrace_regs, regs);
|
||||
DEFINE(__FTRACE_REGS_SIZE, sizeof(struct ftrace_regs));
|
||||
OFFSET(__FTRACE_REGS_PT_REGS, __arch_ftrace_regs, regs);
|
||||
DEFINE(__FTRACE_REGS_SIZE, sizeof(struct __arch_ftrace_regs));
|
||||
|
||||
OFFSET(__PCPU_FLAGS, pcpu, flags);
|
||||
return 0;
|
||||
|
@ -318,7 +318,7 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
kmsan_unpoison_memory(fregs, sizeof(*fregs));
|
||||
kmsan_unpoison_memory(fregs, ftrace_regs_size());
|
||||
regs = ftrace_get_regs(fregs);
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (!regs || unlikely(!p) || kprobe_disabled(p))
|
||||
|
@ -270,9 +270,9 @@ static void notrace __used test_unwind_ftrace_handler(unsigned long ip,
|
||||
struct ftrace_ops *fops,
|
||||
struct ftrace_regs *fregs)
|
||||
{
|
||||
struct unwindme *u = (struct unwindme *)fregs->regs.gprs[2];
|
||||
struct unwindme *u = (struct unwindme *)arch_ftrace_regs(fregs)->regs.gprs[2];
|
||||
|
||||
u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &fregs->regs : NULL,
|
||||
u->ret = test_unwind(NULL, (u->flags & UWM_REGS) ? &arch_ftrace_regs(fregs)->regs : NULL,
|
||||
(u->flags & UWM_SP) ? u->sp : 0);
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,10 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
struct ftrace_regs {
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
struct __arch_ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
|
||||
@ -41,27 +44,27 @@ static __always_inline struct pt_regs *
|
||||
arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
/* Only when FL_SAVE_REGS is set, cs will be non zero */
|
||||
if (!fregs->regs.cs)
|
||||
if (!arch_ftrace_regs(fregs)->regs.cs)
|
||||
return NULL;
|
||||
return &fregs->regs;
|
||||
return &arch_ftrace_regs(fregs)->regs;
|
||||
}
|
||||
|
||||
#define ftrace_regs_set_instruction_pointer(fregs, _ip) \
|
||||
do { (fregs)->regs.ip = (_ip); } while (0)
|
||||
do { arch_ftrace_regs(fregs)->regs.ip = (_ip); } while (0)
|
||||
|
||||
#define ftrace_regs_get_instruction_pointer(fregs) \
|
||||
((fregs)->regs.ip)
|
||||
arch_ftrace_regs(fregs)->regs.ip)
|
||||
|
||||
#define ftrace_regs_get_argument(fregs, n) \
|
||||
regs_get_kernel_argument(&(fregs)->regs, n)
|
||||
regs_get_kernel_argument(&arch_ftrace_regs(fregs)->regs, n)
|
||||
#define ftrace_regs_get_stack_pointer(fregs) \
|
||||
kernel_stack_pointer(&(fregs)->regs)
|
||||
kernel_stack_pointer(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_return_value(fregs) \
|
||||
regs_return_value(&(fregs)->regs)
|
||||
regs_return_value(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_set_return_value(fregs, ret) \
|
||||
regs_set_return_value(&(fregs)->regs, ret)
|
||||
regs_set_return_value(&arch_ftrace_regs(fregs)->regs, ret)
|
||||
#define ftrace_override_function_with_return(fregs) \
|
||||
override_function_with_return(&(fregs)->regs)
|
||||
override_function_with_return(&arch_ftrace_regs(fregs)->regs)
|
||||
#define ftrace_regs_query_register_offset(name) \
|
||||
regs_query_register_offset(name)
|
||||
|
||||
@ -88,7 +91,7 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
|
||||
regs->orig_ax = addr;
|
||||
}
|
||||
#define arch_ftrace_set_direct_caller(fregs, addr) \
|
||||
__arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
|
||||
__arch_ftrace_set_direct_caller(&arch_ftrace_regs(fregs)->regs, addr)
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
@ -647,7 +647,7 @@ void prepare_ftrace_return(unsigned long ip, unsigned long *parent,
|
||||
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
struct pt_regs *regs = &fregs->regs;
|
||||
struct pt_regs *regs = &arch_ftrace_regs(fregs)->regs;
|
||||
unsigned long *stack = (unsigned long *)kernel_stack_pointer(regs);
|
||||
|
||||
prepare_ftrace_return(ip, (unsigned long *)stack, 0);
|
||||
|
@ -115,8 +115,6 @@ static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *val
|
||||
|
||||
extern int ftrace_enabled;
|
||||
|
||||
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
|
||||
/**
|
||||
* ftrace_regs - ftrace partial/optimal register set
|
||||
*
|
||||
@ -142,11 +140,28 @@ extern int ftrace_enabled;
|
||||
*
|
||||
* NOTE: user *must not* access regs directly, only do it via APIs, because
|
||||
* the member can be changed according to the architecture.
|
||||
* This is why the structure is empty here, so that nothing accesses
|
||||
* the ftrace_regs directly.
|
||||
*/
|
||||
struct ftrace_regs {
|
||||
/* Nothing to see here, use the accessor functions! */
|
||||
};
|
||||
|
||||
#define ftrace_regs_size() sizeof(struct __arch_ftrace_regs)
|
||||
|
||||
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
|
||||
|
||||
struct __arch_ftrace_regs {
|
||||
struct pt_regs regs;
|
||||
};
|
||||
#define arch_ftrace_get_regs(fregs) (&(fregs)->regs)
|
||||
|
||||
struct ftrace_regs;
|
||||
#define arch_ftrace_regs(fregs) ((struct __arch_ftrace_regs *)(fregs))
|
||||
|
||||
static inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
|
||||
{
|
||||
return &arch_ftrace_regs(fregs)->regs;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftrace_regs_set_instruction_pointer() is to be defined by the architecture
|
||||
|
@ -7943,7 +7943,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
|
||||
void arch_ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op, struct ftrace_regs *fregs)
|
||||
{
|
||||
kmsan_unpoison_memory(fregs, sizeof(*fregs));
|
||||
kmsan_unpoison_memory(fregs, ftrace_regs_size());
|
||||
__ftrace_ops_list_func(ip, parent_ip, NULL, fregs);
|
||||
}
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user