xtensa: add static function tracer support

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Chris Zankel <chris@zankel.net>
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 8852c0d..7ea6451 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -19,6 +19,7 @@
 	select CLONE_BACKWARDS
 	select IRQ_DOMAIN
 	select HAVE_OPROFILE
+	select HAVE_FUNCTION_TRACER
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
index ad8952e..6868f2c 100644
--- a/arch/xtensa/boot/lib/Makefile
+++ b/arch/xtensa/boot/lib/Makefile
@@ -7,6 +7,13 @@
 lib-y	+= $(zlib:.c=.o) zmem.o
 
 ccflags-y	:= -Ilib/zlib_inflate
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_inflate.o = -pg
+CFLAGS_REMOVE_zmem.o = -pg
+CFLAGS_REMOVE_inftrees.o = -pg
+CFLAGS_REMOVE_inffast.o = -pg
+endif
+
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = cat $< > $@
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 36dc7a68..73cc3f4 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -13,6 +13,7 @@
 #include <asm/processor.h>
 
 #define HAVE_ARCH_CALLER_ADDR
+#ifndef __ASSEMBLY__
 #define CALLER_ADDR0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
@@ -24,10 +25,22 @@
 #define CALLER_ADDR1 return_address(1)
 #define CALLER_ADDR2 return_address(2)
 #define CALLER_ADDR3 return_address(3)
-#else
+#else /* CONFIG_FRAME_POINTER */
 #define CALLER_ADDR1 (0)
 #define CALLER_ADDR2 (0)
 #define CALLER_ADDR3 (0)
-#endif
+#endif /* CONFIG_FRAME_POINTER */
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+#define MCOUNT_INSN_SIZE 3
+
+#ifndef __ASSEMBLY__
+extern void _mcount(void);
+#define mcount _mcount
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
 
 #endif /* _XTENSA_FTRACE_H */
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 1e7fc87..f90265e 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -11,6 +11,7 @@
 obj-$(CONFIG_KGDB) += xtensa-stub.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
+obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
 
 AFLAGS_head.o += -mtext-section-literals
 
diff --git a/arch/xtensa/kernel/mcount.S b/arch/xtensa/kernel/mcount.S
new file mode 100644
index 0000000..0eeda2e
--- /dev/null
+++ b/arch/xtensa/kernel/mcount.S
@@ -0,0 +1,50 @@
+/*
+ * arch/xtensa/kernel/mcount.S
+ *
+ * Xtensa specific mcount support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2013 Tensilica Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/ftrace.h>
+
+/*
+ * Entry condition:
+ *
+ *   a2:	a0 of the caller
+ */
+
+ENTRY(_mcount)
+
+	entry	a1, 16
+
+	movi	a4, ftrace_trace_function
+	l32i	a4, a4, 0
+	movi	a3, ftrace_stub
+	bne	a3, a4, 1f
+	retw
+
+1: 	xor	a7, a2, a1
+	movi	a3, 0x3fffffff
+	and	a7, a7, a3
+	xor	a7, a7, a1
+
+	xor	a6, a0, a1
+	and	a6, a6, a3
+	xor	a6, a6, a1
+	addi	a6, a6, -MCOUNT_INSN_SIZE
+	callx4	a4
+
+	retw
+
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	entry	a1, 16
+	retw
+ENDPROC(ftrace_stub)
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index 42c53c87..d8507f8 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -124,3 +124,7 @@
 extern long _spill_registers;
 EXPORT_SYMBOL(common_exception_return);
 EXPORT_SYMBOL(_spill_registers);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif