|
@@ -0,0 +1,224 @@
|
|
|
+/*
|
|
|
+ * Copyright 2012 Tilera Corporation. All Rights Reserved.
|
|
|
+ *
|
|
|
+ * This program is free software; you can redistribute it and/or
|
|
|
+ * modify it under the terms of the GNU General Public License
|
|
|
+ * as published by the Free Software Foundation, version 2.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful, but
|
|
|
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
|
+ * NON INFRINGEMENT. See the GNU General Public License for
|
|
|
+ * more details.
|
|
|
+ *
|
|
|
+ * TILE-Gx specific __mcount support
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/linkage.h>
|
|
|
+#include <asm/ftrace.h>
|
|
|
+
|
|
|
+#define REGSIZE 8
|
|
|
+
|
|
|
+ .text
|
|
|
+ .global __mcount
|
|
|
+
|
|
|
+ .macro MCOUNT_SAVE_REGS
|
|
|
+ addli sp, sp, -REGSIZE
|
|
|
+ {
|
|
|
+ st sp, lr
|
|
|
+ addli r29, sp, - (12 * REGSIZE)
|
|
|
+ }
|
|
|
+ {
|
|
|
+ addli sp, sp, - (13 * REGSIZE)
|
|
|
+ st r29, sp
|
|
|
+ }
|
|
|
+ addli r29, r29, REGSIZE
|
|
|
+ { st r29, r0; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r1; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r2; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r3; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r4; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r5; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r6; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r7; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r8; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r9; addli r29, r29, REGSIZE }
|
|
|
+ { st r29, r10; addli r29, r29, REGSIZE }
|
|
|
+ .endm
|
|
|
+
|
|
|
+ .macro MCOUNT_RESTORE_REGS
|
|
|
+ addli r29, sp, (2 * REGSIZE)
|
|
|
+ { ld r0, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r1, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r2, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r3, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r4, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r5, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r6, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r7, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r8, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r9, r29; addli r29, r29, REGSIZE }
|
|
|
+ { ld r10, r29; addli lr, sp, (13 * REGSIZE) }
|
|
|
+ { ld lr, lr; addli sp, sp, (14 * REGSIZE) }
|
|
|
+ .endm
|
|
|
+
|
|
|
+ .macro RETURN_BACK
|
|
|
+ { move r12, lr; move lr, r10 }
|
|
|
+ jrp r12
|
|
|
+ .endm
|
|
|
+
|
|
|
+#ifdef CONFIG_DYNAMIC_FTRACE
|
|
|
+
|
|
|
+ .align 64
|
|
|
+STD_ENTRY(__mcount)
|
|
|
+__mcount:
|
|
|
+ j ftrace_stub
|
|
|
+STD_ENDPROC(__mcount)
|
|
|
+
|
|
|
+ .align 64
|
|
|
+STD_ENTRY(ftrace_caller)
|
|
|
+ moveli r11, hw2_last(function_trace_stop)
|
|
|
+ { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr }
|
|
|
+ { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 }
|
|
|
+ ld r11, r11
|
|
|
+ beqz r11, 1f
|
|
|
+ jrp r12
|
|
|
+
|
|
|
+1:
|
|
|
+ { move r10, lr; move lr, r12 }
|
|
|
+ MCOUNT_SAVE_REGS
|
|
|
+
|
|
|
+ /* arg1: self return address */
|
|
|
+ /* arg2: parent's return address */
|
|
|
+ { move r0, lr; move r1, r10 }
|
|
|
+
|
|
|
+ .global ftrace_call
|
|
|
+ftrace_call:
|
|
|
+ /*
|
|
|
+ * a placeholder for the call to a real tracing function, i.e.
|
|
|
+ * ftrace_trace_function()
|
|
|
+ */
|
|
|
+ nop
|
|
|
+
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+ .global ftrace_graph_call
|
|
|
+ftrace_graph_call:
|
|
|
+ /*
|
|
|
+ * a placeholder for the call to a real tracing function, i.e.
|
|
|
+ * ftrace_graph_caller()
|
|
|
+ */
|
|
|
+ nop
|
|
|
+#endif
|
|
|
+ MCOUNT_RESTORE_REGS
|
|
|
+ .global ftrace_stub
|
|
|
+ftrace_stub:
|
|
|
+ RETURN_BACK
|
|
|
+STD_ENDPROC(ftrace_caller)
|
|
|
+
|
|
|
+#else /* ! CONFIG_DYNAMIC_FTRACE */
|
|
|
+
|
|
|
+ .align 64
|
|
|
+STD_ENTRY(__mcount)
|
|
|
+ moveli r11, hw2_last(function_trace_stop)
|
|
|
+ { shl16insli r11, r11, hw1(function_trace_stop); move r12, lr }
|
|
|
+ { shl16insli r11, r11, hw0(function_trace_stop); move lr, r10 }
|
|
|
+ ld r11, r11
|
|
|
+ beqz r11, 1f
|
|
|
+ jrp r12
|
|
|
+
|
|
|
+1:
|
|
|
+ { move r10, lr; move lr, r12 }
|
|
|
+ {
|
|
|
+ moveli r11, hw2_last(ftrace_trace_function)
|
|
|
+ moveli r13, hw2_last(ftrace_stub)
|
|
|
+ }
|
|
|
+ {
|
|
|
+ shl16insli r11, r11, hw1(ftrace_trace_function)
|
|
|
+ shl16insli r13, r13, hw1(ftrace_stub)
|
|
|
+ }
|
|
|
+ {
|
|
|
+ shl16insli r11, r11, hw0(ftrace_trace_function)
|
|
|
+ shl16insli r13, r13, hw0(ftrace_stub)
|
|
|
+ }
|
|
|
+
|
|
|
+ ld r11, r11
|
|
|
+ sub r14, r13, r11
|
|
|
+ bnez r14, static_trace
|
|
|
+
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+ moveli r15, hw2_last(ftrace_graph_return)
|
|
|
+ shl16insli r15, r15, hw1(ftrace_graph_return)
|
|
|
+ shl16insli r15, r15, hw0(ftrace_graph_return)
|
|
|
+ ld r15, r15
|
|
|
+ sub r15, r15, r13
|
|
|
+ bnez r15, ftrace_graph_caller
|
|
|
+
|
|
|
+ {
|
|
|
+ moveli r16, hw2_last(ftrace_graph_entry)
|
|
|
+ moveli r17, hw2_last(ftrace_graph_entry_stub)
|
|
|
+ }
|
|
|
+ {
|
|
|
+ shl16insli r16, r16, hw1(ftrace_graph_entry)
|
|
|
+ shl16insli r17, r17, hw1(ftrace_graph_entry_stub)
|
|
|
+ }
|
|
|
+ {
|
|
|
+ shl16insli r16, r16, hw0(ftrace_graph_entry)
|
|
|
+ shl16insli r17, r17, hw0(ftrace_graph_entry_stub)
|
|
|
+ }
|
|
|
+ ld r16, r16
|
|
|
+ sub r17, r16, r17
|
|
|
+ bnez r17, ftrace_graph_caller
|
|
|
+
|
|
|
+#endif
|
|
|
+ RETURN_BACK
|
|
|
+
|
|
|
+static_trace:
|
|
|
+ MCOUNT_SAVE_REGS
|
|
|
+
|
|
|
+ /* arg1: self return address */
|
|
|
+ /* arg2: parent's return address */
|
|
|
+ { move r0, lr; move r1, r10 }
|
|
|
+
|
|
|
+ /* call ftrace_trace_function() */
|
|
|
+ jalr r11
|
|
|
+
|
|
|
+ MCOUNT_RESTORE_REGS
|
|
|
+
|
|
|
+ .global ftrace_stub
|
|
|
+ftrace_stub:
|
|
|
+ RETURN_BACK
|
|
|
+STD_ENDPROC(__mcount)
|
|
|
+
|
|
|
+#endif /* ! CONFIG_DYNAMIC_FTRACE */
|
|
|
+
|
|
|
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
+
|
|
|
+STD_ENTRY(ftrace_graph_caller)
|
|
|
+ftrace_graph_caller:
|
|
|
+#ifndef CONFIG_DYNAMIC_FTRACE
|
|
|
+ MCOUNT_SAVE_REGS
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* arg1: Get the location of the parent's return address */
|
|
|
+ addi r0, sp, 12 * REGSIZE
|
|
|
+ /* arg2: Get self return address */
|
|
|
+ move r1, lr
|
|
|
+
|
|
|
+ jal prepare_ftrace_return
|
|
|
+
|
|
|
+ MCOUNT_RESTORE_REGS
|
|
|
+ RETURN_BACK
|
|
|
+STD_ENDPROC(ftrace_graph_caller)
|
|
|
+
|
|
|
+ .global return_to_handler
|
|
|
+return_to_handler:
|
|
|
+ MCOUNT_SAVE_REGS
|
|
|
+
|
|
|
+ jal ftrace_return_to_handler
|
|
|
+ /* restore the real parent address */
|
|
|
+ move r11, r0
|
|
|
+
|
|
|
+ MCOUNT_RESTORE_REGS
|
|
|
+ jr r11
|
|
|
+
|
|
|
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|