]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/sh/kernel/traps.c
sched/headers: Prepare for new header dependencies before moving code to <linux/sched...
[mirror_ubuntu-artful-kernel.git] / arch / sh / kernel / traps.c
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/sched/debug.h>
8 #include <linux/uaccess.h>
9 #include <linux/hardirq.h>
10 #include <linux/kernel.h>
11 #include <linux/kexec.h>
12 #include <linux/sched/signal.h>
13
14 #include <linux/extable.h>
15 #include <linux/module.h> /* print_modules */
16 #include <asm/unwinder.h>
17 #include <asm/traps.h>
18
19 static DEFINE_SPINLOCK(die_lock);
20
21 void die(const char *str, struct pt_regs *regs, long err)
22 {
23 static int die_counter;
24
25 oops_enter();
26
27 spin_lock_irq(&die_lock);
28 console_verbose();
29 bust_spinlocks(1);
30
31 printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
32 print_modules();
33 show_regs(regs);
34
35 printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
36 task_pid_nr(current), task_stack_page(current) + 1);
37
38 if (!user_mode(regs) || in_interrupt())
39 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
40 (unsigned long)task_stack_page(current));
41
42 notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
43
44 bust_spinlocks(0);
45 add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
46 spin_unlock_irq(&die_lock);
47 oops_exit();
48
49 if (kexec_should_crash(current))
50 crash_kexec(regs);
51
52 if (in_interrupt())
53 panic("Fatal exception in interrupt");
54
55 if (panic_on_oops)
56 panic("Fatal exception");
57
58 do_exit(SIGSEGV);
59 }
60
61 void die_if_kernel(const char *str, struct pt_regs *regs, long err)
62 {
63 if (!user_mode(regs))
64 die(str, regs, err);
65 }
66
67 /*
68 * try and fix up kernelspace address errors
69 * - userspace errors just cause EFAULT to be returned, resulting in SEGV
70 * - kernel/userspace interfaces cause a jump to an appropriate handler
71 * - other kernel errors are bad
72 */
73 void die_if_no_fixup(const char *str, struct pt_regs *regs, long err)
74 {
75 if (!user_mode(regs)) {
76 const struct exception_table_entry *fixup;
77 fixup = search_exception_tables(regs->pc);
78 if (fixup) {
79 regs->pc = fixup->fixup;
80 return;
81 }
82
83 die(str, regs, err);
84 }
85 }
86
87 #ifdef CONFIG_GENERIC_BUG
88 static void handle_BUG(struct pt_regs *regs)
89 {
90 const struct bug_entry *bug;
91 unsigned long bugaddr = regs->pc;
92 enum bug_trap_type tt;
93
94 if (!is_valid_bugaddr(bugaddr))
95 goto invalid;
96
97 bug = find_bug(bugaddr);
98
99 /* Switch unwinders when unwind_stack() is called */
100 if (bug->flags & BUGFLAG_UNWINDER)
101 unwinder_faulted = 1;
102
103 tt = report_bug(bugaddr, regs);
104 if (tt == BUG_TRAP_TYPE_WARN) {
105 regs->pc += instruction_size(bugaddr);
106 return;
107 }
108
109 invalid:
110 die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
111 }
112
113 int is_valid_bugaddr(unsigned long addr)
114 {
115 insn_size_t opcode;
116
117 if (addr < PAGE_OFFSET)
118 return 0;
119 if (probe_kernel_address((insn_size_t *)addr, opcode))
120 return 0;
121 if (opcode == TRAPA_BUG_OPCODE)
122 return 1;
123
124 return 0;
125 }
126 #endif
127
128 /*
129 * Generic trap handler.
130 */
131 BUILD_TRAP_HANDLER(debug)
132 {
133 TRAP_HANDLER_DECL;
134
135 /* Rewind */
136 regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
137
138 if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff,
139 SIGTRAP) == NOTIFY_STOP)
140 return;
141
142 force_sig(SIGTRAP, current);
143 }
144
145 /*
146 * Special handler for BUG() traps.
147 */
148 BUILD_TRAP_HANDLER(bug)
149 {
150 TRAP_HANDLER_DECL;
151
152 /* Rewind */
153 regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
154
155 if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff,
156 SIGTRAP) == NOTIFY_STOP)
157 return;
158
159 #ifdef CONFIG_GENERIC_BUG
160 if (__kernel_text_address(instruction_pointer(regs))) {
161 insn_size_t insn = *(insn_size_t *)instruction_pointer(regs);
162 if (insn == TRAPA_BUG_OPCODE)
163 handle_BUG(regs);
164 return;
165 }
166 #endif
167
168 force_sig(SIGTRAP, current);
169 }
170
171 BUILD_TRAP_HANDLER(nmi)
172 {
173 unsigned int cpu = smp_processor_id();
174 TRAP_HANDLER_DECL;
175
176 nmi_enter();
177 nmi_count(cpu)++;
178
179 switch (notify_die(DIE_NMI, "NMI", regs, 0, vec & 0xff, SIGINT)) {
180 case NOTIFY_OK:
181 case NOTIFY_STOP:
182 break;
183 case NOTIFY_BAD:
184 die("Fatal Non-Maskable Interrupt", regs, SIGINT);
185 default:
186 printk(KERN_ALERT "Got NMI, but nobody cared. Ignoring...\n");
187 break;
188 }
189
190 nmi_exit();
191 }