[PATCH 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support

2018-01-09 Thread Alan Kao
Cc: Greentime Hu 
Signed-off-by: Alan Kao 
---
 arch/riscv/Kconfig |   1 +
 arch/riscv/kernel/ftrace.c |  17 ++
 arch/riscv/kernel/mcount-dyn.S | 124 +
 3 files changed, 142 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 96db66272db5..06685bcf5643 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -114,6 +114,7 @@ config ARCH_RV64I
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
+   select HAVE_DYNAMIC_FTRACE_WITH_REGS
 
 endchoice
 
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 239ef5d56f24..c9cc884961d7 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -99,6 +99,23 @@ int __init ftrace_dyn_arch_init(void)
 }
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+  unsigned long addr)
+{
+   unsigned int offset = (unsigned int)(old_addr - rec->ip);
+   unsigned int auipc_call = to_auipc_insn(offset);
+   unsigned int jalr_call = to_jalr_insn(offset);
+   unsigned int calls[2] = {auipc_call, jalr_call};
+   int ret = ftrace_check_current_call(rec->ip, calls);
+
+   if (ret)
+   return ret;
+
+   return __ftrace_modify_call(rec->ip, addr, true);
+}
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Most of this function is copied from arm64.
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 627478571c7a..3ec3ddbfb5e7 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -118,3 +118,127 @@ ftrace_call:
RESTORE_ABI_STATE
ret
 ENDPROC(ftrace_caller)
