Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0029ff87 authored by Steven Rostedt's avatar Steven Rostedt Committed by Ingo Molnar
Browse files

powerpc: ftrace, use create_branch



Impact: clean up

Paul Mackerras pointed out that the code to determine if the branch
can reach the destination is incorrect. Michael Ellerman suggested
to pull out the code from create_branch and use that.

Simply using create_branch is probably the best.

Reported-by: default avatarMichael Ellerman <michael@ellerman.id.au>
Reported-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent ec682cef
Loading
Loading
Loading
Loading
+12 −42
Original line number Original line Diff line number Diff line
@@ -114,19 +114,9 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
 */
 */
static int test_24bit_addr(unsigned long ip, unsigned long addr)
static int test_24bit_addr(unsigned long ip, unsigned long addr)
{
{
	long diff;


	/*
	/* use the create_branch to verify that this offset can be branched */
	 * Can we get to addr from ip in 24 bits?
	return create_branch((unsigned int *)ip, addr, 0);
	 *  (26 really, since we mulitply by 4 for 4 byte alignment)
	 */
	diff = addr - ip;

	/*
	 * Return true if diff is less than 1 << 25
	 *  and greater than -1 << 26.
	 */
	return (diff < (1 << 25)) && (diff > (-1 << 26));
}
}


static int is_bl_op(unsigned int op)
static int is_bl_op(unsigned int op)
@@ -134,11 +124,6 @@ static int is_bl_op(unsigned int op)
	return (op & 0xfc000003) == 0x48000001;
	return (op & 0xfc000003) == 0x48000001;
}
}


static int test_offset(unsigned long offset)
{
	return (offset + 0x2000000 > 0x3ffffff) || ((offset & 3) != 0);
}

static unsigned long find_bl_target(unsigned long ip, unsigned int op)
static unsigned long find_bl_target(unsigned long ip, unsigned int op)
{
{
	static int offset;
	static int offset;
@@ -151,12 +136,6 @@ static unsigned long find_bl_target(unsigned long ip, unsigned int op)
	return ip + (long)offset;
	return ip + (long)offset;
}
}


static unsigned int branch_offset(unsigned long offset)
{
	/* return "bl ip+offset" */
	return 0x48000001 | (offset & 0x03fffffc);
}

#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
static int
static int
__ftrace_make_nop(struct module *mod,
__ftrace_make_nop(struct module *mod,
@@ -402,7 +381,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
{
	unsigned int op[2];
	unsigned int op[2];
	unsigned long ip = rec->ip;
	unsigned long ip = rec->ip;
	unsigned long offset;


	/* read where this goes */
	/* read where this goes */
	if (probe_kernel_read(op, (void *)ip, MCOUNT_INSN_SIZE * 2))
	if (probe_kernel_read(op, (void *)ip, MCOUNT_INSN_SIZE * 2))
@@ -424,17 +402,14 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* now calculate a jump to the ftrace caller trampoline */
	/* create the branch to the trampoline */
	offset = rec->arch.mod->arch.tramp - ip;
	op[0] = create_branch((unsigned int *)ip,

			      rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
	if (test_offset(offset)) {
	if (!op[0]) {
		printk(KERN_ERR "REL24 %li out of range!\n",
		printk(KERN_ERR "REL24 out of range!\n");
		       (long int)offset);
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* Set to "bl addr" */
	op[0] = branch_offset(offset);
	/* ld r2,40(r1) */
	/* ld r2,40(r1) */
	op[1] = 0xe8410028;
	op[1] = 0xe8410028;


@@ -453,7 +428,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
{
	unsigned int op;
	unsigned int op;
	unsigned long ip = rec->ip;
	unsigned long ip = rec->ip;
	unsigned long offset;


	/* read where this goes */
	/* read where this goes */
	if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
	if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE))
@@ -471,18 +445,14 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* now calculate a jump to the ftrace caller trampoline */
	/* create the branch to the trampoline */
	offset = rec->arch.mod->arch.tramp - ip;
	op = create_branch((unsigned int *)ip,

			   rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
	if (test_offset(offset)) {
	if (!op) {
		printk(KERN_ERR "REL24 %li out of range!\n",
		printk(KERN_ERR "REL24 out of range!\n");
		       (long int)offset);
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* Set to "bl addr" */
	op = branch_offset(offset);

	DEBUGP("write to %lx\n", rec->ip);
	DEBUGP("write to %lx\n", rec->ip);


	if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
	if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))