]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ftrace: Make ftrace_regs abstract from direct use
authorSteven Rostedt <rostedt@goodmis.org>
Tue, 8 Oct 2024 23:05:28 +0000 (19:05 -0400)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Fri, 11 Oct 2024 00:18:01 +0000 (20:18 -0400)
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>
19 files changed:
arch/arm64/include/asm/ftrace.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/ftrace.c
arch/loongarch/include/asm/ftrace.h
arch/loongarch/kernel/ftrace_dyn.c
arch/powerpc/include/asm/ftrace.h
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/kernel/trace/ftrace_64_pg.c
arch/riscv/include/asm/ftrace.h
arch/riscv/kernel/asm-offsets.c
arch/riscv/kernel/ftrace.c
arch/s390/include/asm/ftrace.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/ftrace.c
arch/s390/lib/test_unwind.c
arch/x86/include/asm/ftrace.h
arch/x86/kernel/ftrace.c
include/linux/ftrace.h
kernel/trace/ftrace.c

index dc9cf0bd2a4cba064c6132a8041c034649ccb949..bbb69c7751b996e79b3c7b446412d98b31177206 100644 (file)
@@ -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 */
 
index 27de1dddb0abee1f6e9d760676a0ffdd0c9a2603..a5de57f682197f7aefcd919cbc961e035d075149 100644 (file)
@@ -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
index a650f5e11fc5d8614a4656b92cce3c4c446eb16f..b2d947175cbecc20df1ab86b8cf0c3485643ab28 100644 (file)
@@ -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
 /*
index c0a682808e0707b2700d43e31b18be5419f6f9d5..0e15d36ce2512e031b14f93d9769f6a15804b75f 100644 (file)
@@ -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
index bff058317062e367941604f97f758b11986002cf..18056229e22e4d41d3a63d0e7d1674f81d539594 100644 (file)
@@ -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 *)&regs->regs[1];
 
        prepare_ftrace_return(ip, (unsigned long *)parent);
index 559560286e6d017d3ce2d34e76b30848accd6775..e299fd47d201429757a28e6428f8b64f88cd05e0 100644 (file)
@@ -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)
 
index d8d6b4fd9a14cbf8f8f93e499500eed11190be71..df41f4a7c738b50ce1e2bade3ef309f533ca4422 100644 (file)
@@ -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 */
index 12fab1803bcf45cafb3fd230c1f7871e2c539f1d..d3c5552e4984d3f530170c262f3fabbcd78fca47 100644 (file)
@@ -829,7 +829,7 @@ out:
 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,
index 2cddd79ff21b1e58ab98a09946adf0fa3f500e3a..c6bcdff105b59c7b60e88d2d4c3ea5d1a21fd53b 100644 (file)
@@ -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 */
 
index e94180ba432f5957b4e73143e17e902be24a6b29..f6f5a277ba9d675db37da5b5997bd090ae271ba5 100644 (file)
@@ -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
 }
index 4b95c574fd0457432d7bad17cac888ecbedfe0e0..5081ad886841fddf3a248eb12b28ab4158d5fcf6 100644 (file)
@@ -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);
index 406746666eb7823fbb4f90d828795b9acb639c92..1498d0a9c7625eeec258ddafa00a2fd2b6b0b77f 100644 (file)
@@ -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 */
index 5529248d84fb8729887d8cae5788f06d6f9bb23f..db96599801755fa4182259d917b1191bc97038a9 100644 (file)
@@ -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;
index 0b6e62d1d8b87e8c9418aef7a91b71c1d04b6ad4..51439a71e392c64e0c9ed0a9ca25ba4407788689 100644 (file)
@@ -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))
index 8b7f981e6f347723efb68704fdd6b20557c796ba..6e42100875e75ba50e5e063b97b5c738ede3b330 100644 (file)
@@ -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);
 }
 
index 0152a81d9b4a2e295fe758475aa2f1b7954a6a6c..87943f7a299b9dc7d3f6b9a22ef59dfc3f976eb5 100644 (file)
@@ -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
index 8da0e66ca22dec8d8076ce0a4377f3cfc50b3619..adb09f78edb289a65f704c61e8d353040980037c 100644 (file)
@@ -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);
index 4c7dd5e58c9f162382d75666637b634cd53626f8..66f10291a0b2c48869bc306ba8b289e03b506739 100644 (file)
@@ -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
index cae388122ca8f8a64da0c04a94d7438a8357bcbd..e9fd4fb2769edd1c1848055b689f7c5ed78cee64 100644 (file)
@@ -7943,7 +7943,7 @@ out:
 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