Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / tile / kernel / mcount_64.S
diff --git a/kernel/arch/tile/kernel/mcount_64.S b/kernel/arch/tile/kernel/mcount_64.S
new file mode 100644 (file)
index 0000000..6c67024
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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)
+       MCOUNT_SAVE_REGS
+
+       /* arg1: self return address */
+       /* arg2: parent's return address */
+       /* arg3: ftrace_ops */
+       /* arg4: regs (but make it NULL) */
+       { move  r0, lr;  moveli        r2, hw2_last(function_trace_op) }
+       { move  r1, r10; shl16insli    r2, r2, hw1(function_trace_op) }
+       { movei r3, 0;   shl16insli    r2, r2, hw0(function_trace_op) }
+       ld      r2,r2
+
+       .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(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 */