arm64: ftrace: Add CALLER_ADDRx macros
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Wed, 30 Apr 2014 09:54:35 +0000 (18:54 +0900)
committerMark Brown <broonie@linaro.org>
Fri, 30 May 2014 17:15:43 +0000 (18:15 +0100)
CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
arch/arm64/include/asm/ftrace.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/return_address.c [new file with mode: 0644]

index ed5c448ece991165ee322f8afc05610b3de88ba9..41e8670db20f6403a9d3616a56370da1f0ec326f 100644 (file)
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
        /* No extra data needed for arm64 */
@@ -33,6 +34,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
         */
        return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define ftrace_return_address(n) return_address(n)
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
index f3a5f4131d40754d2b84d0fc233de02f9b068e07..35cd35bb7f5460877010f2a068a92f86699471fb 100644 (file)
@@ -7,12 +7,13 @@ AFLAGS_head.o         := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
                           entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
                           sys.o stacktrace.o time.o traps.o io.o vdso.o        \
-                          hyp-stub.o psci.o insn.o
+                          hyp-stub.o psci.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
                                           sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644 (file)
index 0000000..89102a6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+       unsigned int level;
+       void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+       struct return_address_data *data = d;
+
+       if (!data->level) {
+               data->addr = (void *)frame->pc;
+               return 1;
+       } else {
+               --data->level;
+               return 0;
+       }
+}
+
+void *return_address(unsigned int level)
+{
+       struct return_address_data data;
+       struct stackframe frame;
+       register unsigned long current_sp asm ("sp");
+
+       data.level = level + 2;
+       data.addr = NULL;
+
+       frame.fp = (unsigned long)__builtin_frame_address(0);
+       frame.sp = current_sp;
+       frame.pc = (unsigned long)return_address; /* dummy */
+
+       walk_stackframe(&frame, save_return_addr, &data);
+
+       if (!data.level)
+               return data.addr;
+       else
+               return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);