aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/ftrace.c')
-rw-r--r--arch/mips/kernel/ftrace.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 6a2d758dd8e9..83fa1460e294 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -25,6 +25,12 @@
25#define MCOUNT_OFFSET_INSNS 4 25#define MCOUNT_OFFSET_INSNS 4
26#endif 26#endif
27 27
28/* Arch override because MIPS doesn't need to run this from stop_machine() */
29void arch_ftrace_update_code(int command)
30{
31 ftrace_modify_all_code(command);
32}
33
28/* 34/*
29 * Check if the address is in kernel space 35 * Check if the address is in kernel space
30 * 36 *
@@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
89 return 0; 95 return 0;
90} 96}
91 97
98#ifndef CONFIG_64BIT
99static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
100 unsigned int new_code2)
101{
102 int faulted;
103
104 safe_store_code(new_code1, ip, faulted);
105 if (unlikely(faulted))
106 return -EFAULT;
107 ip += 4;
108 safe_store_code(new_code2, ip, faulted);
109 if (unlikely(faulted))
110 return -EFAULT;
111 flush_icache_range(ip, ip + 8); /* original ip + 12 */
112 return 0;
113}
114#endif
115
92/* 116/*
93 * The details about the calling site of mcount on MIPS 117 * The details about the calling site of mcount on MIPS
94 * 118 *
@@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod,
131 * needed. 155 * needed.
132 */ 156 */
133 new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; 157 new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
134 158#ifdef CONFIG_64BIT
135 return ftrace_modify_code(ip, new); 159 return ftrace_modify_code(ip, new);
160#else
161 /*
162 * On 32 bit MIPS platforms, gcc adds a stack adjust
163 * instruction in the delay slot after the branch to
164 * mcount and expects mcount to restore the sp on return.
165 * This is based on a legacy API and does nothing but
166 * waste instructions so it's being removed at runtime.
167 */
168 return ftrace_modify_code_2(ip, new, INSN_NOP);
169#endif
136} 170}
137 171
138int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) 172int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)