Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 00/10] ARM: ftrace: cleanups, Thumb-2, and dynamic ftrace (v2)

19 views
Skip to first unread message

Rabin Vincent

unread,
Mar 13, 2010, 2:00:01 AM3/13/10
to
v2: Fixes as per review comments. The only code changes are the #error in 0004
and the removal of the #ifdef in 0009. The rest are comments and commit
message rewording/expansion.

This series contains fixes and improvements to the ARM ftrace support. It adds
Thumb-2 support and re-implements the dynamic ftrace support.

"ftrace: allow building without frame pointers" and "ftrace: pass KBUILD_CFLAGS
to record_mcount.pl" are non-ARM-specific ftrace patches which are required to
support the ARM functionality.

Cleanups / docs:

ARM: ftrace: clean up mcount assembly indentation
ARM: ftrace: document mcount formats

Thumb-2:

ftrace: allow building without frame pointers
ARM: ftrace: allow building without frame pointers
ARM: ftrace: add ENDPROC annotations
ARM: ftrace: add Thumb-2 support

Dynamic ftrace:

ftrace: pass KBUILD_CFLAGS to record_mcount.pl
ARM: ftrace: fix and update dynamic ftrace
ARM: ftrace: add Thumb-2 support to dynamic ftrace
ARM: ftrace: enable dynamic ftrace

Makefile | 7 ++
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 5 +
arch/arm/include/asm/ftrace.h | 20 ++++-
arch/arm/kernel/armksyms.c | 2 +
arch/arm/kernel/entry-common.S | 178 +++++++++++++++++++++++++++-----------
arch/arm/kernel/ftrace.c | 188 +++++++++++++++++++++++++++++----------
kernel/trace/Kconfig | 2 +-
scripts/Makefile.build | 3 +-
scripts/recordmcount.pl | 2 +
10 files changed, 307 insertions(+), 102 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
Fix the mcount routines to build and run on a kernel built with the
Thumb-2 instruction set:

- Without the BSYM, the following assembler errors appear:

entry-common.S: Assembler messages:
entry-common.S:179: Error: invalid immediate for address calculation (value = 0x00000004)

- Without the orr, the lsb is not set on the pointer loaded from
ftrace_trace_function, but is set on BSYM(ftrace_stub), leading to the
comparison failing even when the pointer is pointing to ftrace_stub.

- The problem with the "mov lr, pc", is that it does not set the lsb when
storing the pc in lr. The called function returns with "bx lr", and the
mode changes to ARM. The blx is to avoid this.

Cc: Catalin Marinas <catalin...@arm.com>
Signed-off-by: Rabin Vincent <ra...@rab.in>
---
arch/arm/kernel/entry-common.S | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index c3bdb05..573ed3b 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -167,7 +167,8 @@ ENTRY(__gnu_mcount_nc)
stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
ldr r2, [r0]
- adr r0, ftrace_stub
+ THUMB( orr r2, r2, #1 )
+ adr r0, BSYM(ftrace_stub)
cmp r0, r2
bne gnu_trace
ldmia sp!, {r0-r3, ip, lr}
@@ -177,8 +178,9 @@ gnu_trace:
ldr r1, [sp, #20] @ lr of instrumented routine
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
- mov lr, pc
- mov pc, r2
+ ARM( mov lr, pc )
+ ARM( mov pc, r2 )
+ THUMB( blx r2 )
ldmia sp!, {r0-r3, ip, lr}
mov pc, ip
ENDPROC(__gnu_mcount_nc)
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
With current gcc, compiling with both -pg and -fomit-frame-pointer is
not allowed. However, -pg can be used to build without actually
specying -fno-omit-frame-pointer, upon which the defaut behaviour for
the target will be used.

On ARM, it is not possible to build a Thumb-2 kernel with
-fno-omit-frame-pointer (FRAME_POINTERS depends on !THUMB2_KERNEL). In
order to support ftrace for Thumb-2, we need to be able to allow a
combination of FUNCTION_TRACER and !FRAME_POINTER. We do this by
omitting -fomit-frame-pointer if ftrace is enabled.

Acked-by: Frederic Weisbecker <fwei...@gmail.com>


Signed-off-by: Rabin Vincent <ra...@rab.in>
---

v2: Better comment.

Makefile | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile
index 08ff02d..61404e0 100644
--- a/Makefile
+++ b/Makefile
@@ -546,8 +546,15 @@ endif
ifdef CONFIG_FRAME_POINTER
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
+# Some targets (ARM with Thumb2, for example), can't be built with frame
+# pointers. For those, we don't have FUNCTION_TRACER automatically
+# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
+# incompatible with -fomit-frame-pointer with current GCC, so we don't use
+# -fomit-frame-pointer with FUNCTION_TRACER.
+ifndef CONFIG_FUNCTION_TRACER
KBUILD_CFLAGS += -fomit-frame-pointer
endif
+endif

ifdef CONFIG_DEBUG_INFO
KBUILD_CFLAGS += -g
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
This adds mcount recording and updates dynamic ftrace for ARM to work
with the new ftrace dyamic tracing implementation. It also adds support
for the mcount format used by newer ARM compilers.

With dynamic tracing, mcount() is implemented as a nop. Callsites are
patched on startup with nops, and dynamically patched to call to the
ftrace_caller() routine as needed.

Signed-off-by: Rabin Vincent <ra...@rab.in>
---

arch/arm/include/asm/ftrace.h | 19 +++++-
arch/arm/kernel/entry-common.S | 37 +++++++---
arch/arm/kernel/ftrace.c | 155 +++++++++++++++++++++++++++------------
scripts/recordmcount.pl | 2 +
4 files changed, 155 insertions(+), 58 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 103f7ee..4a56a2e 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -2,12 +2,29 @@
#define _ASM_ARM_FTRACE

#ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_ADDR ((long)(mcount))
+#define MCOUNT_ADDR ((unsigned long)(__gnu_mcount_nc))
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */

#ifndef __ASSEMBLY__
extern void mcount(void);
extern void __gnu_mcount_nc(void);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+#ifdef CONFIG_OLD_MCOUNT
+ bool old_mcount;
+#endif
+};
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ return addr;
+}
+
+extern void ftrace_caller_old(void);
+extern void ftrace_call_old(void);
+#endif
+
#endif

