aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/traps.c
diff options
context:
space:
mode:
authorTony Lu <zlu@tilera.com>2013-08-09 15:08:57 -0400
committerChris Metcalf <cmetcalf@tilera.com>2013-08-30 11:55:53 -0400
commit3fa17c395bb0c358745fbe0c8aa039d6cdac1735 (patch)
treec12f999476581bf31929c4d6a7697efe7062d904 /arch/tile/kernel/traps.c
parenta61fd5e3662d576998d72f80376f23b6ef083d6e (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.c45
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
218static 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
217void __kprobes do_trap(struct pt_regs *regs, int fault_num, 255void __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 */