s390/ftrace: assume -mhotpatch or -mrecord-mcount always available
authorVasily Gorbik <gor@linux.ibm.com>
Thu, 12 Nov 2020 14:54:47 +0000 (15:54 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Fri, 20 Nov 2020 18:19:11 +0000 (19:19 +0100)
Currently the kernel minimal compiler requirement is gcc 4.9 or
clang 10.0.1.
* gcc -mhotpatch option is supported since 4.8.
* A combination of -pg -mrecord-mcount -mnop-mcount -mfentry flags is
supported since gcc 9 and since clang 10.

Drop support for old -pg function prologues. Which leaves binary
compatible -mhotpatch / -mnop-mcount -mfentry prologues in a form:
brcl 0,0
Which are also do not require initial nop optimization / conversion and
presence of _mcount symbol.

Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/ftrace.h
arch/s390/kernel/ftrace.c
arch/s390/kernel/mcount.S
scripts/recordmcount.pl

index 68d362f8d6c17bafa112b08837dffd0dc8c47ad3..695c61989f97c7c06becbb383bb553d89f195ca5 100644 (file)
@@ -2,16 +2,9 @@
 #ifndef _ASM_S390_FTRACE_H
 #define _ASM_S390_FTRACE_H
 
+#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
 #define ARCH_SUPPORTS_FTRACE_OPS 1
-
-#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
 #define MCOUNT_INSN_SIZE       6
-#else
-#define MCOUNT_INSN_SIZE       24
-#define MCOUNT_RETURN_FIXUP    18
-#endif
-
-#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
 
 #ifndef __ASSEMBLY__
 
@@ -22,7 +15,6 @@
 #define ftrace_return_address(n) __builtin_return_address(n)
 #endif
 
-void _mcount(void);
 void ftrace_caller(void);
 
 extern char ftrace_graph_caller_end;
@@ -30,12 +22,20 @@ extern unsigned long ftrace_plt;
 
 struct dyn_arch_ftrace { };
 
-#define MCOUNT_ADDR ((unsigned long)_mcount)
+#define MCOUNT_ADDR 0
 #define FTRACE_ADDR ((unsigned long)ftrace_caller)
 
 #define KPROBE_ON_FTRACE_NOP   0
 #define KPROBE_ON_FTRACE_CALL  1
 
+struct module;
+struct dyn_ftrace;
+/*
+ * Either -mhotpatch or -mnop-mcount is used - no explicit init is required
+ */
+static inline int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) { return 0; }
+#define ftrace_init_nop ftrace_init_nop
+
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
        return addr;
