xref: /linux/arch/sh/kernel/traps.c (revision 8fa5723aa7e053d498336b48448b292fc2e0458b)
1 #include <linux/bug.h>
2 #include <linux/io.h>
3 #include <linux/types.h>
4 #include <linux/kdebug.h>
5 #include <linux/signal.h>
6 #include <linux/sched.h>
7 #include <linux/uaccess.h>
8 #include <asm/system.h>
9 
10 #ifdef CONFIG_BUG
11 static void handle_BUG(struct pt_regs *regs)
12 {
13 	enum bug_trap_type tt;
14 	tt = report_bug(regs->pc, regs);
15 	if (tt == BUG_TRAP_TYPE_WARN) {
16 		regs->pc += instruction_size(regs->pc);
17 		return;
18 	}
19 
20 	die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
21 }
22 
23 int is_valid_bugaddr(unsigned long addr)
24 {
25 	unsigned short opcode;
26 
27 	if (addr < PAGE_OFFSET)
28 		return 0;
29 	if (probe_kernel_address((u16 *)addr, opcode))
30 		return 0;
31 
32 	return opcode == TRAPA_BUG_OPCODE;
33 }
34 #endif
35 
36 /*
37  * Generic trap handler.
38  */
39 BUILD_TRAP_HANDLER(debug)
40 {
41 	TRAP_HANDLER_DECL;
42 
43 	/* Rewind */
44 	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
45 
46 	if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
47 		       SIGTRAP) == NOTIFY_STOP)
48 		return;
49 
50 	force_sig(SIGTRAP, current);
51 }
52 
53 /*
54  * Special handler for BUG() traps.
55  */
56 BUILD_TRAP_HANDLER(bug)
57 {
58 	TRAP_HANDLER_DECL;
59 
60 	/* Rewind */
61 	regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
62 
63 	if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
64 		       SIGTRAP) == NOTIFY_STOP)
65 		return;
66 
67 #ifdef CONFIG_BUG
68 	if (__kernel_text_address(instruction_pointer(regs))) {
69 		opcode_t insn = *(opcode_t *)instruction_pointer(regs);
70 		if (insn == TRAPA_BUG_OPCODE)
71 			handle_BUG(regs);
72 	}
73 #endif
74 
75 	force_sig(SIGTRAP, current);
76 }
77