Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m68k/kernel/traps_no.c
10817 views
1
/*
2
* linux/arch/m68knommu/kernel/traps.c
3
*
4
* Copyright (C) 1993, 1994 by Hamish Macdonald
5
*
6
* 68040 fixes by Michael Rausch
7
* 68040 fixes by Martin Apel
8
* 68060 fixes by Roman Hodek
9
* 68060 fixes by Jesper Skov
10
*
11
* This file is subject to the terms and conditions of the GNU General Public
12
* License. See the file COPYING in the main directory of this archive
13
* for more details.
14
*/
15
16
/*
17
* Sets up all exception vectors
18
*/
19
#include <linux/sched.h>
20
#include <linux/signal.h>
21
#include <linux/kernel.h>
22
#include <linux/mm.h>
23
#include <linux/module.h>
24
#include <linux/types.h>
25
#include <linux/user.h>
26
#include <linux/string.h>
27
#include <linux/linkage.h>
28
#include <linux/init.h>
29
#include <linux/ptrace.h>
30
#include <linux/kallsyms.h>
31
32
#include <asm/setup.h>
33
#include <asm/fpu.h>
34
#include <asm/system.h>
35
#include <asm/uaccess.h>
36
#include <asm/traps.h>
37
#include <asm/pgtable.h>
38
#include <asm/machdep.h>
39
#include <asm/siginfo.h>
40
41
static char const * const vec_names[] = {
42
"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
43
"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
44
"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
45
"UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
46
"FORMAT ERROR", "UNINITIALIZED INTERRUPT",
47
"UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
48
"UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
49
"UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
50
"UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
51
"SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
52
"LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
53
"SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
54
"TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
55
"TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
56
"TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
57
"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
58
"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
59
"FPCP UNSUPPORTED OPERATION",
60
"MMU CONFIGURATION ERROR"
61
};
62
63
void __init trap_init(void)
64
{
65
}
66
67
void die_if_kernel(char *str, struct pt_regs *fp, int nr)
68
{
69
if (!(fp->sr & PS_S))
70
return;
71
72
console_verbose();
73
printk(KERN_EMERG "%s: %08x\n",str,nr);
74
printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
75
fp->pc, fp->sr, fp, fp->a2);
76
printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
77
fp->d0, fp->d1, fp->d2, fp->d3);
78
printk(KERN_EMERG "d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
79
fp->d4, fp->d5, fp->a0, fp->a1);
80
81
printk(KERN_EMERG "Process %s (pid: %d, stackpage=%08lx)\n",
82
current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
83
show_stack(NULL, (unsigned long *)(fp + 1));
84
add_taint(TAINT_DIE);
85
do_exit(SIGSEGV);
86
}
87
88
asmlinkage void buserr_c(struct frame *fp)
89
{
90
/* Only set esp0 if coming from user mode */
91
if (user_mode(&fp->ptregs))
92
current->thread.esp0 = (unsigned long) fp;
93
94
#if defined(DEBUG)
95
printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
96
#endif
97
98
die_if_kernel("bad frame format",&fp->ptregs,0);
99
#if defined(DEBUG)
100
printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
101
#endif
102
force_sig(SIGSEGV, current);
103
}
104
105
static void print_this_address(unsigned long addr, int i)
106
{
107
#ifdef CONFIG_KALLSYMS
108
printk(KERN_EMERG " [%08lx] ", addr);
109
print_symbol(KERN_CONT "%s\n", addr);
110
#else
111
if (i % 5)
112
printk(KERN_CONT " [%08lx] ", addr);
113
else
114
printk(KERN_EMERG " [%08lx] ", addr);
115
i++;
116
#endif
117
}
118
119
int kstack_depth_to_print = 48;
120
121
static void __show_stack(struct task_struct *task, unsigned long *stack)
122
{
123
unsigned long *endstack, addr;
124
#ifdef CONFIG_FRAME_POINTER
125
unsigned long *last_stack;
126
#endif
127
int i;
128
129
if (!stack)
130
stack = (unsigned long *)task->thread.ksp;
131
132
addr = (unsigned long) stack;
133
endstack = (unsigned long *) PAGE_ALIGN(addr);
134
135
printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
136
for (i = 0; i < kstack_depth_to_print; i++) {
137
if (stack + 1 + i > endstack)
138
break;
139
if (i % 8 == 0)
140
printk(KERN_EMERG " ");
141
printk(KERN_CONT " %08lx", *(stack + i));
142
}
143
printk("\n");
144
i = 0;
145
146
#ifdef CONFIG_FRAME_POINTER
147
printk(KERN_EMERG "Call Trace:\n");
148
149
last_stack = stack - 1;
150
while (stack <= endstack && stack > last_stack) {
151
152
addr = *(stack + 1);
153
print_this_address(addr, i);
154
i++;
155
156
last_stack = stack;
157
stack = (unsigned long *)*stack;
158
}
159
printk("\n");
160
#else
161
printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
162
while (stack <= endstack) {
163
addr = *stack++;
164
/*
165
* If the address is either in the text segment of the kernel,
166
* or in a region which is occupied by a module then it *may*
167
* be the address of a calling routine; if so, print it so that
168
* someone tracing down the cause of the crash will be able to
169
* figure out the call path that was taken.
170
*/
171
if (__kernel_text_address(addr)) {
172
print_this_address(addr, i);
173
i++;
174
}
175
}
176
printk(KERN_CONT "\n");
177
#endif
178
}
179
180
void bad_super_trap(struct frame *fp)
181
{
182
int vector = (fp->ptregs.vector >> 2) & 0xff;
183
184
console_verbose();
185
if (vector < ARRAY_SIZE(vec_names))
186
printk (KERN_WARNING "*** %s *** FORMAT=%X\n",
187
vec_names[vector],
188
fp->ptregs.format);
189
else
190
printk (KERN_WARNING "*** Exception %d *** FORMAT=%X\n",
191
vector,
192
fp->ptregs.format);
193
printk (KERN_WARNING "Current process id is %d\n", current->pid);
194
die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
195
}
196
197
asmlinkage void trap_c(struct frame *fp)
198
{
199
int sig;
200
int vector = (fp->ptregs.vector >> 2) & 0xff;
201
siginfo_t info;
202
203
if (fp->ptregs.sr & PS_S) {
204
if (vector == VEC_TRACE) {
205
/* traced a trapping instruction */
206
} else
207
bad_super_trap(fp);
208
return;
209
}
210
211
/* send the appropriate signal to the user program */
212
switch (vector) {
213
case VEC_ADDRERR:
214
info.si_code = BUS_ADRALN;
215
sig = SIGBUS;
216
break;
217
case VEC_ILLEGAL:
218
case VEC_LINE10:
219
case VEC_LINE11:
220
info.si_code = ILL_ILLOPC;
221
sig = SIGILL;
222
break;
223
case VEC_PRIV:
224
info.si_code = ILL_PRVOPC;
225
sig = SIGILL;
226
break;
227
case VEC_COPROC:
228
info.si_code = ILL_COPROC;
229
sig = SIGILL;
230
break;
231
case VEC_TRAP1: /* gdbserver breakpoint */
232
fp->ptregs.pc -= 2;
233
info.si_code = TRAP_TRACE;
234
sig = SIGTRAP;
235
break;
236
case VEC_TRAP2:
237
case VEC_TRAP3:
238
case VEC_TRAP4:
239
case VEC_TRAP5:
240
case VEC_TRAP6:
241
case VEC_TRAP7:
242
case VEC_TRAP8:
243
case VEC_TRAP9:
244
case VEC_TRAP10:
245
case VEC_TRAP11:
246
case VEC_TRAP12:
247
case VEC_TRAP13:
248
case VEC_TRAP14:
249
info.si_code = ILL_ILLTRP;
250
sig = SIGILL;
251
break;
252
case VEC_FPBRUC:
253
case VEC_FPOE:
254
case VEC_FPNAN:
255
info.si_code = FPE_FLTINV;
256
sig = SIGFPE;
257
break;
258
case VEC_FPIR:
259
info.si_code = FPE_FLTRES;
260
sig = SIGFPE;
261
break;
262
case VEC_FPDIVZ:
263
info.si_code = FPE_FLTDIV;
264
sig = SIGFPE;
265
break;
266
case VEC_FPUNDER:
267
info.si_code = FPE_FLTUND;
268
sig = SIGFPE;
269
break;
270
case VEC_FPOVER:
271
info.si_code = FPE_FLTOVF;
272
sig = SIGFPE;
273
break;
274
case VEC_ZERODIV:
275
info.si_code = FPE_INTDIV;
276
sig = SIGFPE;
277
break;
278
case VEC_CHK:
279
case VEC_TRAP:
280
info.si_code = FPE_INTOVF;
281
sig = SIGFPE;
282
break;
283
case VEC_TRACE: /* ptrace single step */
284
info.si_code = TRAP_TRACE;
285
sig = SIGTRAP;
286
break;
287
case VEC_TRAP15: /* breakpoint */
288
info.si_code = TRAP_BRKPT;
289
sig = SIGTRAP;
290
break;
291
default:
292
info.si_code = ILL_ILLOPC;
293
sig = SIGILL;
294
break;
295
}
296
info.si_signo = sig;
297
info.si_errno = 0;
298
switch (fp->ptregs.format) {
299
default:
300
info.si_addr = (void *) fp->ptregs.pc;
301
break;
302
case 2:
303
info.si_addr = (void *) fp->un.fmt2.iaddr;
304
break;
305
case 7:
306
info.si_addr = (void *) fp->un.fmt7.effaddr;
307
break;
308
case 9:
309
info.si_addr = (void *) fp->un.fmt9.iaddr;
310
break;
311
case 10:
312
info.si_addr = (void *) fp->un.fmta.daddr;
313
break;
314
case 11:
315
info.si_addr = (void *) fp->un.fmtb.daddr;
316
break;
317
}
318
force_sig_info (sig, &info, current);
319
}
320
321
asmlinkage void set_esp0(unsigned long ssp)
322
{
323
current->thread.esp0 = ssp;
324
}
325
326
/*
327
* The architecture-independent backtrace generator
328
*/
329
void dump_stack(void)
330
{
331
/*
332
* We need frame pointers for this little trick, which works as follows:
333
*
334
* +------------+ 0x00
335
* | Next SP | -> 0x0c
336
* +------------+ 0x04
337
* | Caller |
338
* +------------+ 0x08
339
* | Local vars | -> our stack var
340
* +------------+ 0x0c
341
* | Next SP | -> 0x18, that is what we pass to show_stack()
342
* +------------+ 0x10
343
* | Caller |
344
* +------------+ 0x14
345
* | Local vars |
346
* +------------+ 0x18
347
* | ... |
348
* +------------+
349
*/
350
351
unsigned long *stack;
352
353
stack = (unsigned long *)&stack;
354
stack++;
355
__show_stack(current, stack);
356
}
357
EXPORT_SYMBOL(dump_stack);
358
359
void show_stack(struct task_struct *task, unsigned long *stack)
360
{
361
if (!stack && !task)
362
dump_stack();
363
else
364
__show_stack(task, stack);
365
}
366
367