+
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+   .macro SAVE_ALL
+   addisp, sp, -(PT_SIZE_ON_STACK+16)
+   sd  s0, (PT_SIZE_ON_STACK)(sp)
+   sd  ra, (PT_SIZE_ON_STACK+8)(sp)
+   addis0, sp, (PT_SIZE_ON_STACK+16)
+
+   sd x1,  PT_RA(sp)
+   sd x2,  PT_SP(sp)
+   sd x3,  PT_GP(sp)
+   sd x4,  PT_TP(sp)
+   sd x5,  PT_T0(sp)
+   sd x6,  PT_T1(sp)
+   sd x7,  PT_T2(sp)
+   sd x8,  PT_S0(sp)
+   sd x9,  PT_S1(sp)
+   sd x10, PT_A0(sp)
+   sd x11, PT_A1(sp)
+   sd x12, PT_A2(sp)
+   sd x13, PT_A3(sp)
+   sd x14, PT_A4(sp)
+   sd x15, PT_A5(sp)
+   sd x16, PT_A6(sp)
+   sd x17, PT_A7(sp)
+   sd x18, PT_S2(sp)
+   sd x19, PT_S3(sp)
+   sd x20, PT_S4(sp)
+   sd x21, PT_S5(sp)
+   sd x22, PT_S6(sp)
+   sd x23, PT_S7(sp)
+   sd x24, PT_S8(sp)
+   sd x25, PT_S9(sp)
+   sd x26, PT_S10(sp)
+   sd x27, PT_S11(sp)
+   sd x28, PT_T3(sp)
+   sd x29, PT_T4(sp)
+   sd x30, PT_T5(sp)
+   sd x31, PT_T6(sp)
+   .endm
+
+   .macro RESTORE_ALL
+   ld x1,  PT_RA(sp)
+   ld x2,  PT_SP(sp)
+   ld x3,  PT_GP(sp)
+   ld x4,  PT_TP(sp)
+   ld x5,  PT_T0(sp)
+   ld x6,  PT_T1(sp)
+   ld x7,  PT_T2(sp)
+   ld x8,  PT_S0(sp)
+   ld x9,  PT_S1(sp)
+   ld x10, PT_A0(sp)
+   ld x11, PT_A1(sp)
+   ld x12, PT_A2(sp)
+   ld x13, PT_A3(sp)
+   ld x14, PT_A4(sp)
+   ld x15, PT_A5(sp)
+   ld x16, PT_A6(sp)
+   ld x17, PT_A7(sp)
+   ld x18, PT_S2(sp)
+   ld x19, PT_S3(sp)
+   ld x20, PT_S4(sp)
+   ld x21, PT_S5(sp)
+   ld x22, PT_S6(sp)
+   ld x23, PT_S7(sp)
+   ld x24, PT_S8(sp)
+   ld x25, PT_S9(sp)
+   ld x26, PT_S10(sp)
+   ld x27, PT_S11(sp)
+   ld x28, PT_T3(sp)
+   ld x29, PT_T4(sp)
+   ld x30, PT_T5(sp)
+   ld x31, PT_T6(sp)
+
+   ld  s0, (PT_SIZE_ON_STACK)(sp)
+   ld  ra, (PT_SIZE_ON_STACK+8)(sp)
+   addisp, sp, (PT_SIZE_ON_STACK+16)
+   .endm
+
+   .macro RESTORE_GRAPH_REG_ARGS
+   ld  a0, PT_T0(sp)
+   ld  a1, PT_T1(sp)
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+   ld  a2, PT_T2(sp)
+#endif
+   .endm
+
+/*
+ * Most of the contents are the same as ftrace_caller.
+ */
+ENTRY(ftrace_regs_caller)
+   /*
+* a3: the address of all registers in the stack
+*/
+   ld  a1, -8(s0)
+   addia0, ra, -MCOUNT_INSN_SIZE
+   la  t5, function_trace_op
+   ld  a2, 0(t5)
+   addia3, sp, -(PT_SIZE_ON_STACK+16)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+   addit0, s0, -8
+   mv  t1, a0
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+   ld  t2, -16(s0)
+#endif
+#endif
+   SAVE_ALL
+
+ftrace_regs_call:
+   .global ftrace_regs_call
+   addix0, x0, 0
+   addix0, x0, 0
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+   RESTORE_GRAPH_REG_ARGS
+   callftrace_graph_caller
+#endif
+
+   RESTORE_ALL
+   ret
+ENDPROC(ftrace_regs_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
-- 
2.15.1



[PATCH 5/6] riscv/ftrace: Add DYNAMIC_FTRACE_WITH_REGS support

2018-01-09 Thread Alan Kao
Cc: Greentime Hu 
Signed-off-by: Alan Kao 
---
 arch/riscv/Kconfig |   1 +
 arch/riscv/kernel/ftrace.c |  17 ++
 arch/riscv/kernel/mcount-dyn.S | 124 +
 3 files changed, 142 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 96db66272db5..06685bcf5643 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -114,6 +114,7 @@ config ARCH_RV64I
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
+   select HAVE_DYNAMIC_FTRACE_WITH_REGS
 
 endchoice
 
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 239ef5d56f24..c9cc884961d7 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -99,6 +99,23 @@ int __init ftrace_dyn_arch_init(void)
 }
 #endif
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+  unsigned long addr)
+{
+   unsigned int offset = (unsigned int)(old_addr - rec->ip);
+   unsigned int auipc_call = to_auipc_insn(offset);
+   unsigned int jalr_call = to_jalr_insn(offset);
+   unsigned int calls[2] = {auipc_call, jalr_call};
+   int ret = ftrace_check_current_call(rec->ip, calls);
+
+   if (ret)
+   return ret;
+
+   return __ftrace_modify_call(rec->ip, addr, true);
+}
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Most of this function is copied from arm64.
diff --git a/arch/riscv/kernel/mcount-dyn.S b/arch/riscv/kernel/mcount-dyn.S
index 627478571c7a..3ec3ddbfb5e7 100644
--- a/arch/riscv/kernel/mcount-dyn.S
+++ b/arch/riscv/kernel/mcount-dyn.S
@@ -118,3 +118,127 @@ ftrace_call:
RESTORE_ABI_STATE
ret
 ENDPROC(ftrace_caller)
