diff options
author | Tony Lu <zlu@tilera.com> | 2013-08-09 15:08:57 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2013-08-30 11:55:53 -0400 |
commit | 3fa17c395bb0c358745fbe0c8aa039d6cdac1735 (patch) | |
tree | c12f999476581bf31929c4d6a7697efe7062d904 /arch/tile/kernel/traps.c | |
parent | a61fd5e3662d576998d72f80376f23b6ef083d6e (diff) |
tile: support kprobes on tilegx
This change includes support for Kprobes, Jprobes and Return Probes.
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Tony Lu <zlu@tilera.com>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/kernel/traps.c')
-rw-r--r-- | arch/tile/kernel/traps.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index a1bbc5de4d00..cfff6f958d58 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/kprobes.h> | 17 | #include <linux/kprobes.h> |
18 | #include <linux/kdebug.h> | ||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
20 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
@@ -214,6 +215,43 @@ static const char *const int_name[] = { | |||
214 | #endif | 215 | #endif |
215 | }; | 216 | }; |
216 | 217 | ||
218 | static int do_bpt(struct pt_regs *regs) | ||
219 | { | ||
220 | unsigned long bundle, bcode, bpt; | ||
221 | |||
222 | bundle = *(unsigned long *)instruction_pointer(regs); | ||
223 | |||
224 | /* | ||
225 | * bpt shoule be { bpt; nop }, which is 0x286a44ae51485000ULL. | ||
226 | * we encode the unused least significant bits for other purpose. | ||
227 | */ | ||
228 | bpt = bundle & ~((1ULL << 12) - 1); | ||
229 | if (bpt != TILE_BPT_BUNDLE) | ||
230 | return 0; | ||
231 | |||
232 | bcode = bundle & ((1ULL << 12) - 1); | ||
233 | /* | ||
234 | * notify the kprobe handlers, if instruction is likely to | ||
235 | * pertain to them. | ||
236 | */ | ||
237 | switch (bcode) { | ||
238 | /* breakpoint_insn */ | ||
239 | case 0: | ||
240 | notify_die(DIE_BREAK, "debug", regs, bundle, | ||
241 | INT_ILL, SIGTRAP); | ||
242 | break; | ||
243 | /* breakpoint2_insn */ | ||
244 | case DIE_SSTEPBP: | ||
245 | notify_die(DIE_SSTEPBP, "single_step", regs, bundle, | ||
246 | INT_ILL, SIGTRAP); | ||
247 | break; | ||
248 | default: | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | return 1; | ||
253 | } | ||
254 | |||
217 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, | 255 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, |
218 | unsigned long reason) | 256 | unsigned long reason) |
219 | { | 257 | { |
@@ -221,6 +259,11 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
221 | int signo, code; | 259 | int signo, code; |
222 | unsigned long address = 0; | 260 | unsigned long address = 0; |
223 | bundle_bits instr; | 261 | bundle_bits instr; |
262 | int is_kernel = !user_mode(regs); | ||
263 | |||
264 | /* Handle breakpoints, etc. */ | ||
265 | if (is_kernel && fault_num == INT_ILL && do_bpt(regs)) | ||
266 | return; | ||
224 | 267 | ||
225 | /* Re-enable interrupts, if they were previously enabled. */ | 268 | /* Re-enable interrupts, if they were previously enabled. */ |
226 | if (!(regs->flags & PT_FLAGS_DISABLE_IRQ)) | 269 | if (!(regs->flags & PT_FLAGS_DISABLE_IRQ)) |
@@ -230,7 +273,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
230 | * If it hits in kernel mode and we can't fix it up, just exit the | 273 | * If it hits in kernel mode and we can't fix it up, just exit the |
231 | * current process and hope for the best. | 274 | * current process and hope for the best. |
232 | */ | 275 | */ |
233 | if (!user_mode(regs)) { | 276 | if (is_kernel) { |
234 | const char *name; | 277 | const char *name; |
235 | char buf[100]; | 278 | char buf[100]; |
236 | if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */ | 279 | if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */ |