diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-02-13 09:31:39 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-02-22 18:48:55 -0500 |
commit | b54dcfe108b1b72c9d891dce1034aa5679c0d7db (patch) | |
tree | 6f0d272d80f7859b308e13b102a31e74ebeebde6 /arch/powerpc/kernel/ftrace.c | |
parent | 60ce8f7260d9ae4ff17548f5a275edfbc200187a (diff) |
powerpc, ftrace: use unsigned int for instruction manipulation
The original port of ftrace to PowerPC kept a lot of the code used
by x86. Some of this code was to handle x86's 5 byte instruction.
This was handled by using character arrays to manipulate the
code.
PowerPC has a consistent 4 byte instruction. Using unsigned ints
makes the code more efficient as well as more readable.
By converting to use unsigned ints to represent instructions,
I was able to remove the side effects that were needed for
manipulating character strings.
i.e. memcpy and memcmp
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/ftrace.c')
-rw-r--r-- | arch/powerpc/kernel/ftrace.c | 45 |
1 files changed, 18 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index dddd99bbbd8d..610c852b92ed 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -31,22 +31,20 @@ | |||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #ifdef CONFIG_DYNAMIC_FTRACE | 33 | #ifdef CONFIG_DYNAMIC_FTRACE |
34 | static unsigned int ftrace_nop = PPC_NOP_INSTR; | ||
35 | |||
36 | static unsigned int ftrace_calc_offset(long ip, long addr) | 34 | static unsigned int ftrace_calc_offset(long ip, long addr) |
37 | { | 35 | { |
38 | return (int)(addr - ip); | 36 | return (int)(addr - ip); |
39 | } | 37 | } |
40 | 38 | ||
41 | static unsigned char *ftrace_nop_replace(void) | 39 | static unsigned int ftrace_nop_replace(void) |
42 | { | 40 | { |
43 | return (char *)&ftrace_nop; | 41 | return PPC_NOP_INSTR; |
44 | } | 42 | } |
45 | 43 | ||
46 | static unsigned char * | 44 | static unsigned int |
47 | ftrace_call_replace(unsigned long ip, unsigned long addr, int link) | 45 | ftrace_call_replace(unsigned long ip, unsigned long addr, int link) |
48 | { | 46 | { |
49 | static unsigned int op; | 47 | unsigned int op; |
50 | 48 | ||
51 | /* | 49 | /* |
52 | * It would be nice to just use create_function_call, but that will | 50 | * It would be nice to just use create_function_call, but that will |
@@ -60,11 +58,7 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link) | |||
60 | op = 0x48000000 | (link ? 1 : 0); | 58 | op = 0x48000000 | (link ? 1 : 0); |
61 | op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc); | 59 | op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc); |
62 | 60 | ||
63 | /* | 61 | return op; |
64 | * No locking needed, this must be called via kstop_machine | ||
65 | * which in essence is like running on a uniprocessor machine. | ||
66 | */ | ||
67 | return (unsigned char *)&op; | ||
68 | } | 62 | } |
69 | 63 | ||
70 | #ifdef CONFIG_PPC64 | 64 | #ifdef CONFIG_PPC64 |
@@ -76,10 +70,9 @@ ftrace_call_replace(unsigned long ip, unsigned long addr, int link) | |||
76 | #endif | 70 | #endif |
77 | 71 | ||
78 | static int | 72 | static int |
79 | ftrace_modify_code(unsigned long ip, unsigned char *old_code, | 73 | ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new) |
80 | unsigned char *new_code) | ||
81 | { | 74 | { |
82 | unsigned char replaced[MCOUNT_INSN_SIZE]; | 75 | unsigned int replaced; |
83 | 76 | ||
84 | /* | 77 | /* |
85 | * Note: Due to modules and __init, code can | 78 | * Note: Due to modules and __init, code can |
@@ -92,15 +85,15 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, | |||
92 | */ | 85 | */ |
93 | 86 | ||
94 | /* read the text we want to modify */ | 87 | /* read the text we want to modify */ |
95 | if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) | 88 | if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE)) |
96 | return -EFAULT; | 89 | return -EFAULT; |
97 | 90 | ||
98 | /* Make sure it is what we expect it to be */ | 91 | /* Make sure it is what we expect it to be */ |
99 | if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) | 92 | if (replaced != old) |
100 | return -EINVAL; | 93 | return -EINVAL; |
101 | 94 | ||
102 | /* replace the text with the new text */ | 95 | /* replace the text with the new text */ |
103 | if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) | 96 | if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE)) |
104 | return -EPERM; | 97 | return -EPERM; |
105 | 98 | ||
106 | flush_icache_range(ip, ip + 8); | 99 | flush_icache_range(ip, ip + 8); |
@@ -336,8 +329,8 @@ __ftrace_make_nop(struct module *mod, | |||
336 | int ftrace_make_nop(struct module *mod, | 329 | int ftrace_make_nop(struct module *mod, |
337 | struct dyn_ftrace *rec, unsigned long addr) | 330 | struct dyn_ftrace *rec, unsigned long addr) |
338 | { | 331 | { |
339 | unsigned char *old, *new; | ||
340 | unsigned long ip = rec->ip; | 332 | unsigned long ip = rec->ip; |
333 | unsigned int old, new; | ||
341 | 334 | ||
342 | /* | 335 | /* |
343 | * If the calling address is more that 24 bits away, | 336 | * If the calling address is more that 24 bits away, |
@@ -475,8 +468,8 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
475 | 468 | ||
476 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 469 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
477 | { | 470 | { |
478 | unsigned char *old, *new; | ||
479 | unsigned long ip = rec->ip; | 471 | unsigned long ip = rec->ip; |
472 | unsigned int old, new; | ||
480 | 473 | ||
481 | /* | 474 | /* |
482 | * If the calling address is more that 24 bits away, | 475 | * If the calling address is more that 24 bits away, |
@@ -511,10 +504,10 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
511 | int ftrace_update_ftrace_func(ftrace_func_t func) | 504 | int ftrace_update_ftrace_func(ftrace_func_t func) |
512 | { | 505 | { |
513 | unsigned long ip = (unsigned long)(&ftrace_call); | 506 | unsigned long ip = (unsigned long)(&ftrace_call); |
514 | unsigned char old[MCOUNT_INSN_SIZE], *new; | 507 | unsigned int old, new; |
515 | int ret; | 508 | int ret; |
516 | 509 | ||
517 | memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); | 510 | old = *(unsigned int *)&ftrace_call; |
518 | new = ftrace_call_replace(ip, (unsigned long)func, 1); | 511 | new = ftrace_call_replace(ip, (unsigned long)func, 1); |
519 | ret = ftrace_modify_code(ip, old, new); | 512 | ret = ftrace_modify_code(ip, old, new); |
520 | 513 | ||
@@ -543,10 +536,9 @@ int ftrace_enable_ftrace_graph_caller(void) | |||
543 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | 536 | unsigned long ip = (unsigned long)(&ftrace_graph_call); |
544 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); | 537 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); |
545 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); | 538 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); |
546 | unsigned char old[MCOUNT_INSN_SIZE], *new; | 539 | unsigned int old, new; |
547 | 540 | ||
548 | new = ftrace_call_replace(ip, stub, 0); | 541 | old = ftrace_call_replace(ip, stub, 0); |
549 | memcpy(old, new, MCOUNT_INSN_SIZE); | ||
550 | new = ftrace_call_replace(ip, addr, 0); | 542 | new = ftrace_call_replace(ip, addr, 0); |
551 | 543 | ||
552 | return ftrace_modify_code(ip, old, new); | 544 | return ftrace_modify_code(ip, old, new); |
@@ -557,10 +549,9 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
557 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | 549 | unsigned long ip = (unsigned long)(&ftrace_graph_call); |
558 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); | 550 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); |
559 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); | 551 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); |
560 | unsigned char old[MCOUNT_INSN_SIZE], *new; | 552 | unsigned int old, new; |
561 | 553 | ||
562 | new = ftrace_call_replace(ip, addr, 0); | 554 | old = ftrace_call_replace(ip, addr, 0); |
563 | memcpy(old, new, MCOUNT_INSN_SIZE); | ||
564 | new = ftrace_call_replace(ip, stub, 0); | 555 | new = ftrace_call_replace(ip, stub, 0); |
565 | 556 | ||
566 | return ftrace_modify_code(ip, old, new); | 557 | return ftrace_modify_code(ip, old, new); |