diff options
| -rw-r--r-- | arch/arm/kernel/ftrace.c | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index c0062ad1e847..6fd7c4a1e532 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
| @@ -121,15 +121,17 @@ static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static int ftrace_modify_code(unsigned long pc, unsigned long old, | 123 | static int ftrace_modify_code(unsigned long pc, unsigned long old, |
| 124 | unsigned long new) | 124 | unsigned long new, bool validate) |
| 125 | { | 125 | { |
| 126 | unsigned long replaced; | 126 | unsigned long replaced; |
| 127 | 127 | ||
| 128 | if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE)) | 128 | if (validate) { |
| 129 | return -EFAULT; | 129 | if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE)) |
| 130 | return -EFAULT; | ||
| 130 | 131 | ||
| 131 | if (replaced != old) | 132 | if (replaced != old) |
| 132 | return -EINVAL; | 133 | return -EINVAL; |
| 134 | } | ||
| 133 | 135 | ||
| 134 | if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE)) | 136 | if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE)) |
| 135 | return -EPERM; | 137 | return -EPERM; |
| @@ -141,23 +143,21 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old, | |||
| 141 | 143 | ||
| 142 | int ftrace_update_ftrace_func(ftrace_func_t func) | 144 | int ftrace_update_ftrace_func(ftrace_func_t func) |
| 143 | { | 145 | { |
| 144 | unsigned long pc, old; | 146 | unsigned long pc; |
| 145 | unsigned long new; | 147 | unsigned long new; |
| 146 | int ret; | 148 | int ret; |
| 147 | 149 | ||
| 148 | pc = (unsigned long)&ftrace_call; | 150 | pc = (unsigned long)&ftrace_call; |
| 149 | memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE); | ||
| 150 | new = ftrace_call_replace(pc, (unsigned long)func); | 151 | new = ftrace_call_replace(pc, (unsigned long)func); |
| 151 | 152 | ||
| 152 | ret = ftrace_modify_code(pc, old, new); | 153 | ret = ftrace_modify_code(pc, 0, new, false); |
| 153 | 154 | ||
| 154 | #ifdef CONFIG_OLD_MCOUNT | 155 | #ifdef CONFIG_OLD_MCOUNT |
| 155 | if (!ret) { | 156 | if (!ret) { |
| 156 | pc = (unsigned long)&ftrace_call_old; | 157 | pc = (unsigned long)&ftrace_call_old; |
| 157 | memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE); | ||
| 158 | new = ftrace_call_replace(pc, (unsigned long)func); | 158 | new = ftrace_call_replace(pc, (unsigned long)func); |
| 159 | 159 | ||
| 160 | ret = ftrace_modify_code(pc, old, new); | 160 | ret = ftrace_modify_code(pc, 0, new, false); |
| 161 | } | 161 | } |
| 162 | #endif | 162 | #endif |
| 163 | 163 | ||
| @@ -172,7 +172,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
| 172 | old = ftrace_nop_replace(rec); | 172 | old = ftrace_nop_replace(rec); |
| 173 | new = ftrace_call_replace(ip, adjust_address(rec, addr)); | 173 | new = ftrace_call_replace(ip, adjust_address(rec, addr)); |
| 174 | 174 | ||
| 175 | return ftrace_modify_code(rec->ip, old, new); | 175 | return ftrace_modify_code(rec->ip, old, new, true); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | int ftrace_make_nop(struct module *mod, | 178 | int ftrace_make_nop(struct module *mod, |
| @@ -185,7 +185,7 @@ int ftrace_make_nop(struct module *mod, | |||
| 185 | 185 | ||
| 186 | old = ftrace_call_replace(ip, adjust_address(rec, addr)); | 186 | old = ftrace_call_replace(ip, adjust_address(rec, addr)); |
| 187 | new = ftrace_nop_replace(rec); | 187 | new = ftrace_nop_replace(rec); |
| 188 | ret = ftrace_modify_code(ip, old, new); | 188 | ret = ftrace_modify_code(ip, old, new, true); |
| 189 | 189 | ||
| 190 | #ifdef CONFIG_OLD_MCOUNT | 190 | #ifdef CONFIG_OLD_MCOUNT |
| 191 | if (ret == -EINVAL && addr == MCOUNT_ADDR) { | 191 | if (ret == -EINVAL && addr == MCOUNT_ADDR) { |
| @@ -193,7 +193,7 @@ int ftrace_make_nop(struct module *mod, | |||
| 193 | 193 | ||
| 194 | old = ftrace_call_replace(ip, adjust_address(rec, addr)); | 194 | old = ftrace_call_replace(ip, adjust_address(rec, addr)); |
| 195 | new = ftrace_nop_replace(rec); | 195 | new = ftrace_nop_replace(rec); |
| 196 | ret = ftrace_modify_code(ip, old, new); | 196 | ret = ftrace_modify_code(ip, old, new, true); |
| 197 | } | 197 | } |
| 198 | #endif | 198 | #endif |
| 199 | 199 | ||
| @@ -254,7 +254,7 @@ static int __ftrace_modify_caller(unsigned long *callsite, | |||
| 254 | unsigned long old = enable ? nop : branch; | 254 | unsigned long old = enable ? nop : branch; |
| 255 | unsigned long new = enable ? branch : nop; | 255 | unsigned long new = enable ? branch : nop; |
| 256 | 256 | ||
| 257 | return ftrace_modify_code(pc, old, new); | 257 | return ftrace_modify_code(pc, old, new, true); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static int ftrace_modify_graph_caller(bool enable) | 260 | static int ftrace_modify_graph_caller(bool enable) |