#endif
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 573ed3b..9931a02 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -127,6 +127,10 @@ ENDPROC(ret_from_fork)
* clobber the ip register. This is OK because the ARM calling convention
* allows it to be clobbered in subroutines and doesn't use it to hold
* parameters.)
+ *
+ * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0"
+ * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see
+ * arch/arm/kernel/ftrace.c).
*/

#ifndef CONFIG_OLD_MCOUNT
@@ -136,30 +140,45 @@ ENDPROC(ret_from_fork)
#endif

#ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(mcount)
+ENTRY(__gnu_mcount_nc)
+ mov ip, lr
+ ldmia sp!, {lr}
+ mov pc, ip
+ENDPROC(__gnu_mcount_nc)
+
+ENTRY(ftrace_caller)
stmdb sp!, {r0-r3, lr}


mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE

+ ldr r1, [sp, #20]

- .globl mcount_call
-mcount_call:
+ .global ftrace_call
+ftrace_call:
bl ftrace_stub
- ldr lr, [fp, #-4] @ restore lr
- ldmia sp!, {r0-r3, pc}
+ ldmia sp!, {r0-r3, ip, lr}
+ mov pc, ip
+ENDPROC(ftrace_caller)
+
+#ifdef CONFIG_OLD_MCOUNT
+ENTRY(mcount)
+ stmdb sp!, {lr}
+ ldr lr, [fp, #-4]
+ ldmia sp!, {pc}
ENDPROC(mcount)

-ENTRY(ftrace_caller)
+ENTRY(ftrace_caller_old)
stmdb sp!, {r0-r3, lr}
ldr r1, [fp, #-4]


mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE

- .globl ftrace_call
-ftrace_call:
+ .globl ftrace_call_old
+ftrace_call_old:
bl ftrace_stub
ldr lr, [fp, #-4] @ restore lr
ldmia sp!, {r0-r3, pc}
-ENDPROC(ftrace_caller)
+ENDPROC(ftrace_caller_old)
+#endif

#else

diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index c638427..f09014c 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -2,102 +2,161 @@
* Dynamic function tracing support.
*
* Copyright (C) 2008 Abhishek Sagar <sagar.a...@gmail.com>
+ * Copyright (C) 2010 Rabin Vincent <ra...@rab.in>
*
* For licencing details, see COPYING.
*
* Defines low-level handling of mcount calls when the kernel
* is compiled with the -pg flag. When using dynamic ftrace, the
- * mcount call-sites get patched lazily with NOP till they are
- * enabled. All code mutation routines here take effect atomically.
+ * mcount call-sites get patched with NOP till they are enabled.
+ * All code mutation routines here are called under stop_machine().
*/

#include <linux/ftrace.h>
+#include <linux/uaccess.h>

#include <asm/cacheflush.h>
#include <asm/ftrace.h>

-#define PC_OFFSET 8
-#define BL_OPCODE 0xeb000000
-#define BL_OFFSET_MASK 0x00ffffff
+#define NOP 0xe8bd4000 /* pop {lr} */

-static unsigned long bl_insn;
-static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
+#ifdef CONFIG_OLD_MCOUNT
+#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
+#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)

-unsigned char *ftrace_nop_replace(void)
+#define OLD_NOP 0xe1a00000 /* mov r0, r0 */
+
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
+{
+ return rec->arch.old_mcount ? OLD_NOP : NOP;
+}
+
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
+{
+ if (!rec->arch.old_mcount)
+ return addr;
+
+ if (addr == MCOUNT_ADDR)
+ addr = OLD_MCOUNT_ADDR;
+ else if (addr == FTRACE_ADDR)
+ addr = OLD_FTRACE_ADDR;
+
+ return addr;
+}
+#else
+static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
+{
+ return NOP;
+}
+
+static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
{
- return (char *)&NOP;
+ return addr;
}
+#endif

/* construct a branch (BL) instruction to addr */
-unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
{
long offset;

- offset = (long)addr - (long)(pc + PC_OFFSET);
+ offset = (long)addr - (long)(pc + 8);
if (unlikely(offset < -33554432 || offset > 33554428)) {
/* Can't generate branches that far (from ARM ARM). Ftrace
* doesn't generate branches outside of kernel text.
*/
WARN_ON_ONCE(1);
- return NULL;
+ return 0;
}
- offset = (offset >> 2) & BL_OFFSET_MASK;
- bl_insn = BL_OPCODE | offset;
- return (unsigned char *)&bl_insn;
-}

-int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
- unsigned char *new_code)
-{
- unsigned long err = 0, replaced = 0, old, new;
+ offset = (offset >> 2) & 0x00ffffff;

- old = *(unsigned long *)old_code;
- new = *(unsigned long *)new_code;
+ return 0xeb000000 | offset;
+}

- __asm__ __volatile__ (
- "1: ldr %1, [%2] \n"
- " cmp %1, %4 \n"
- "2: streq %3, [%2] \n"
- " cmpne %1, %3 \n"
- " movne %0, #2 \n"
- "3:\n"
+static int ftrace_modify_code(unsigned long pc, unsigned long old,
+ unsigned long new)
+{
+ unsigned long replaced;

- ".section .fixup, \"ax\"\n"
- "4: mov %0, #1 \n"
- " b 3b \n"
- ".previous\n"
+ if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+ return -EFAULT;

- ".section __ex_table, \"a\"\n"
- " .long 1b, 4b \n"
- " .long 2b, 4b \n"
- ".previous\n"
+ if (replaced != old)
+ return -EINVAL;

- : "=r"(err), "=r"(replaced)
- : "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
- : "memory");
+ if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
+ return -EPERM;

- if (!err && (replaced == old))
- flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+ flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);

- return err;
+ return 0;
}

int ftrace_update_ftrace_func(ftrace_func_t func)
{
- int ret;
unsigned long pc, old;
- unsigned char *new;
+ unsigned long new;
+ int ret;

pc = (unsigned long)&ftrace_call;
memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
new = ftrace_call_replace(pc, (unsigned long)func);
- ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
+
+ ret = ftrace_modify_code(pc, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+ if (!ret) {
+ pc = (unsigned long)&ftrace_call_old;
+ memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
+ new = ftrace_call_replace(pc, (unsigned long)func);
+
+ ret = ftrace_modify_code(pc, old, new);
+ }
+#endif
+
+ return ret;
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long new, old;
+ unsigned long ip = rec->ip;
+
+ old = ftrace_nop_replace(rec);
+ new = ftrace_call_replace(ip, adjust_address(rec, addr));
+
+ return ftrace_modify_code(rec->ip, old, new);
+}
+
+int ftrace_make_nop(struct module *mod,
+ struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ unsigned long old;
+ unsigned long new;
+ int ret;
+
+ old = ftrace_call_replace(ip, adjust_address(rec, addr));
+ new = ftrace_nop_replace(rec);
+ ret = ftrace_modify_code(ip, old, new);
+
+#ifdef CONFIG_OLD_MCOUNT
+ if (ret == -EINVAL && addr == MCOUNT_ADDR) {
+ rec->arch.old_mcount = true;
+
+ old = ftrace_call_replace(ip, adjust_address(rec, addr));
+ new = ftrace_nop_replace(rec);
+ ret = ftrace_modify_code(ip, old, new);
+ }
+#endif
+
return ret;
}

-/* run from ftrace_init with irqs disabled */
int __init ftrace_dyn_arch_init(void *data)
{
- ftrace_mcount_set(data);
+ *(unsigned long *)data = 0;
+
return 0;
}
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index f3c9c0a..319af1e 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -268,6 +268,8 @@ if ($arch eq "x86_64") {
} elsif ($arch eq "arm") {
$alignment = 2;
$section_type = '%progbits';
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24)" .
+ "\\s+(__gnu_mcount_nc|mcount)\$";

} elsif ($arch eq "ia64") {
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
Add a comment describing the mcount variants and how the callsites look
like.

Acked-by: Frederic Weisbecker <fwei...@gmail.com>


Signed-off-by: Rabin Vincent <ra...@rab.in>
---

v2: Reword/expand comment.

arch/arm/kernel/entry-common.S | 36 ++++++++++++++++++++++++++++++++++++
1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 0b042bd..f05a35a 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -92,6 +92,42 @@ ENDPROC(ret_from_fork)
#define CALL(x) .long x

#ifdef CONFIG_FUNCTION_TRACER
+/*
+ * When compiling with -pg, gcc inserts a call to the mcount routine at the
+ * start of every function. In mcount, apart from the function's address (in
+ * lr), we need to get hold of the function's caller's address.
+ *
+ * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this:
+ *
+ * bl mcount
+ *
+ * These versions have the limitation that in order for the mcount routine to
+ * be able to determine the function's caller's address, an APCS-style frame
+ * pointer (which is set up with something like the code below) is required.
+ *
+ * mov ip, sp
+ * push {fp, ip, lr, pc}
+ * sub fp, ip, #4
+ *
+ * With EABI, these frame pointers are not available unless -mapcs-frame is
+ * specified, and if building as Thumb-2, not even then.
+ *
+ * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount,
+ * with call sites like:
+ *
+ * push {lr}
+ * bl __gnu_mcount_nc
+ *
+ * With these compilers, frame pointers are not necessary.
+ *
+ * mcount can be thought of as a function called in the middle of a subroutine
+ * call. As such, it needs to be transparent for both the caller and the
+ * callee: the original lr needs to be restored when leaving mcount, and no
+ * registers should be clobbered. (In the __gnu_mcount_nc implementation, we
+ * clobber the ip register. This is OK because the ARM calling convention
+ * allows it to be clobbered in subroutines and doesn't use it to hold
+ * parameters.)
+ */
#ifdef CONFIG_DYNAMIC_FTRACE
ENTRY(mcount)
stmdb sp!, {r0-r3, lr}
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:03 AM3/13/10
to
On ARM, we have two ABIs, and the ABI used is controlled via a config
option. Object files built with one ABI can't be merged with object
files built with the other ABI. So, record_mcount.pl needs to use the
same compiler flags as the kernel when generating the object file with
the mcount locations. Ensure this by passing CFLAGS to the script.

Signed-off-by: Rabin Vincent <ra...@rab.in>
---

scripts/Makefile.build | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 0b94d2f..2535c11 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -209,7 +209,8 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
"$(if $(CONFIG_64BIT),64,32)" \
- "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+ "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
+ "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
"$(if $(part-of-module),1,0)" "$(@)";
endif

--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:03 AM3/13/10
to
Dynamic ftrace for ARM has been disabled since 07c4cc1cdaa08f ("ftrace:
disable dynamic ftrace for all archs that use daemon"). Now that the
code has been updated, re-enable it.

Signed-off-by: Rabin Vincent <ra...@rab.in>
---

arch/arm/Kconfig | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cadfe2e..a264837 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -18,6 +18,8 @@ config ARM
select HAVE_KPROBES if (!XIP_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+ select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
+ select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
select HAVE_GENERIC_DMA_COHERENT
select HAVE_KERNEL_GZIP
select HAVE_KERNEL_LZO
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
With a new enough GCC, ARM function tracing can be supported without the
need for frame pointers. This is essential for Thumb-2 support, since
frame pointers aren't available then.

Signed-off-by: Rabin Vincent <ra...@rab.in>
---

v2: #error if incompatible GCC.

arch/arm/Kconfig.debug | 5 +++++
arch/arm/kernel/armksyms.c | 2 ++
arch/arm/kernel/entry-common.S | 14 ++++++++++++++
kernel/trace/Kconfig | 2 +-
4 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 91344af..4dbce53 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -27,6 +27,11 @@ config ARM_UNWIND
the performance is not affected. Currently, this feature
only works with EABI compilers. If unsure say Y.

+config OLD_MCOUNT
+ bool
+ depends on FUNCTION_TRACER && FRAME_POINTER
+ default y
+
config DEBUG_USER
bool "Verbose user fault messages"
help
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 8214bfe..e5e1e53 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -165,6 +165,8 @@ EXPORT_SYMBOL(_find_next_bit_be);
#endif

#ifdef CONFIG_FUNCTION_TRACER
+#ifdef CONFIG_OLD_MCOUNT
EXPORT_SYMBOL(mcount);
+#endif
EXPORT_SYMBOL(__gnu_mcount_nc);
#endif
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index f05a35a..6805a72 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -128,6 +128,13 @@ ENDPROC(ret_from_fork)


* allows it to be clobbered in subroutines and doesn't use it to hold

* parameters.)
*/
+
+#ifndef CONFIG_OLD_MCOUNT
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0.
+#endif
+#endif
+


#ifdef CONFIG_DYNAMIC_FTRACE
ENTRY(mcount)
stmdb sp!, {r0-r3, lr}

@@ -173,6 +180,12 @@ gnu_trace:


ldmia sp!, {r0-r3, ip, lr}

mov pc, ip

+#ifdef CONFIG_OLD_MCOUNT
+/*
+ * This is under an ifdef in order to force link-time errors for people trying
+ * to build with !FRAME_POINTER with a GCC which doesn't use the new-style
+ * mcount.
+ */


ENTRY(mcount)
stmdb sp!, {r0-r3, lr}

ldr r0, =ftrace_trace_function
@@ -191,6 +204,7 @@ trace:
mov pc, r2


ldr lr, [fp, #-4] @ restore lr
ldmia sp!, {r0-r3, pc}

+#endif

#endif /* CONFIG_DYNAMIC_FTRACE */

diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 13e13d4..e10519f 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -124,7 +124,7 @@ if FTRACE
config FUNCTION_TRACER
bool "Kernel Function Tracer"
depends on HAVE_FUNCTION_TRACER
- select FRAME_POINTER
+ select FRAME_POINTER if (!ARM_UNWIND)
select KALLSYMS
select GENERIC_TRACER
select CONTEXT_SWITCH_TRACER
--
1.7.0

Rabin Vincent

unread,
Mar 13, 2010, 2:00:02 AM3/13/10
to
Handle the different nop and call instructions for Thumb-2. Also, we
need to adjust the recorded mcount_loc addresses because they have the
lsb set.

Cc: Catalin Marinas <catalin...@arm.com>
Acked-by: Steven Rostedt <ros...@goodmis.org> [recordmcount.pl change]


Signed-off-by: Rabin Vincent <ra...@rab.in>
---

v2: #ifdef in ftrace_call_adjust replaced with comment.

arch/arm/include/asm/ftrace.h | 3 ++-
arch/arm/kernel/ftrace.c | 33 +++++++++++++++++++++++++++++++++
scripts/recordmcount.pl | 2 +-
3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index 4a56a2e..f89515a 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -18,7 +18,8 @@ struct dyn_arch_ftrace {



static inline unsigned long ftrace_call_adjust(unsigned long addr)

{
- return addr;
+ /* With Thumb-2, the recorded addresses have the lsb set */
+ return addr & ~1;
}

extern void ftrace_caller_old(void);
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c
index f09014c..971ac8c 100644
--- a/arch/arm/kernel/ftrace.c
+++ b/arch/arm/kernel/ftrace.c
@@ -18,7 +18,11 @@
#include <asm/cacheflush.h>
#include <asm/ftrace.h>

+#ifdef CONFIG_THUMB2_KERNEL
+#define NOP 0xeb04f85d /* pop.w {lr} */
+#else


#define NOP 0xe8bd4000 /* pop {lr} */

+#endif

#ifdef CONFIG_OLD_MCOUNT
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
@@ -56,6 +60,34 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)


#endif

/* construct a branch (BL) instruction to addr */

+#ifdef CONFIG_THUMB2_KERNEL


+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)

+{
+ unsigned long s, j1, j2, i1, i2, imm10, imm11;
+ unsigned long first, second;
+ long offset;
+
+ offset = (long)addr - (long)(pc + 4);
+ if (offset < -16777216 || offset > 16777214) {
+ WARN_ON_ONCE(1);
+ return 0;
+ }
+
+ s = (offset >> 24) & 0x1;
+ i1 = (offset >> 23) & 0x1;
+ i2 = (offset >> 22) & 0x1;
+ imm10 = (offset >> 12) & 0x3ff;
+ imm11 = (offset >> 1) & 0x7ff;
+
+ j1 = (!i1) ^ s;
+ j2 = (!i2) ^ s;
+
+ first = 0xf000 | (s << 10) | imm10;
+ second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
+
+ return (second << 16) | first;
+}
+#else


static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
{
long offset;

@@ -73,6 +105,7 @@ static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)

return 0xeb000000 | offset;
}
+#endif



static int ftrace_modify_code(unsigned long pc, unsigned long old,

unsigned long new)
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 319af1e..0218a1b 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -268,7 +268,7 @@ if ($arch eq "x86_64") {


} elsif ($arch eq "arm") {
$alignment = 2;
$section_type = '%progbits';

- $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24)" .
+ $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .


"\\s+(__gnu_mcount_nc|mcount)\$";

} elsif ($arch eq "ia64") {

--
1.7.0

Steven Rostedt

unread,
Mar 13, 2010, 12:40:02 PM3/13/10
to

I believe this is correct, but have you tested this on other archs other
than ARM? I can do it for x86 and PPC, but it will need to wait as those
machines are currently performing stress tests.

-- Steve

> endif
> +endif
>
> ifdef CONFIG_DEBUG_INFO
> KBUILD_CFLAGS += -g

--

Steven Rostedt

unread,
Mar 13, 2010, 12:40:03 PM3/13/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> With a new enough GCC, ARM function tracing can be supported without the
> need for frame pointers. This is essential for Thumb-2 support, since
> frame pointers aren't available then.
>
> Signed-off-by: Rabin Vincent <ra...@rab.in>

> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig


> index 13e13d4..e10519f 100644
> --- a/kernel/trace/Kconfig
> +++ b/kernel/trace/Kconfig
> @@ -124,7 +124,7 @@ if FTRACE
> config FUNCTION_TRACER
> bool "Kernel Function Tracer"
> depends on HAVE_FUNCTION_TRACER
> - select FRAME_POINTER
> + select FRAME_POINTER if (!ARM_UNWIND)

I'm fine with this if the ARM maintainers are.

Acked-by: Steven Rostedt <ros...@goodmis.org>

-- Steve

> select KALLSYMS
> select GENERIC_TRACER
> select CONTEXT_SWITCH_TRACER

--

Steven Rostedt

unread,
Mar 13, 2010, 12:50:02 PM3/13/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> This adds mcount recording and updates dynamic ftrace for ARM to work
> with the new ftrace dyamic tracing implementation. It also adds support
> for the mcount format used by newer ARM compilers.
>
> With dynamic tracing, mcount() is implemented as a nop. Callsites are
> patched on startup with nops, and dynamically patched to call to the
> ftrace_caller() routine as needed.
>
> Signed-off-by: Rabin Vincent <rabin@rab.i


> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index f3c9c0a..319af1e 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -268,6 +268,8 @@ if ($arch eq "x86_64") {
> } elsif ($arch eq "arm") {
> $alignment = 2;
> $section_type = '%progbits';
> + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24)" .
> + "\\s+(__gnu_mcount_nc|mcount)\$";
>
> } elsif ($arch eq "ia64") {
> $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";

Acked-by: Steven Rostedt <ros...@goodmis.org>

-- Steve

--

Steven Rostedt

unread,
Mar 13, 2010, 12:50:02 PM3/13/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> On ARM, we have two ABIs, and the ABI used is controlled via a config
> option. Object files built with one ABI can't be merged with object
> files built with the other ABI. So, record_mcount.pl needs to use the
> same compiler flags as the kernel when generating the object file with
> the mcount locations. Ensure this by passing CFLAGS to the script.
>
> Signed-off-by: Rabin Vincent <ra...@rab.in>
> ---
> scripts/Makefile.build | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 0b94d2f..2535c11 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -209,7 +209,8 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
> cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
> "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
> "$(if $(CONFIG_64BIT),64,32)" \
> - "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
> + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
> + "$(LD)" "$(NM)" "$(RM)" "$(MV)" \

Again, I'll have to test this on other archs, just to make sure its does
not cause any side effects. Oh, I forgot I now have a MIPS board I can
test on too. I'll probably do this on Monday.

Thanks,

-- Steve

> "$(if $(part-of-module),1,0)" "$(@)";
> endif
>

--

Steven Rostedt

unread,
Mar 14, 2010, 1:00:03 PM3/14/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> On ARM, we have two ABIs, and the ABI used is controlled via a config
> option. Object files built with one ABI can't be merged with object
> files built with the other ABI. So, record_mcount.pl needs to use the
> same compiler flags as the kernel when generating the object file with
> the mcount locations. Ensure this by passing CFLAGS to the script.
>
> Signed-off-by: Rabin Vincent <ra...@rab.in>
> ---
> scripts/Makefile.build | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 0b94d2f..2535c11 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -209,7 +209,8 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
> cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
> "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
> "$(if $(CONFIG_64BIT),64,32)" \
> - "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
> + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
> + "$(LD)" "$(NM)" "$(RM)" "$(MV)" \

Again, I'll have to test this on other archs, just to make sure its does


not cause any side effects. Oh, I forgot I now have a MIPS board I can
test on too. I'll probably do this on Monday.

Thanks,

-- Steve

> "$(if $(part-of-module),1,0)" "$(@)";
> endif
>

--

Steven Rostedt

unread,
Mar 14, 2010, 1:00:02 PM3/14/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:

I believe this is correct, but have you tested this on other archs other


than ARM? I can do it for x86 and PPC, but it will need to wait as those
machines are currently performing stress tests.

-- Steve

> endif


> +endif
>
> ifdef CONFIG_DEBUG_INFO
> KBUILD_CFLAGS += -g

--

Steven Rostedt

unread,
Mar 14, 2010, 1:00:02 PM3/14/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> This adds mcount recording and updates dynamic ftrace for ARM to work
> with the new ftrace dyamic tracing implementation. It also adds support
> for the mcount format used by newer ARM compilers.
>
> With dynamic tracing, mcount() is implemented as a nop. Callsites are
> patched on startup with nops, and dynamically patched to call to the
> ftrace_caller() routine as needed.
>
> Signed-off-by: Rabin Vincent <rabin@rab.i


> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index f3c9c0a..319af1e 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -268,6 +268,8 @@ if ($arch eq "x86_64") {
> } elsif ($arch eq "arm") {
> $alignment = 2;
> $section_type = '%progbits';
> + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24)" .
> + "\\s+(__gnu_mcount_nc|mcount)\$";
>
> } elsif ($arch eq "ia64") {
> $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";

Acked-by: Steven Rostedt <ros...@goodmis.org>

-- Steve

--

Steven Rostedt

unread,
Mar 14, 2010, 1:00:02 PM3/14/10
to
On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> With a new enough GCC, ARM function tracing can be supported without the
> need for frame pointers. This is essential for Thumb-2 support, since
> frame pointers aren't available then.
>
> Signed-off-by: Rabin Vincent <ra...@rab.in>

> diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig


> index 13e13d4..e10519f 100644
> --- a/kernel/trace/Kconfig
> +++ b/kernel/trace/Kconfig
> @@ -124,7 +124,7 @@ if FTRACE
> config FUNCTION_TRACER
> bool "Kernel Function Tracer"
> depends on HAVE_FUNCTION_TRACER
> - select FRAME_POINTER
> + select FRAME_POINTER if (!ARM_UNWIND)

I'm fine with this if the ARM maintainers are.

Acked-by: Steven Rostedt <ros...@goodmis.org>

-- Steve

> select KALLSYMS
> select GENERIC_TRACER
> select CONTEXT_SWITCH_TRACER

--

Catalin Marinas

unread,
Mar 14, 2010, 6:40:02 PM3/14/10
to
On Sat, 2010-03-13 at 06:49 +0000, Rabin Vincent wrote:
> - The problem with the "mov lr, pc", is that it does not set the lsb when
> storing the pc in lr. The called function returns with "bx lr", and the
> mode changes to ARM. The blx is to avoid this.

I'm not familiar with ftrace but why does the called function returns
using "bx lr". Is this generated by the compiler? I had the impression
that if we don't enable interworking, we wouldn't get this instruction
(but haven't tried this yet).

--
Catalin

Rabin Vincent

unread,
Mar 15, 2010, 2:40:02 PM3/15/10
to
On Sun, Mar 14, 2010 at 10:30:15PM +0000, Catalin Marinas wrote:
> On Sat, 2010-03-13 at 06:49 +0000, Rabin Vincent wrote:
> > - The problem with the "mov lr, pc", is that it does not set the lsb when
> > storing the pc in lr. The called function returns with "bx lr", and the
> > mode changes to ARM. The blx is to avoid this.
>
> I'm not familiar with ftrace but why does the called function returns
> using "bx lr". Is this generated by the compiler? I had the impression
> that if we don't enable interworking, we wouldn't get this instruction
> (but haven't tried this yet).

There's nothing special about the called function: it's just a regular C
function. GCC uses "bx lr" for the return.

Rabin

Rabin Vincent

unread,
Mar 15, 2010, 2:50:01 PM3/15/10
to
On Sat, Mar 13, 2010 at 12:36:32PM -0500, Steven Rostedt wrote:
> On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> > ifdef CONFIG_FRAME_POINTER
> > KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
> > else
> > +# Some targets (ARM with Thumb2, for example), can't be built with frame
> > +# pointers. For those, we don't have FUNCTION_TRACER automatically
> > +# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
> > +# incompatible with -fomit-frame-pointer with current GCC, so we don't use
> > +# -fomit-frame-pointer with FUNCTION_TRACER.
> > +ifndef CONFIG_FUNCTION_TRACER
> > KBUILD_CFLAGS += -fomit-frame-pointer
>
> I believe this is correct, but have you tested this on other archs other
> than ARM? I can do it for x86 and PPC, but it will need to wait as those
> machines are currently performing stress tests.

I've tested the series on x86-64.

Note that this particular change will not currently affect other archs
since they still have the "select FRAME_POINTER" in FUNCTION_TRACER.

Rabin

Catalin Marinas

unread,
Mar 16, 2010, 6:30:03 AM3/16/10
to
Hi Rabin,

Rabin Vincent <ra...@rab.in> wrote:
> Fix the mcount routines to build and run on a kernel built with the
> Thumb-2 instruction set:
>
> - Without the BSYM, the following assembler errors appear:
>
> entry-common.S: Assembler messages:
> entry-common.S:179: Error: invalid immediate for address calculation (value = 0x00000004)

I'm still confused by this. I think that's a compiler problem but need
to get some feedback from toolchain people.

> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S
> @@ -167,7 +167,8 @@ ENTRY(__gnu_mcount_nc)
> stmdb sp!, {r0-r3, lr}
> ldr r0, =ftrace_trace_function
> ldr r2, [r0]
> - adr r0, ftrace_stub
> + THUMB( orr r2, r2, #1 )
> + adr r0, BSYM(ftrace_stub)

If the ftrace_stub isn't .globl, the code compiles fine. My approach
would be something like this:

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index d085033..5f5aef6 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -122,7 +122,7 @@ ENTRY(__gnu_mcount_nc)


stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
ldr r2, [r0]
- adr r0, ftrace_stub

+ adr r0, 1f


cmp r0, r2
bne gnu_trace
ldmia sp!, {r0-r3, ip, lr}

@@ -132,8 +132,9 @@ gnu_trace:


ldr r1, [sp, #20] @ lr of instrumented routine
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
- mov lr, pc

+ adr lr, BSYM(2f)
mov pc, r2
+2:


ldmia sp!, {r0-r3, ip, lr}
mov pc, ip

@@ -141,7 +142,7 @@ ENTRY(mcount)


stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
ldr r2, [r0]
- adr r0, ftrace_stub

+ adr r0, 1f
cmp r0, r2
bne trace


ldr lr, [fp, #-4] @ restore lr

@@ -160,6 +161,7 @@ trace:

.globl ftrace_stub
ftrace_stub:
+1:
mov pc, lr

#endif /* CONFIG_FUNCTION_TRACER */

--
Catalin

Catalin Marinas

unread,
Mar 17, 2010, 12:20:07 PM3/17/10
to
On Sun, 2010-03-14 at 16:56 +0000, Steven Rostedt wrote:
> On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> > With a new enough GCC, ARM function tracing can be supported without the
> > need for frame pointers. This is essential for Thumb-2 support, since
> > frame pointers aren't available then.
> >
> > Signed-off-by: Rabin Vincent <ra...@rab.in>
>
> > diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
> > index 13e13d4..e10519f 100644
> > --- a/kernel/trace/Kconfig
> > +++ b/kernel/trace/Kconfig
> > @@ -124,7 +124,7 @@ if FTRACE
> > config FUNCTION_TRACER
> > bool "Kernel Function Tracer"
> > depends on HAVE_FUNCTION_TRACER
> > - select FRAME_POINTER
> > + select FRAME_POINTER if (!ARM_UNWIND)
>
> I'm fine with this if the ARM maintainers are.
>
> Acked-by: Steven Rostedt <ros...@goodmis.org>

I think we did this already in other places, so:

Acked-by: Catalin Marinas <catalin...@arm.com>

Rabin Vincent

unread,
Mar 31, 2010, 2:30:01 PM3/31/10
to
On Tue, Mar 16, 2010 at 10:23:54AM +0000, Catalin Marinas wrote:
> If the ftrace_stub isn't .globl, the code compiles fine. My approach
> would be something like this:

New patch below:

From bf828a0c069b1bb3f6bf4e68f1dceecab396c286 Mon Sep 17 00:00:00 2001
From: Rabin Vincent <ra...@rab.in>
Date: Sun, 14 Feb 2010 01:18:34 +0530
Subject: [PATCH 06/10] ARM: ftrace: add Thumb-2 support

Fix the mcount routines to build and run on a kernel built with the

Thumb-2 instruction set by correcting the following errors using the
fixes suggested by Catalin Marinas:

- Problem: The following assembler errors appear at the "adr r0,
ftrace_stub" instruction:

entry-common.S: Assembler messages:
entry-common.S:179: Error: invalid immediate for address calculation (value = 0x00000004)

Fix: The errors don't occur with a non-global symbol, so use one.

- Problem: The "mov lr, pc" does not set the lsb when storing the pc in


lr. The called function returns with "bx lr", and the mode changes
to ARM.

Fix: Add a label on the return address and use "adr lr, BSYM(label)".

We don't modify the old mcount because it won't be built when using
Thumb-2.

Cc: Catalin Marinas <catalin...@arm.com>
Signed-off-by: Rabin Vincent <ra...@rab.in>
---

arch/arm/kernel/entry-common.S | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index c7a8c20..f5e75de 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -167,7 +167,7 @@ ENTRY(__gnu_mcount_nc)


stmdb sp!, {r0-r3, lr}
ldr r0, =ftrace_trace_function
ldr r2, [r0]
- adr r0, ftrace_stub

+ adr r0, .Lftrace_stub


cmp r0, r2
bne gnu_trace
ldmia sp!, {r0-r3, ip, lr}

@@ -177,8 +177,9 @@ gnu_trace:


ldr r1, [sp, #20] @ lr of instrumented routine
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
- mov lr, pc

+ adr lr, BSYM(1f)
mov pc, r2
+1:


ldmia sp!, {r0-r3, ip, lr}
mov pc, ip

ENDPROC(__gnu_mcount_nc)
@@ -213,6 +214,7 @@ ENDPROC(mcount)
#endif /* CONFIG_DYNAMIC_FTRACE */

ENTRY(ftrace_stub)
+.Lftrace_stub:
mov pc, lr
ENDPROC(ftrace_stub)

--
1.7.0

Rabin Vincent

unread,
Mar 31, 2010, 2:50:01 PM3/31/10
to
On Sun, Mar 14, 2010 at 12:56:11PM -0400, Steven Rostedt wrote:
> On Sat, 2010-03-13 at 12:19 +0530, Rabin Vincent wrote:
> > diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> > index 0b94d2f..2535c11 100644
> > --- a/scripts/Makefile.build
> > +++ b/scripts/Makefile.build
> > @@ -209,7 +209,8 @@ ifdef CONFIG_FTRACE_MCOUNT_RECORD
> > cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
> > "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
> > "$(if $(CONFIG_64BIT),64,32)" \
> > - "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
> > + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
> > + "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>
> Again, I'll have to test this on other archs, just to make sure its does
> not cause any side effects. Oh, I forgot I now have a MIPS board I can
> test on too. I'll probably do this on Monday.

I've now built PowerPC, SH, and MIPS kernels with dynamic ftrace enabled
and checked that the obj files don't change as the result of this
series. I've run the MIPS kernel on QEMU and x86_64 on my PC.

Rabin

Rabin Vincent

unread,
Apr 21, 2010, 3:30:02 PM4/21/10
to
Hi Steven,

On Sat, Mar 13, 2010 at 12:19:37PM +0530, Rabin Vincent wrote:
> This series contains fixes and improvements to the ARM ftrace support. It adds
> Thumb-2 support and re-implements the dynamic ftrace support.

Do you have any further concerns about this patchset?

If not, do you mind if I try to send in the series (v2 + the two updated
patches) via the ARM patch system, since most of the patches only touch
code under arch/arm/?

Rabin

Catalin Marinas

unread,
Apr 23, 2010, 11:40:02 AM4/23/10
to
On Wed, 2010-03-31 at 19:25 +0100, Rabin Vincent wrote:
> From bf828a0c069b1bb3f6bf4e68f1dceecab396c286 Mon Sep 17 00:00:00 2001
> From: Rabin Vincent <ra...@rab.in>
> Date: Sun, 14 Feb 2010 01:18:34 +0530
> Subject: [PATCH 06/10] ARM: ftrace: add Thumb-2 support
>
> Fix the mcount routines to build and run on a kernel built with the
> Thumb-2 instruction set by correcting the following errors using the
> fixes suggested by Catalin Marinas:
>
> - Problem: The following assembler errors appear at the "adr r0,
> ftrace_stub" instruction:
>
> entry-common.S: Assembler messages:
> entry-common.S:179: Error: invalid immediate for address calculation (value = 0x00000004)
>
> Fix: The errors don't occur with a non-global symbol, so use one.
>
> - Problem: The "mov lr, pc" does not set the lsb when storing the pc in
> lr. The called function returns with "bx lr", and the mode changes
> to ARM.
>
> Fix: Add a label on the return address and use "adr lr, BSYM(label)".
>
> We don't modify the old mcount because it won't be built when using
> Thumb-2.
>
> Cc: Catalin Marinas <catalin...@arm.com>
> Signed-off-by: Rabin Vincent <ra...@rab.in>

Acked-by: Catalin Marinas <catalin...@arm.com>

--
Catalin

Rabin Vincent

unread,
Aug 3, 2010, 12:50:01 PM8/3/10
to
Steven, Frederic,

I'd like to resurrect this old ARM dynamic ftrace patchset. It still
applies on next except for a small merge conflict in one of the
ARM-specific patches.

On Sat, Mar 13, 2010 at 12:19:44PM +0530, Rabin Vincent wrote:
> On ARM, we have two ABIs, and the ABI used is controlled via a config
> option. Object files built with one ABI can't be merged with object
> files built with the other ABI. So, record_mcount.pl needs to use the
> same compiler flags as the kernel when generating the object file with
> the mcount locations. Ensure this by passing CFLAGS to the script.
>
> Signed-off-by: Rabin Vincent <ra...@rab.in>

This is the only non-arch/arm/ patch in the series which doesn't have
either of your Acked-bys, so if you'd be willing to ack it, I'll send in
the lot via rmk's ARM patch system for .37.

Alternatively, this one and "[PATCH 03/10] ftrace: allow building
without frame pointers" could go in via the tracing tree for .36? Then
I'll send in the ARM specific stuff for .37 via the ARM tree.

Thanks,
Rabin

Frederic Weisbecker

unread,
Aug 6, 2010, 11:40:02 AM8/6/10
to
On Tue, Aug 03, 2010 at 10:12:47PM +0530, Rabin Vincent wrote:
> Steven, Frederic,
>
> I'd like to resurrect this old ARM dynamic ftrace patchset. It still
> applies on next except for a small merge conflict in one of the
> ARM-specific patches.
>
> On Sat, Mar 13, 2010 at 12:19:44PM +0530, Rabin Vincent wrote:
> > On ARM, we have two ABIs, and the ABI used is controlled via a config
> > option. Object files built with one ABI can't be merged with object
> > files built with the other ABI. So, record_mcount.pl needs to use the
> > same compiler flags as the kernel when generating the object file with
> > the mcount locations. Ensure this by passing CFLAGS to the script.
> >
> > Signed-off-by: Rabin Vincent <ra...@rab.in>
>
> This is the only non-arch/arm/ patch in the series which doesn't have
> either of your Acked-bys, so if you'd be willing to ack it, I'll send in
> the lot via rmk's ARM patch system for .37.
>
> Alternatively, this one and "[PATCH 03/10] ftrace: allow building
> without frame pointers" could go in via the tracing tree for .36? Then
> I'll send in the ARM specific stuff for .37 via the ARM tree.
>
> Thanks,
> Rabin

I'll let Steve handling this one as I have few skills with things that touch
scripts/recordmcount.pl :)

Steven Rostedt

unread,
Aug 6, 2010, 4:30:02 PM8/6/10
to
Sorry for the late reply, just got back from vacation.

Hmm, this changes the number of parameters passed to the
recordmcount.pl. shouldn't this be part of the change to
recordmcount.pl? Otherwise, we can break a bisect.

-- Steve

Rabin Vincent

unread,
Aug 7, 2010, 1:40:01 AM8/7/10
to
On Sat, Aug 7, 2010 at 1:53 AM, Steven Rostedt <ros...@goodmis.org> wrote:
>> >     "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
>> >     "$(if $(CONFIG_64BIT),64,32)" \
>> > -   "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>> > +   "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
>> > +   "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>
> Hmm, this changes the number of parameters passed to the
> recordmcount.pl. shouldn't this be part of the change to
> recordmcount.pl? Otherwise, we can break a bisect.

No, this doesn't change the number of parameters. KBUILD_CFLAGS
is included inside the CC argument.

Rabin

Steven Rostedt

unread,
Aug 7, 2010, 9:20:02 AM8/7/10
to
Sorry for top post. Sent from phone.

Argh! We had this discussion before. I must be getting old.

Acked-by: Steven Rostedt <ros...@goodmis.org>

-- Steve


"Rabin Vincent" <ra...@rab.in> wrote:

>On Sat, Aug 7, 2010 at 1:53 AM, Steven Rostedt <ros...@goodmis.org> wrote:
>>> >     "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
>>> >     "$(if $(CONFIG_64BIT),64,32)" \
>>> > -   "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>>> > +   "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
>>> > +   "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
>>
>> Hmm, this changes the number of parameters passed to the
>> recordmcount.pl. shouldn't this be part of the change to
>> recordmcount.pl? Otherwise, we can break a bisect.
>
>No, this doesn't change the number of parameters. KBUILD_CFLAGS
>is included inside the CC argument.
>
>Rabin

--
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

0 new messages