diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-11-25 17:06:19 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-28 08:08:01 -0500 |
commit | 0029ff87529dff01a4b9c5bf380a0caacb5f7418 (patch) | |
tree | 143534dbd52f76ae008b3abc21256c00d4d9fa9b /arch/powerpc/kernel/ftrace.c | |
parent | ec682cef2d2c1a25a198d32a87fe2649da671d1e (diff) |
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: Michael Ellerman <michael@ellerman.id.au>
Reported-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/kernel/ftrace.c')
-rw-r--r-- | arch/powerpc/kernel/ftrace.c | 54 |
1 files changed, 12 insertions, 42 deletions
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index a4640e4f1172..5355244c99ff 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -114,19 +114,9 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, | |||
114 | */ | 114 | */ |
115 | static int test_24bit_addr(unsigned long ip, unsigned long addr) | 115 | static int test_24bit_addr(unsigned long ip, unsigned long addr) |
116 | { | 116 | { |
117 | long diff; | ||
118 | 117 | ||
119 | /* | 118 | /* use the create_branch to verify that this offset can be branched */ |
120 | * Can we get to addr from ip in 24 bits? | 119 | return create_branch((unsigned int *)ip, addr, 0); |
121 | * (26 really, since we mulitply by 4 for 4 byte alignment) | ||
122 | */ | ||
123 | diff = addr - ip; | ||
124 | |||
125 | /* | ||
126 | * Return true if diff is less than 1 << 25 | ||
127 | * and greater than -1 << 26. | ||
128 | */ | ||
129 | return (diff < (1 << 25)) && (diff > (-1 << 26)); | ||
130 | } | 120 | } |
131 | 121 | ||
132 | static int is_bl_op(unsigned int op) | 122 | static int is_bl_op(unsigned int op) |
@@ -134,11 +124,6 @@ static int is_bl_op(unsigned int op) | |||
134 | return (op & 0xfc000003) == 0x48000001; | 124 | return (op & 0xfc000003) == 0x48000001; |
135 | } | 125 | } |
136 | 126 | ||
137 | static int test_offset(unsigned long offset) | ||
138 | { | ||
139 | return (offset + 0x2000000 > 0x3ffffff) || ((offset & 3) != 0); | ||
140 | } | ||
141 | |||
142 | static unsigned long find_bl_target(unsigned long ip, unsigned int op) | 127 | static unsigned long find_bl_target(unsigned long ip, unsigned int op) |
143 | { | 128 | { |
144 | static int offset; | 129 | static int offset; |
@@ -151,12 +136,6 @@ static unsigned long find_bl_target(unsigned long ip, unsigned int op) | |||
151 | return ip + (long)offset; | 136 | return ip + (long)offset; |
152 | } | 137 | } |
153 | 138 | ||
154 | static unsigned int branch_offset(unsigned long offset) | ||
155 | { | ||
156 | /* return "bl ip+offset" */ | ||
157 | return 0x48000001 | (offset & 0x03fffffc); | ||
158 | } | ||
159 | |||
160 | #ifdef CONFIG_PPC64 | 139 | #ifdef CONFIG_PPC64 |
161 | static int | 140 | static int |
162 | __ftrace_make_nop(struct module *mod, | 141 | __ftrace_make_nop(struct module *mod, |
@@ -402,7 +381,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
402 | { | 381 | { |
403 | unsigned int op[2]; | 382 | unsigned int op[2]; |
404 | unsigned long ip = rec->ip; | 383 | unsigned long ip = rec->ip; |
405 | unsigned long offset; | ||
406 | 384 | ||
407 | /* read where this goes */ | 385 | /* read where this goes */ |
408 | if (probe_kernel_read(op, (void *)ip, MCOUNT_INSN_SIZE * 2)) | 386 | 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) | |||
424 | return -EINVAL; | 402 | return -EINVAL; |
425 | } | 403 | } |
426 | 404 | ||
427 | /* now calculate a jump to the ftrace caller trampoline */ | 405 | /* create the branch to the trampoline */ |
428 | offset = rec->arch.mod->arch.tramp - ip; | 406 | op[0] = create_branch((unsigned int *)ip, |
429 | 407 | rec->arch.mod->arch.tramp, BRANCH_SET_LINK); | |
430 | if (test_offset(offset)) { | 408 | if (!op[0]) { |
431 | printk(KERN_ERR "REL24 %li out of range!\n", | 409 | printk(KERN_ERR "REL24 out of range!\n"); |
432 | (long int)offset); | ||
433 | return -EINVAL; | 410 | return -EINVAL; |
434 | } | 411 | } |
435 | 412 | ||
436 | /* Set to "bl addr" */ | ||
437 | op[0] = branch_offset(offset); | ||
438 | /* ld r2,40(r1) */ | 413 | /* ld r2,40(r1) */ |
439 | op[1] = 0xe8410028; | 414 | op[1] = 0xe8410028; |
440 | 415 | ||
@@ -453,7 +428,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
453 | { | 428 | { |
454 | unsigned int op; | 429 | unsigned int op; |
455 | unsigned long ip = rec->ip; | 430 | unsigned long ip = rec->ip; |
456 | unsigned long offset; | ||
457 | 431 | ||
458 | /* read where this goes */ | 432 | /* read where this goes */ |
459 | if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE)) | 433 | if (probe_kernel_read(&op, (void *)ip, MCOUNT_INSN_SIZE)) |
@@ -471,18 +445,14 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
471 | return -EINVAL; | 445 | return -EINVAL; |
472 | } | 446 | } |
473 | 447 | ||
474 | /* now calculate a jump to the ftrace caller trampoline */ | 448 | /* create the branch to the trampoline */ |
475 | offset = rec->arch.mod->arch.tramp - ip; | 449 | op = create_branch((unsigned int *)ip, |
476 | 450 | rec->arch.mod->arch.tramp, BRANCH_SET_LINK); | |
477 | if (test_offset(offset)) { | 451 | if (!op) { |
478 | printk(KERN_ERR "REL24 %li out of range!\n", | 452 | printk(KERN_ERR "REL24 out of range!\n"); |
479 | (long int)offset); | ||
480 | return -EINVAL; | 453 | return -EINVAL; |
481 | } | 454 | } |
482 | 455 | ||
483 | /* Set to "bl addr" */ | ||
484 | op = branch_offset(offset); | ||
485 | |||
486 | DEBUGP("write to %lx\n", rec->ip); | 456 | DEBUGP("write to %lx\n", rec->ip); |
487 | 457 | ||
488 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) | 458 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) |