+
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+   .macro SAVE_ALL
+   addisp, sp, -(PT_SIZE_ON_STACK+16)
+   sd  s0, (PT_SIZE_ON_STACK)(sp)
+   sd  ra, (PT_SIZE_ON_STACK+8)(sp)
+   addis0, sp, (PT_SIZE_ON_STACK+16)
+
+   sd x1,  PT_RA(sp)
+   sd x2,  PT_SP(sp)
+   sd x3,  PT_GP(sp)
+   sd x4,  PT_TP(sp)
+   sd x5,  PT_T0(sp)
+   sd x6,  PT_T1(sp)
+   sd x7,  PT_T2(sp)
+   sd x8,  PT_S0(sp)
+   sd x9,  PT_S1(sp)
+   sd x10, PT_A0(sp)
+   sd x11, PT_A1(sp)
+   sd x12, PT_A2(sp)
+   sd x13, PT_A3(sp)
+   sd x14, PT_A4(sp)
+   sd x15, PT_A5(sp)
+   sd x16, PT_A6(sp)
+   sd x17, PT_A7(sp)
+   sd x18, PT_S2(sp)
+   sd x19, PT_S3(sp)
+   sd x20, PT_S4(sp)
+   sd x21, PT_S5(sp)
+   sd x22, PT_S6(sp)
+   sd x23, PT_S7(sp)
+   sd x24, PT_S8(sp)
+   sd x25, PT_S9(sp)
+   sd x26, PT_S10(sp)
+   sd x27, PT_S11(sp)
+   sd x28, PT_T3(sp)
+   sd x29, PT_T4(sp)
+   sd x30, PT_T5(sp)
+   sd x31, PT_T6(sp)
+   .endm
+
+   .macro RESTORE_ALL
+   ld x1,  PT_RA(sp)
+   ld x2,  PT_SP(sp)
+   ld x3,  PT_GP(sp)
+   ld x4,  PT_TP(sp)
+   ld x5,  PT_T0(sp)
+   ld x6,  PT_T1(sp)
+   ld x7,  PT_T2(sp)
+   ld x8,  PT_S0(sp)
+   ld x9,  PT_S1(sp)
+   ld x10, PT_A0(sp)
+   ld x11, PT_A1(sp)
+   ld x12, PT_A2(sp)
+   ld x13, PT_A3(sp)
+   ld x14, PT_A4(sp)
+   ld x15, PT_A5(sp)
+   ld x16, PT_A6(sp)
+   ld x17, PT_A7(sp)
+   ld x18, PT_S2(sp)
+   ld x19, PT_S3(sp)
+   ld x20, PT_S4(sp)
+   ld x21, PT_S5(sp)
+   ld x22, PT_S6(sp)
+   ld x23, PT_S7(sp)
+   ld x24, PT_S8(sp)
+   ld x25, PT_S9(sp)
+   ld x26, PT_S10(sp)
+   ld x27, PT_S11(sp)
+   ld x28, PT_T3(sp)
+   ld x29, PT_T4(sp)
+   ld x30, PT_T5(sp)
+   ld x31, PT_T6(sp)
+
+   ld  s0, (PT_SIZE_ON_STACK)(sp)
+   ld  ra, (PT_SIZE_ON_STACK+8)(sp)
+   addisp, sp, (PT_SIZE_ON_STACK+16)
+   .endm
+
+   .macro RESTORE_GRAPH_REG_ARGS
+   ld  a0, PT_T0(sp)
+   ld  a1, PT_T1(sp)
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+   ld  a2, PT_T2(sp)
+#endif
+   .endm
+
+/*
+ * Most of the contents are the same as ftrace_caller.
+ */
+ENTRY(ftrace_regs_caller)
+   /*
+* a3: the address of all registers in the stack
+*/
+   ld  a1, -8(s0)
+   addia0, ra, -MCOUNT_INSN_SIZE
+   la  t5, function_trace_op
+   ld  a2, 0(t5)
+   addia3, sp, -(PT_SIZE_ON_STACK+16)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+   addit0, s0, -8
+   mv  t1, a0
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+   ld  t2, -16(s0)
+#endif
+#endif
+   SAVE_ALL
+
+ftrace_regs_call:
+   .global ftrace_regs_call
+   addix0, x0, 0
+   addix0, x0, 0
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+   RESTORE_GRAPH_REG_ARGS
+   callftrace_graph_caller
+#endif
+
+   RESTORE_ALL
+   ret
+ENDPROC(ftrace_regs_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
-- 
2.15.1