diff options
Diffstat (limited to 'arch/mips/kernel/ftrace.c')
| -rw-r--r-- | arch/mips/kernel/ftrace.c | 36 | 
1 files changed, 35 insertions, 1 deletions
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c index 6a2d758dd8e..83fa1460e29 100644 --- a/arch/mips/kernel/ftrace.c +++ b/arch/mips/kernel/ftrace.c @@ -25,6 +25,12 @@  #define MCOUNT_OFFSET_INSNS 4  #endif +/* Arch override because MIPS doesn't need to run this from stop_machine() */ +void arch_ftrace_update_code(int command) +{ +	ftrace_modify_all_code(command); +} +  /*   * Check if the address is in kernel space   * @@ -89,6 +95,24 @@ static int ftrace_modify_code(unsigned long ip, unsigned int new_code)  	return 0;  } +#ifndef CONFIG_64BIT +static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1, +				unsigned int new_code2) +{ +	int faulted; + +	safe_store_code(new_code1, ip, faulted); +	if (unlikely(faulted)) +		return -EFAULT; +	ip += 4; +	safe_store_code(new_code2, ip, faulted); +	if (unlikely(faulted)) +		return -EFAULT; +	flush_icache_range(ip, ip + 8); /* original ip + 12 */ +	return 0; +} +#endif +  /*   * The details about the calling site of mcount on MIPS   * @@ -131,8 +155,18 @@ int ftrace_make_nop(struct module *mod,  	 * needed.  	 */  	new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F; - +#ifdef CONFIG_64BIT  	return ftrace_modify_code(ip, new); +#else +	/* +	 * On 32 bit MIPS platforms, gcc adds a stack adjust +	 * instruction in the delay slot after the branch to +	 * mcount and expects mcount to restore the sp on return. +	 * This is based on a legacy API and does nothing but +	 * waste instructions so it's being removed at runtime. +	 */ +	return ftrace_modify_code_2(ip, new, INSN_NOP); +#endif  }  int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  |