diff options
Diffstat (limited to 'arch/powerpc/kernel/trace/ftrace.c')
| -rw-r--r-- | arch/powerpc/kernel/trace/ftrace.c | 107 | 
1 files changed, 45 insertions, 62 deletions
| diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index d89c5df4f206..80b6285769f2 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -41,10 +41,10 @@  #define	NUM_FTRACE_TRAMPS	8  static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS]; -static struct ppc_inst +static ppc_inst_t  ftrace_call_replace(unsigned long ip, unsigned long addr, int link)  { -	struct ppc_inst op; +	ppc_inst_t op;  	addr = ppc_function_entry((void *)addr); @@ -55,9 +55,9 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link)  }  static int -ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new) +ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new)  { -	struct ppc_inst replaced; +	ppc_inst_t replaced;  	/*  	 * Note: @@ -90,24 +90,24 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new)   */  static int test_24bit_addr(unsigned long ip, unsigned long addr)  { -	struct ppc_inst op; +	ppc_inst_t op;  	addr = ppc_function_entry((void *)addr);  	/* use the create_branch to verify that this offset can be branched */  	return create_branch(&op, (u32 *)ip, addr, 0) == 0;  } -static int is_bl_op(struct ppc_inst op) +static int is_bl_op(ppc_inst_t op)  {  	return (ppc_inst_val(op) & 0xfc000003) == 0x48000001;  } -static int is_b_op(struct ppc_inst op) +static int is_b_op(ppc_inst_t op)  {  	return (ppc_inst_val(op) & 0xfc000003) == 0x48000000;  } -static unsigned long find_bl_target(unsigned long ip, struct ppc_inst op) +static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op)  {  	int offset; @@ -127,7 +127,7 @@ __ftrace_make_nop(struct module *mod,  {  	unsigned long entry, ptr, tramp;  	unsigned long ip = rec->ip; -	struct ppc_inst op, pop; +	ppc_inst_t op, pop;  	/* read where this goes */  	if (copy_inst_from_kernel_nofault(&op, (void *)ip)) { @@ -221,10 +221,9 @@ static int  __ftrace_make_nop(struct module *mod,  		  struct dyn_ftrace *rec, unsigned long addr)  { -	struct ppc_inst op; -	unsigned int jmp[4]; +	ppc_inst_t op;  	unsigned long ip = rec->ip; -	unsigned long tramp; +	unsigned long tramp, ptr;  	if (copy_from_kernel_nofault(&op, (void *)ip, MCOUNT_INSN_SIZE))  		return -EFAULT; @@ -238,41 +237,13 @@ __ftrace_make_nop(struct module *mod,  	/* lets find where the pointer goes */  	tramp = find_bl_target(ip, op); -	/* -	 * On PPC32 the trampoline looks like: -	 *  0x3d, 0x80, 0x00, 0x00  lis r12,sym@ha -	 *  0x39, 0x8c, 0x00, 0x00  addi r12,r12,sym@l -	 *  0x7d, 0x89, 0x03, 0xa6  mtctr r12 -	 *  0x4e, 0x80, 0x04, 0x20  bctr -	 */ - -	pr_devel("ip:%lx jumps to %lx", ip, tramp); -  	/* Find where the trampoline jumps to */ -	if (copy_from_kernel_nofault(jmp, (void *)tramp, sizeof(jmp))) { -		pr_err("Failed to read %lx\n", tramp); +	if (module_trampoline_target(mod, tramp, &ptr)) { +		pr_err("Failed to get trampoline target\n");  		return -EFAULT;  	} -	pr_devel(" %08x %08x ", jmp[0], jmp[1]); - -	/* verify that this is what we expect it to be */ -	if (((jmp[0] & 0xffff0000) != 0x3d800000) || -	    ((jmp[1] & 0xffff0000) != 0x398c0000) || -	    (jmp[2] != 0x7d8903a6) || -	    (jmp[3] != 0x4e800420)) { -		pr_err("Not a trampoline\n"); -		return -EINVAL; -	} - -	tramp = (jmp[1] & 0xffff) | -		((jmp[0] & 0xffff) << 16); -	if (tramp & 0x8000) -		tramp -= 0x10000; - -	pr_devel(" %lx ", tramp); - -	if (tramp != addr) { +	if (ptr != addr) {  		pr_err("Trampoline location %08lx does not match addr\n",  		       tramp);  		return -EINVAL; @@ -291,7 +262,7 @@ __ftrace_make_nop(struct module *mod,  static unsigned long find_ftrace_tramp(unsigned long ip)  {  	int i; -	struct ppc_inst instr; +	ppc_inst_t instr;  	/*  	 * We have the compiler generated long_branch tramps at the end @@ -329,9 +300,9 @@ static int add_ftrace_tramp(unsigned long tramp)  static int setup_mcount_compiler_tramp(unsigned long tramp)  {  	int i; -	struct ppc_inst op; +	ppc_inst_t op;  	unsigned long ptr; -	struct ppc_inst instr; +	ppc_inst_t instr;  	static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];  	/* Is this a known long jump tramp? */ @@ -396,7 +367,7 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)  static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)  {  	unsigned long tramp, ip = rec->ip; -	struct ppc_inst op; +	ppc_inst_t op;  	/* Read where this goes */  	if (copy_inst_from_kernel_nofault(&op, (void *)ip)) { @@ -436,7 +407,7 @@ int ftrace_make_nop(struct module *mod,  		    struct dyn_ftrace *rec, unsigned long addr)  {  	unsigned long ip = rec->ip; -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	/*  	 * If the calling address is more that 24 bits away, @@ -489,7 +460,7 @@ int ftrace_make_nop(struct module *mod,   */  #ifndef CONFIG_MPROFILE_KERNEL  static int -expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1) +expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1)  {  	/*  	 * We expect to see: @@ -507,7 +478,7 @@ expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)  }  #else  static int -expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1) +expected_nop_sequence(void *ip, ppc_inst_t op0, ppc_inst_t op1)  {  	/* look for patched "NOP" on ppc64 with -mprofile-kernel */  	if (!ppc_inst_equal(op0, ppc_inst(PPC_RAW_NOP()))) @@ -519,8 +490,8 @@ expected_nop_sequence(void *ip, struct ppc_inst op0, struct ppc_inst op1)  static int  __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  { -	struct ppc_inst op[2]; -	struct ppc_inst instr; +	ppc_inst_t op[2]; +	ppc_inst_t instr;  	void *ip = (void *)rec->ip;  	unsigned long entry, ptr, tramp;  	struct module *mod = rec->arch.mod; @@ -588,8 +559,10 @@ static int  __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  {  	int err; -	struct ppc_inst op; +	ppc_inst_t op;  	u32 *ip = (u32 *)rec->ip; +	struct module *mod = rec->arch.mod; +	unsigned long tramp;  	/* read where this goes */  	if (copy_inst_from_kernel_nofault(&op, ip)) @@ -602,13 +575,23 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  	}  	/* If we never set up a trampoline to ftrace_caller, then bail */ -	if (!rec->arch.mod->arch.tramp) { +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +	if (!mod->arch.tramp || !mod->arch.tramp_regs) { +#else +	if (!mod->arch.tramp) { +#endif  		pr_err("No ftrace trampoline\n");  		return -EINVAL;  	} +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +	if (rec->flags & FTRACE_FL_REGS) +		tramp = mod->arch.tramp_regs; +	else +#endif +		tramp = mod->arch.tramp;  	/* create the branch to the trampoline */ -	err = create_branch(&op, ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK); +	err = create_branch(&op, ip, tramp, BRANCH_SET_LINK);  	if (err) {  		pr_err("REL24 out of range!\n");  		return -EINVAL; @@ -626,7 +609,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)  { -	struct ppc_inst op; +	ppc_inst_t op;  	void *ip = (void *)rec->ip;  	unsigned long tramp, entry, ptr; @@ -674,7 +657,7 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)  int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)  {  	unsigned long ip = rec->ip; -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	/*  	 * If the calling address is more that 24 bits away, @@ -713,7 +696,7 @@ static int  __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,  					unsigned long addr)  { -	struct ppc_inst op; +	ppc_inst_t op;  	unsigned long ip = rec->ip;  	unsigned long entry, ptr, tramp;  	struct module *mod = rec->arch.mod; @@ -807,7 +790,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,  			unsigned long addr)  {  	unsigned long ip = rec->ip; -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	/*  	 * If the calling address is more that 24 bits away, @@ -847,7 +830,7 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,  int ftrace_update_ftrace_func(ftrace_func_t func)  {  	unsigned long ip = (unsigned long)(&ftrace_call); -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	int ret;  	old = ppc_inst_read((u32 *)&ftrace_call); @@ -932,7 +915,7 @@ int ftrace_enable_ftrace_graph_caller(void)  	unsigned long ip = (unsigned long)(&ftrace_graph_call);  	unsigned long addr = (unsigned long)(&ftrace_graph_caller);  	unsigned long stub = (unsigned long)(&ftrace_graph_stub); -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	old = ftrace_call_replace(ip, stub, 0);  	new = ftrace_call_replace(ip, addr, 0); @@ -945,7 +928,7 @@ int ftrace_disable_ftrace_graph_caller(void)  	unsigned long ip = (unsigned long)(&ftrace_graph_call);  	unsigned long addr = (unsigned long)(&ftrace_graph_caller);  	unsigned long stub = (unsigned long)(&ftrace_graph_stub); -	struct ppc_inst old, new; +	ppc_inst_t old, new;  	old = ftrace_call_replace(ip, addr, 0);  	new = ftrace_call_replace(ip, stub, 0); |