@@ -49,28 +49,17 @@ struct ftrace_insn {
 static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
 {
 #ifdef CONFIG_FUNCTION_TRACER
-#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
        /* brcl 0,0 */
        insn->opc = 0xc004;
        insn->disp = 0;
-#else
-       /* jg .+24 */
-       insn->opc = 0xc0f4;
-       insn->disp = MCOUNT_INSN_SIZE / 2;
-#endif
 #endif
 }
 
 static inline int is_ftrace_nop(struct ftrace_insn *insn)
 {
 #ifdef CONFIG_FUNCTION_TRACER
-#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
        if (insn->disp == 0)
                return 1;
-#else
-       if (insn->disp == MCOUNT_INSN_SIZE / 2)
-               return 1;
-#endif
 #endif
        return 0;
 }
index b388e87a08bf908ccdf85b92dad0902ff09a062d..ebc1284a618b9e7b7ca947f5cf590f7785073795 100644 (file)
 #include "entry.h"
 
 /*
- * The mcount code looks like this:
- *     stg     %r14,8(%r15)            # offset 0
- *     larl    %r1,<&counter>          # offset 6
- *     brasl   %r14,_mcount            # offset 12
- *     lg      %r14,8(%r15)            # offset 18
- * Total length is 24 bytes. Only the first instruction will be patched
- * by ftrace_make_call / ftrace_make_nop.
- * The enabled ftrace code block looks like this:
+ * To generate function prologue either gcc's hotpatch feature (since gcc 4.8)
+ * or a combination of -pg -mrecord-mcount -mnop-mcount -mfentry flags
+ * (since gcc 9 / clang 10) is used.
+ * In both cases the original and also the disabled function prologue contains
+ * only a single six byte instruction and looks like this:
+ * >   brcl    0,0                     # offset 0
+ * To enable ftrace the code gets patched like above and afterwards looks
+ * like this:
  * >   brasl   %r0,ftrace_caller       # offset 0
- *     larl    %r1,<&counter>          # offset 6
- *     brasl   %r14,_mcount            # offset 12
- *     lg      %r14,8(%r15)            # offset 18
+ *
+ * The instruction will be patched by ftrace_make_call / ftrace_make_nop.
  * The ftrace function gets called with a non-standard C function call ABI
  * where r0 contains the return address. It is also expected that the called
  * function only clobbers r0 and r1, but restores r2-r15.
  * For module code we can't directly jump to ftrace caller, but need a
  * trampoline (ftrace_plt), which clobbers also r1.
- * The return point of the ftrace function has offset 24, so execution
- * continues behind the mcount block.
- * The disabled ftrace code block looks like this:
- * >   jg      .+24                    # offset 0
- *     larl    %r1,<&counter>          # offset 6
- *     brasl   %r14,_mcount            # offset 12
- *     lg      %r14,8(%r15)            # offset 18
- * The jg instruction branches to offset 24 to skip as many instructions
- * as possible.
- * In case we use gcc's hotpatch feature the original and also the disabled
- * function prologue contains only a single six byte instruction and looks
- * like this:
- * >   brcl    0,0                     # offset 0
- * To enable ftrace the code gets patched like above and afterwards looks
- * like this:
- * >   brasl   %r0,ftrace_caller       # offset 0
  */
 
 unsigned long ftrace_plt;
 
-static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn)
-{
-#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
-       /* brcl 0,0 */
-       insn->opc = 0xc004;
-       insn->disp = 0;
-#else
-       /* stg r14,8(r15) */
-       insn->opc = 0xe3e0;
-       insn->disp = 0xf0080024;
-#endif
-}
-
 int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
                       unsigned long addr)
 {
@@ -85,15 +55,10 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
 
        if (copy_from_kernel_nofault(&old, (void *) rec->ip, sizeof(old)))
                return -EFAULT;
-       if (addr == MCOUNT_ADDR) {
-               /* Initial code replacement */
-               ftrace_generate_orig_insn(&orig);
-               ftrace_generate_nop_insn(&new);
-       } else {
-               /* Replace ftrace call with a nop. */
-               ftrace_generate_call_insn(&orig, rec->ip);
-               ftrace_generate_nop_insn(&new);
-       }
+       /* Replace ftrace call with a nop. */
+       ftrace_generate_call_insn(&orig, rec->ip);
+       ftrace_generate_nop_insn(&new);
+
        /* Verify that the to be replaced code matches what we expect. */
        if (memcmp(&orig, &old, sizeof(old)))
                return -EINVAL;
index 7458dcfd64642cf4e2016bd8e1b4bf2ecfc4a716..faf64c2f90f52e35b6b204534a750844461b3200 100644 (file)
@@ -33,11 +33,6 @@ ENDPROC(ftrace_stub)
 #define TRACED_FUNC_FRAME_SIZE STACK_FRAME_OVERHEAD
 #endif
 
-ENTRY(_mcount)
-       BR_EX   %r14
-ENDPROC(_mcount)
-EXPORT_SYMBOL(_mcount)
-
 ENTRY(ftrace_caller)
        .globl  ftrace_regs_caller
        .set    ftrace_regs_caller,ftrace_caller
@@ -46,9 +41,6 @@ ENTRY(ftrace_caller)
        ipm     %r14                            # don't put any instructions
        sllg    %r14,%r14,16                    # clobbering CC before this point
        lgr     %r1,%r15
-#if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
-       aghi    %r0,MCOUNT_RETURN_FIXUP
-#endif
        # allocate stack frame for ftrace_caller to contain traced function
        aghi    %r15,-TRACED_FUNC_FRAME_SIZE
        stg     %r1,__SF_BACKCHAIN(%r15)
index 3f77a5d695c13ac68e0ffb28372de9447b2f73b6..56c801502b9a7b224af3d4d47b9caa71c9033ea8 100755 (executable)
@@ -254,9 +254,6 @@ if ($arch eq "x86_64") {
     if ($cc =~ /-DCC_USING_HOTPATCH/) {
        $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*c0 04 00 00 00 00\\s*brcl\\s*0,[0-9a-f]+ <([^\+]*)>\$";
        $mcount_adjust = 0;
-    } else {
-       $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_390_(PC|PLT)32DBL\\s+_mcount\\+0x2\$";
-       $mcount_adjust = -14;
     }
     $alignment = 8;
     $type = ".quad";