1 /*
2 * linux/arch/m68k/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 * 68040 fixes and writeback by Richard Zidlicky
9 * 68060 fixes by Roman Hodek
10 * 68060 fixes by Jesper Skov
11 *
12 * This file is subject to the terms and conditions of the GNU General Public
13 * License. See the file COPYING in the main directory of this archive
14 * for more details.
15 */
16
17 /*
18 * Sets up all exception vectors
19 */
20
21 #include <linux/config.h>
22 #include <linux/sched.h>
23 #include <linux/signal.h>
24 #include <linux/kernel.h>
25 #include <linux/mm.h>
26 #include <linux/module.h>
27 #include <linux/a.out.h>
28 #include <linux/user.h>
29 #include <linux/string.h>
30 #include <linux/linkage.h>
31 #include <linux/init.h>
32
33 #include <asm/setup.h>
34 #include <asm/fpu.h>
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
37 #include <asm/traps.h>
38 #include <asm/pgalloc.h>
39 #include <asm/machdep.h>
40 #include <asm/siginfo.h>
41
42 /* assembler routines */
43 asmlinkage void system_call(void);
44 asmlinkage void buserr(void);
45 asmlinkage void trap(void);
46 asmlinkage void inthandler(void);
47 asmlinkage void nmihandler(void);
48 #ifdef CONFIG_M68KFPU_EMU
49 asmlinkage void fpu_emu(void);
50 #endif
51
52 e_vector vectors[256] = {
53 0, 0, buserr, trap, trap, trap, trap, trap,
54 trap, trap, trap, trap, trap, trap, trap, trap,
55 trap, trap, trap, trap, trap, trap, trap, trap,
56 inthandler, inthandler, inthandler, inthandler,
57 inthandler, inthandler, inthandler, inthandler,
58 /* TRAP #0-15 */
59 system_call, trap, trap, trap, trap, trap, trap, trap,
60 trap, trap, trap, trap, trap, trap, trap, trap,
61 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 };
63
64 /* nmi handler for the Amiga */
65 asm(".text\n"
66 __ALIGN_STR "\n"
67 SYMBOL_NAME_STR(nmihandler) ": rte");
68
69 /*
70 * this must be called very early as the kernel might
71 * use some instruction that are emulated on the 060
72 */
base_trap_init(void)73 void __init base_trap_init(void)
74 {
75 if(MACH_IS_SUN3X) {
76 extern e_vector *sun3x_prom_vbr;
77
78 __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
79 }
80
81 /* setup the exception vector table */
82 __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
83
84 if (CPU_IS_060) {
85 /* set up ISP entry points */
86 asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
87
88 vectors[VEC_UNIMPII] = unimp_vec;
89 }
90 }
91
trap_init(void)92 void __init trap_init (void)
93 {
94 int i;
95
96 for (i = 48; i < 64; i++)
97 if (!vectors[i])
98 vectors[i] = trap;
99
100 for (i = 64; i < 256; i++)
101 vectors[i] = inthandler;
102
103 #ifdef CONFIG_M68KFPU_EMU
104 if (FPU_IS_EMU)
105 vectors[VEC_LINE11] = fpu_emu;
106 #endif
107
108 if (CPU_IS_040 && !FPU_IS_EMU) {
109 /* set up FPSP entry points */
110 asmlinkage void dz_vec(void) asm ("dz");
111 asmlinkage void inex_vec(void) asm ("inex");
112 asmlinkage void ovfl_vec(void) asm ("ovfl");
113 asmlinkage void unfl_vec(void) asm ("unfl");
114 asmlinkage void snan_vec(void) asm ("snan");
115 asmlinkage void operr_vec(void) asm ("operr");
116 asmlinkage void bsun_vec(void) asm ("bsun");
117 asmlinkage void fline_vec(void) asm ("fline");
118 asmlinkage void unsupp_vec(void) asm ("unsupp");
119
120 vectors[VEC_FPDIVZ] = dz_vec;
121 vectors[VEC_FPIR] = inex_vec;
122 vectors[VEC_FPOVER] = ovfl_vec;
123 vectors[VEC_FPUNDER] = unfl_vec;
124 vectors[VEC_FPNAN] = snan_vec;
125 vectors[VEC_FPOE] = operr_vec;
126 vectors[VEC_FPBRUC] = bsun_vec;
127 vectors[VEC_LINE11] = fline_vec;
128 vectors[VEC_FPUNSUP] = unsupp_vec;
129 }
130
131 if (CPU_IS_060 && !FPU_IS_EMU) {
132 /* set up IFPSP entry points */
133 asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
134 asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
135 asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
136 asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
137 asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
138 asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
139 asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
140 asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
141 asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
142
143 vectors[VEC_FPNAN] = snan_vec;
144 vectors[VEC_FPOE] = operr_vec;
145 vectors[VEC_FPOVER] = ovfl_vec;
146 vectors[VEC_FPUNDER] = unfl_vec;
147 vectors[VEC_FPDIVZ] = dz_vec;
148 vectors[VEC_FPIR] = inex_vec;
149 vectors[VEC_LINE11] = fline_vec;
150 vectors[VEC_FPUNSUP] = unsupp_vec;
151 vectors[VEC_UNIMPEA] = effadd_vec;
152 }
153
154 /* if running on an amiga, make the NMI interrupt do nothing */
155 if (MACH_IS_AMIGA) {
156 vectors[VEC_INT7] = nmihandler;
157 }
158 }
159
160
161 static char *vec_names[] = {
162 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
163 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
164 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
165 "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
166 "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
167 "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
168 "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
169 "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
170 "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
171 "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
172 "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
173 "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
174 "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
175 "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
176 "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
177 "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
178 "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
179 "FPCP UNSUPPORTED OPERATION",
180 "MMU CONFIGURATION ERROR"
181 };
182
183 #ifndef CONFIG_SUN3
184 static char *space_names[] = {
185 "Space 0", "User Data", "User Program", "Space 3",
186 "Space 4", "Super Data", "Super Program", "CPU"
187 };
188 #else
189 static char *space_names[] = {
190 "Space 0", "User Data", "User Program", "Control",
191 "Space 4", "Super Data", "Super Program", "CPU"
192 };
193 #endif
194
195 void die_if_kernel(char *,struct pt_regs *,int);
196 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
197 unsigned long error_code);
198 int send_fault_sig(struct pt_regs *regs);
199
200 asmlinkage void trap_c(struct frame *fp);
201
202 #if defined (CONFIG_M68060)
access_error060(struct frame * fp)203 static inline void access_error060 (struct frame *fp)
204 {
205 unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
206
207 #ifdef DEBUG
208 printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
209 #endif
210
211 if (fslw & MMU060_BPE) {
212 /* branch prediction error -> clear branch cache */
213 __asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
214 "orl #0x00400000,%/d0\n\t"
215 "movec %/d0,%/cacr"
216 : : : "d0" );
217 /* return if there's no other error */
218 if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
219 return;
220 }
221
222 if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
223 unsigned long errorcode;
224 unsigned long addr = fp->un.fmt4.effaddr;
225
226 if (fslw & MMU060_MA)
227 addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
228
229 errorcode = 1;
230 if (fslw & MMU060_DESC_ERR) {
231 __flush_tlb040_one(addr);
232 errorcode = 0;
233 }
234 if (fslw & MMU060_W)
235 errorcode |= 2;
236 #ifdef DEBUG
237 printk("errorcode = %d\n", errorcode );
238 #endif
239 do_page_fault(&fp->ptregs, addr, errorcode);
240 } else if (fslw & (MMU060_SEE)){
241 /* Software Emulation Error.
242 * fault during mem_read/mem_write in ifpsp060/os.S
243 */
244 send_fault_sig(&fp->ptregs);
245 } else {
246 printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
247 printk( "68060 access error, fslw=%lx\n", fslw );
248 trap_c( fp );
249 }
250 }
251 #endif /* CONFIG_M68060 */
252
253 #if defined (CONFIG_M68040)
probe040(int iswrite,unsigned long addr,int wbs)254 static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
255 {
256 unsigned long mmusr;
257 mm_segment_t old_fs = get_fs();
258
259 set_fs(MAKE_MM_SEG(wbs));
260
261 if (iswrite)
262 asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
263 else
264 asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
265
266 asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
267
268 set_fs(old_fs);
269
270 return mmusr;
271 }
272
do_040writeback1(unsigned short wbs,unsigned long wba,unsigned long wbd)273 static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
274 unsigned long wbd)
275 {
276 int res = 0;
277 mm_segment_t old_fs = get_fs();
278
279 /* set_fs can not be moved, otherwise put_user() may oops */
280 set_fs(MAKE_MM_SEG(wbs));
281
282 switch (wbs & WBSIZ_040) {
283 case BA_SIZE_BYTE:
284 res = put_user(wbd & 0xff, (char *)wba);
285 break;
286 case BA_SIZE_WORD:
287 res = put_user(wbd & 0xffff, (short *)wba);
288 break;
289 case BA_SIZE_LONG:
290 res = put_user(wbd, (int *)wba);
291 break;
292 }
293
294 /* set_fs can not be moved, otherwise put_user() may oops */
295 set_fs(old_fs);
296
297
298 #ifdef DEBUG
299 printk("do_040writeback1, res=%d\n",res);
300 #endif
301
302 return res;
303 }
304
305 /* after an exception in a writeback the stack frame corresponding
306 * to that exception is discarded, set a few bits in the old frame
307 * to simulate what it should look like
308 */
fix_xframe040(struct frame * fp,unsigned long wba,unsigned short wbs)309 static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
310 {
311 fp->un.fmt7.faddr = wba;
312 fp->un.fmt7.ssw = wbs & 0xff;
313 if (wba != current->thread.faddr)
314 fp->un.fmt7.ssw |= MA_040;
315 }
316
do_040writebacks(struct frame * fp)317 static inline void do_040writebacks(struct frame *fp)
318 {
319 int res = 0;
320 #if 0
321 if (fp->un.fmt7.wb1s & WBV_040)
322 printk("access_error040: cannot handle 1st writeback. oops.\n");
323 #endif
324
325 if ((fp->un.fmt7.wb2s & WBV_040) &&
326 !(fp->un.fmt7.wb2s & WBTT_040)) {
327 res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
328 fp->un.fmt7.wb2d);
329 if (res)
330 fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
331 else
332 fp->un.fmt7.wb2s = 0;
333 }
334
335 /* do the 2nd wb only if the first one was successful (except for a kernel wb) */
336 if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
337 res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
338 fp->un.fmt7.wb3d);
339 if (res)
340 {
341 fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
342
343 fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
344 fp->un.fmt7.wb3s &= (~WBV_040);
345 fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
346 fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
347 }
348 else
349 fp->un.fmt7.wb3s = 0;
350 }
351
352 if (res)
353 send_fault_sig(&fp->ptregs);
354 }
355
356 /*
357 * called from sigreturn(), must ensure userspace code didn't
358 * manipulate exception frame to circumvent protection, then complete
359 * pending writebacks
360 * we just clear TM2 to turn it into an userspace access
361 */
berr_040cleanup(struct frame * fp)362 asmlinkage void berr_040cleanup(struct frame *fp)
363 {
364 fp->un.fmt7.wb2s &= ~4;
365 fp->un.fmt7.wb3s &= ~4;
366
367 do_040writebacks(fp);
368 }
369
access_error040(struct frame * fp)370 static inline void access_error040(struct frame *fp)
371 {
372 unsigned short ssw = fp->un.fmt7.ssw;
373 unsigned long mmusr;
374
375 #ifdef DEBUG
376 printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
377 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
378 fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
379 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
380 fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
381 fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
382 #endif
383
384 if (ssw & ATC_040) {
385 unsigned long addr = fp->un.fmt7.faddr;
386 unsigned long errorcode;
387
388 /*
389 * The MMU status has to be determined AFTER the address
390 * has been corrected if there was a misaligned access (MA).
391 */
392 if (ssw & MA_040)
393 addr = (addr + 7) & -8;
394
395 /* MMU error, get the MMUSR info for this access */
396 mmusr = probe040(!(ssw & RW_040), addr, ssw);
397 #ifdef DEBUG
398 printk("mmusr = %lx\n", mmusr);
399 #endif
400 errorcode = 1;
401 if (!(mmusr & MMU_R_040)) {
402 /* clear the invalid atc entry */
403 __flush_tlb040_one(addr);
404 errorcode = 0;
405 }
406
407 /* despite what documentation seems to say, RMW
408 * accesses have always both the LK and RW bits set */
409 if (!(ssw & RW_040) || (ssw & LK_040))
410 errorcode |= 2;
411
412 if (do_page_fault(&fp->ptregs, addr, errorcode)) {
413 #ifdef DEBUG
414 printk("do_page_fault() !=0 \n");
415 #endif
416 if (user_mode(&fp->ptregs)){
417 /* delay writebacks after signal delivery */
418 #ifdef DEBUG
419 printk(".. was usermode - return\n");
420 #endif
421 return;
422 }
423 /* disable writeback into user space from kernel
424 * (if do_page_fault didn't fix the mapping,
425 * the writeback won't do good)
426 */
427 #ifdef DEBUG
428 printk(".. disabling wb2\n");
429 #endif
430 if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
431 fp->un.fmt7.wb2s &= ~WBV_040;
432 }
433 } else {
434 printk("68040 access error, ssw=%x\n", ssw);
435 trap_c(fp);
436 }
437
438 do_040writebacks(fp);
439 }
440 #endif /* CONFIG_M68040 */
441
442 #if defined(CONFIG_SUN3)
443 #include <asm/sun3mmu.h>
444
445 extern int mmu_emu_handle_fault (unsigned long, int, int);
446
447 /* sun3 version of bus_error030 */
448
bus_error030(struct frame * fp)449 static inline void bus_error030(struct frame *fp)
450 {
451 unsigned char buserr_type = sun3_get_buserr ();
452 unsigned long addr, errorcode;
453 unsigned short ssw = fp->un.fmtb.ssw;
454
455 #if DEBUG
456 if (ssw & (FC | FB))
457 printk ("Instruction fault at %#010lx\n",
458 ssw & FC ?
459 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
460 :
461 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
462 if (ssw & DF)
463 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
464 ssw & RW ? "read" : "write",
465 fp->un.fmtb.daddr,
466 space_names[ssw & DFC], fp->ptregs.pc);
467 #endif
468
469 /*
470 * Check if this page should be demand-mapped. This needs to go before
471 * the testing for a bad kernel-space access (demand-mapping applies
472 * to kernel accesses too).
473 */
474
475 if ((ssw & DF)
476 && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
477 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
478 return;
479 }
480
481 /* Check for kernel-space pagefault (BAD). */
482 if (fp->ptregs.sr & PS_S) {
483 /* kernel fault must be a data fault to user space */
484 if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
485 // try checking the kernel mappings before surrender
486 if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
487 return;
488 /* instruction fault or kernel data fault! */
489 if (ssw & (FC | FB))
490 printk ("Instruction fault at %#010lx\n",
491 fp->ptregs.pc);
492 if (ssw & DF) {
493 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
494 ssw & RW ? "read" : "write",
495 fp->un.fmtb.daddr,
496 space_names[ssw & DFC], fp->ptregs.pc);
497 }
498 printk ("BAD KERNEL BUSERR\n");
499
500 die_if_kernel("Oops", &fp->ptregs,0);
501 force_sig(SIGKILL, current);
502 return;
503 }
504 } else {
505 /* user fault */
506 if (!(ssw & (FC | FB)) && !(ssw & DF))
507 /* not an instruction fault or data fault! BAD */
508 panic ("USER BUSERR w/o instruction or data fault");
509 }
510
511
512 /* First handle the data fault, if any. */
513 if (ssw & DF) {
514 addr = fp->un.fmtb.daddr;
515
516 // errorcode bit 0: 0 -> no page 1 -> protection fault
517 // errorcode bit 1: 0 -> read fault 1 -> write fault
518
519 // (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
520 // (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
521
522 if (buserr_type & SUN3_BUSERR_PROTERR)
523 errorcode = 0x01;
524 else if (buserr_type & SUN3_BUSERR_INVALID)
525 errorcode = 0x00;
526 else {
527 #ifdef DEBUG
528 printk ("*** unexpected busfault type=%#04x\n", buserr_type);
529 printk ("invalid %s access at %#lx from pc %#lx\n",
530 !(ssw & RW) ? "write" : "read", addr,
531 fp->ptregs.pc);
532 #endif
533 die_if_kernel ("Oops", &fp->ptregs, buserr_type);
534 force_sig (SIGBUS, current);
535 return;
536 }
537
538 //todo: wtf is RM bit? --m
539 if (!(ssw & RW) || ssw & RM)
540 errorcode |= 0x02;
541
542 /* Handle page fault. */
543 do_page_fault (&fp->ptregs, addr, errorcode);
544
545 /* Retry the data fault now. */
546 return;
547 }
548
549 /* Now handle the instruction fault. */
550
551 /* Get the fault address. */
552 if (fp->ptregs.format == 0xA)
553 addr = fp->ptregs.pc + 4;
554 else
555 addr = fp->un.fmtb.baddr;
556 if (ssw & FC)
557 addr -= 2;
558
559 if (buserr_type & SUN3_BUSERR_INVALID) {
560 if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
561 do_page_fault (&fp->ptregs, addr, 0);
562 } else {
563 #ifdef DEBUG
564 printk ("protection fault on insn access (segv).\n");
565 #endif
566 force_sig (SIGSEGV, current);
567 }
568 }
569 #else
570 #if defined(CPU_M68020_OR_M68030)
bus_error030(struct frame * fp)571 static inline void bus_error030 (struct frame *fp)
572 {
573 volatile unsigned short temp;
574 unsigned short mmusr;
575 unsigned long addr, errorcode;
576 unsigned short ssw = fp->un.fmtb.ssw;
577 #if DEBUG
578 unsigned long desc;
579
580 printk ("pid = %x ", current->pid);
581 printk ("SSW=%#06x ", ssw);
582
583 if (ssw & (FC | FB))
584 printk ("Instruction fault at %#010lx\n",
585 ssw & FC ?
586 fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
587 :
588 fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
589 if (ssw & DF)
590 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
591 ssw & RW ? "read" : "write",
592 fp->un.fmtb.daddr,
593 space_names[ssw & DFC], fp->ptregs.pc);
594 #endif
595
596 /* ++andreas: If a data fault and an instruction fault happen
597 at the same time map in both pages. */
598
599 /* First handle the data fault, if any. */
600 if (ssw & DF) {
601 addr = fp->un.fmtb.daddr;
602
603 #if DEBUG
604 asm volatile ("ptestr %3,%2@,#7,%0\n\t"
605 "pmove %%psr,%1@"
606 : "=a&" (desc)
607 : "a" (&temp), "a" (addr), "d" (ssw));
608 #else
609 asm volatile ("ptestr %2,%1@,#7\n\t"
610 "pmove %%psr,%0@"
611 : : "a" (&temp), "a" (addr), "d" (ssw));
612 #endif
613 mmusr = temp;
614
615 #if DEBUG
616 printk("mmusr is %#x for addr %#lx in task %p\n",
617 mmusr, addr, current);
618 printk("descriptor address is %#lx, contents %#lx\n",
619 __va(desc), *(unsigned long *)__va(desc));
620 #endif
621
622 errorcode = (mmusr & MMU_I) ? 0 : 1;
623 if (!(ssw & RW) || (ssw & RM))
624 errorcode |= 2;
625
626 if (mmusr & (MMU_I | MMU_WP)) {
627 if (ssw & 4) {
628 printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
629 ssw & RW ? "read" : "write",
630 fp->un.fmtb.daddr,
631 space_names[ssw & DFC], fp->ptregs.pc);
632 goto buserr;
633 }
634 /* Don't try to do anything further if an exception was
635 handled. */
636 if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
637 return;
638 } else if (!(mmusr & MMU_I)) {
639 /* propably a 020 cas fault */
640 if (!(ssw & RM))
641 printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
642 } else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
643 printk("invalid %s access at %#lx from pc %#lx\n",
644 !(ssw & RW) ? "write" : "read", addr,
645 fp->ptregs.pc);
646 die_if_kernel("Oops",&fp->ptregs,mmusr);
647 force_sig(SIGSEGV, current);
648 return;
649 } else {
650 #if 0
651 static volatile long tlong;
652 #endif
653
654 printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
655 !(ssw & RW) ? "write" : "read", addr,
656 fp->ptregs.pc, ssw);
657 asm volatile ("ptestr #1,%1@,#0\n\t"
658 "pmove %%psr,%0@"
659 : /* no outputs */
660 : "a" (&temp), "a" (addr));
661 mmusr = temp;
662
663 printk ("level 0 mmusr is %#x\n", mmusr);
664 #if 0
665 asm volatile ("pmove %%tt0,%0@"
666 : /* no outputs */
667 : "a" (&tlong));
668 printk("tt0 is %#lx, ", tlong);
669 asm volatile ("pmove %%tt1,%0@"
670 : /* no outputs */
671 : "a" (&tlong));
672 printk("tt1 is %#lx\n", tlong);
673 #endif
674 #if DEBUG
675 printk("Unknown SIGSEGV - 1\n");
676 #endif
677 die_if_kernel("Oops",&fp->ptregs,mmusr);
678 force_sig(SIGSEGV, current);
679 return;
680 }
681
682 /* setup an ATC entry for the access about to be retried */
683 if (!(ssw & RW) || (ssw & RM))
684 asm volatile ("ploadw %1,%0@" : /* no outputs */
685 : "a" (addr), "d" (ssw));
686 else
687 asm volatile ("ploadr %1,%0@" : /* no outputs */
688 : "a" (addr), "d" (ssw));
689 }
690
691 /* Now handle the instruction fault. */
692
693 if (!(ssw & (FC|FB)))
694 return;
695
696 if (fp->ptregs.sr & PS_S) {
697 printk("Instruction fault at %#010lx\n",
698 fp->ptregs.pc);
699 buserr:
700 printk ("BAD KERNEL BUSERR\n");
701 die_if_kernel("Oops",&fp->ptregs,0);
702 force_sig(SIGKILL, current);
703 return;
704 }
705
706 /* get the fault address */
707 if (fp->ptregs.format == 10)
708 addr = fp->ptregs.pc + 4;
709 else
710 addr = fp->un.fmtb.baddr;
711 if (ssw & FC)
712 addr -= 2;
713
714 if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
715 /* Insn fault on same page as data fault. But we
716 should still create the ATC entry. */
717 goto create_atc_entry;
718
719 #if DEBUG
720 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
721 "pmove %%psr,%1@"
722 : "=a&" (desc)
723 : "a" (&temp), "a" (addr));
724 #else
725 asm volatile ("ptestr #1,%1@,#7\n\t"
726 "pmove %%psr,%0@"
727 : : "a" (&temp), "a" (addr));
728 #endif
729 mmusr = temp;
730
731 #ifdef DEBUG
732 printk ("mmusr is %#x for addr %#lx in task %p\n",
733 mmusr, addr, current);
734 printk ("descriptor address is %#lx, contents %#lx\n",
735 __va(desc), *(unsigned long *)__va(desc));
736 #endif
737
738 if (mmusr & MMU_I)
739 do_page_fault (&fp->ptregs, addr, 0);
740 else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
741 printk ("invalid insn access at %#lx from pc %#lx\n",
742 addr, fp->ptregs.pc);
743 #if DEBUG
744 printk("Unknown SIGSEGV - 2\n");
745 #endif
746 die_if_kernel("Oops",&fp->ptregs,mmusr);
747 force_sig(SIGSEGV, current);
748 return;
749 }
750
751 create_atc_entry:
752 /* setup an ATC entry for the access about to be retried */
753 asm volatile ("ploadr #2,%0@" : /* no outputs */
754 : "a" (addr));
755 }
756 #endif /* CPU_M68020_OR_M68030 */
757 #endif /* !CONFIG_SUN3 */
758
buserr_c(struct frame * fp)759 asmlinkage void buserr_c(struct frame *fp)
760 {
761 /* Only set esp0 if coming from user mode */
762 if (user_mode(&fp->ptregs))
763 current->thread.esp0 = (unsigned long) fp;
764
765 #if DEBUG
766 printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
767 #endif
768
769 switch (fp->ptregs.format) {
770 #if defined (CONFIG_M68060)
771 case 4: /* 68060 access error */
772 access_error060 (fp);
773 break;
774 #endif
775 #if defined (CONFIG_M68040)
776 case 0x7: /* 68040 access error */
777 access_error040 (fp);
778 break;
779 #endif
780 #if defined (CPU_M68020_OR_M68030)
781 case 0xa:
782 case 0xb:
783 bus_error030 (fp);
784 break;
785 #endif
786 default:
787 die_if_kernel("bad frame format",&fp->ptregs,0);
788 #if DEBUG
789 printk("Unknown SIGSEGV - 4\n");
790 #endif
791 force_sig(SIGSEGV, current);
792 }
793 }
794
795
796 int kstack_depth_to_print = 48;
797 extern struct module kernel_module;
798
kernel_text_address(unsigned long addr)799 static inline int kernel_text_address(unsigned long addr)
800 {
801 #ifdef CONFIG_MODULES
802 struct module *mod;
803 #endif
804 extern char _stext, _etext;
805
806 if (addr >= (unsigned long) &_stext &&
807 addr <= (unsigned long) &_etext)
808 return 1;
809
810 #ifdef CONFIG_MODULES
811 for (mod = module_list; mod != &kernel_module; mod = mod->next) {
812 /* mod_bound tests for addr being inside the vmalloc'ed
813 * module area. Of course it'd be better to test only
814 * for the .text subset... */
815 if (mod_bound(addr, 0, mod))
816 return 1;
817 }
818 #endif
819
820 return 0;
821 }
822
show_trace(unsigned long * stack)823 void show_trace(unsigned long *stack)
824 {
825 unsigned long *endstack;
826 unsigned long addr;
827 int i;
828
829 printk("Call Trace:");
830 addr = (unsigned long)stack + THREAD_SIZE - 1;
831 endstack = (unsigned long *)(addr & -THREAD_SIZE);
832 i = 0;
833 while (stack + 1 <= endstack) {
834 addr = *stack++;
835 /*
836 * If the address is either in the text segment of the
837 * kernel, or in the region which contains vmalloc'ed
838 * memory, it *may* be the address of a calling
839 * routine; if so, print it so that someone tracing
840 * down the cause of the crash will be able to figure
841 * out the call path that was taken.
842 */
843 if (kernel_text_address(addr)) {
844 if (i % 4 == 0)
845 printk("\n ");
846 printk(" [<%08lx>]", addr);
847 i++;
848 }
849 }
850 printk("\n");
851 }
852
show_trace_task(struct task_struct * tsk)853 void show_trace_task(struct task_struct *tsk)
854 {
855 show_trace((unsigned long *)tsk->thread.esp0);
856 }
857
show_stack(struct frame * fp)858 static void show_stack(struct frame *fp)
859 {
860 unsigned long *stack, *endstack, addr;
861 int i;
862
863 if (fp == NULL)
864 fp = (struct frame *)&fp;
865
866 addr = (unsigned long)&fp->un;
867 printk("Frame format=%X ", fp->ptregs.format);
868 switch (fp->ptregs.format) {
869 case 0x2:
870 printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
871 addr += sizeof(fp->un.fmt2);
872 break;
873 case 0x3:
874 printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
875 addr += sizeof(fp->un.fmt3);
876 break;
877 case 0x4:
878 printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
879 : "eff addr=%08lx pc=%08lx\n"),
880 fp->un.fmt4.effaddr, fp->un.fmt4.pc);
881 addr += sizeof(fp->un.fmt4);
882 break;
883 case 0x7:
884 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
885 fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
886 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
887 fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
888 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
889 fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
890 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
891 fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
892 printk("push data: %08lx %08lx %08lx %08lx\n",
893 fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
894 fp->un.fmt7.pd3);
895 addr += sizeof(fp->un.fmt7);
896 break;
897 case 0x9:
898 printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
899 addr += sizeof(fp->un.fmt9);
900 break;
901 case 0xa:
902 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
903 fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
904 fp->un.fmta.daddr, fp->un.fmta.dobuf);
905 addr += sizeof(fp->un.fmta);
906 break;
907 case 0xb:
908 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
909 fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
910 fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
911 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
912 fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
913 addr += sizeof(fp->un.fmtb);
914 break;
915 default:
916 printk("\n");
917 }
918
919 stack = (unsigned long *)addr;
920 endstack = (unsigned long *)((addr + THREAD_SIZE - 1) & -THREAD_SIZE);
921
922 printk("Stack from %08lx:", (unsigned long)stack);
923 for (i = 0; i < kstack_depth_to_print; i++) {
924 if (stack + 1 > endstack)
925 break;
926 if (i % 8 == 0)
927 printk("\n ");
928 printk(" %08lx", *stack++);
929 }
930 printk("\n");
931 show_trace((unsigned long *)addr);
932
933 printk("Code: ");
934 for (i = 0; i < 10; i++)
935 printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
936 printk ("\n");
937 }
938
939 /*
940 * The architecture-independent backtrace generator
941 */
dump_stack(void)942 void dump_stack(void)
943 {
944 show_stack(0);
945 }
946
bad_super_trap(struct frame * fp)947 void bad_super_trap (struct frame *fp)
948 {
949 console_verbose();
950 if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
951 printk ("*** %s *** FORMAT=%X\n",
952 vec_names[(fp->ptregs.vector) >> 2],
953 fp->ptregs.format);
954 else
955 printk ("*** Exception %d *** FORMAT=%X\n",
956 (fp->ptregs.vector) >> 2,
957 fp->ptregs.format);
958 if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
959 unsigned short ssw = fp->un.fmtb.ssw;
960
961 printk ("SSW=%#06x ", ssw);
962
963 if (ssw & RC)
964 printk ("Pipe stage C instruction fault at %#010lx\n",
965 (fp->ptregs.format) == 0xA ?
966 fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
967 if (ssw & RB)
968 printk ("Pipe stage B instruction fault at %#010lx\n",
969 (fp->ptregs.format) == 0xA ?
970 fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
971 if (ssw & DF)
972 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
973 ssw & RW ? "read" : "write",
974 fp->un.fmtb.daddr, space_names[ssw & DFC],
975 fp->ptregs.pc);
976 }
977 printk ("Current process id is %d\n", current->pid);
978 die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
979 }
980
trap_c(struct frame * fp)981 asmlinkage void trap_c(struct frame *fp)
982 {
983 int sig;
984 siginfo_t info;
985
986 if (fp->ptregs.sr & PS_S) {
987 if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
988 /* traced a trapping instruction */
989 current->ptrace |= PT_DTRACE;
990 } else
991 bad_super_trap(fp);
992 return;
993 }
994
995 /* send the appropriate signal to the user program */
996 switch ((fp->ptregs.vector) >> 2) {
997 case VEC_ADDRERR:
998 info.si_code = BUS_ADRALN;
999 sig = SIGBUS;
1000 break;
1001 case VEC_ILLEGAL:
1002 case VEC_LINE10:
1003 case VEC_LINE11:
1004 info.si_code = ILL_ILLOPC;
1005 sig = SIGILL;
1006 break;
1007 case VEC_PRIV:
1008 info.si_code = ILL_PRVOPC;
1009 sig = SIGILL;
1010 break;
1011 case VEC_COPROC:
1012 info.si_code = ILL_COPROC;
1013 sig = SIGILL;
1014 break;
1015 case VEC_TRAP1:
1016 case VEC_TRAP2:
1017 case VEC_TRAP3:
1018 case VEC_TRAP4:
1019 case VEC_TRAP5:
1020 case VEC_TRAP6:
1021 case VEC_TRAP7:
1022 case VEC_TRAP8:
1023 case VEC_TRAP9:
1024 case VEC_TRAP10:
1025 case VEC_TRAP11:
1026 case VEC_TRAP12:
1027 case VEC_TRAP13:
1028 case VEC_TRAP14:
1029 info.si_code = ILL_ILLTRP;
1030 sig = SIGILL;
1031 break;
1032 case VEC_FPBRUC:
1033 case VEC_FPOE:
1034 case VEC_FPNAN:
1035 info.si_code = FPE_FLTINV;
1036 sig = SIGFPE;
1037 break;
1038 case VEC_FPIR:
1039 info.si_code = FPE_FLTRES;
1040 sig = SIGFPE;
1041 break;
1042 case VEC_FPDIVZ:
1043 info.si_code = FPE_FLTDIV;
1044 sig = SIGFPE;
1045 break;
1046 case VEC_FPUNDER:
1047 info.si_code = FPE_FLTUND;
1048 sig = SIGFPE;
1049 break;
1050 case VEC_FPOVER:
1051 info.si_code = FPE_FLTOVF;
1052 sig = SIGFPE;
1053 break;
1054 case VEC_ZERODIV:
1055 info.si_code = FPE_INTDIV;
1056 sig = SIGFPE;
1057 break;
1058 case VEC_CHK:
1059 case VEC_TRAP:
1060 info.si_code = FPE_INTOVF;
1061 sig = SIGFPE;
1062 break;
1063 case VEC_TRACE: /* ptrace single step */
1064 info.si_code = TRAP_TRACE;
1065 sig = SIGTRAP;
1066 break;
1067 case VEC_TRAP15: /* breakpoint */
1068 info.si_code = TRAP_BRKPT;
1069 sig = SIGTRAP;
1070 break;
1071 default:
1072 info.si_code = ILL_ILLOPC;
1073 sig = SIGILL;
1074 break;
1075 }
1076 info.si_signo = sig;
1077 info.si_errno = 0;
1078 switch (fp->ptregs.format) {
1079 default:
1080 info.si_addr = (void *) fp->ptregs.pc;
1081 break;
1082 case 2:
1083 info.si_addr = (void *) fp->un.fmt2.iaddr;
1084 break;
1085 case 7:
1086 info.si_addr = (void *) fp->un.fmt7.effaddr;
1087 break;
1088 case 9:
1089 info.si_addr = (void *) fp->un.fmt9.iaddr;
1090 break;
1091 case 10:
1092 info.si_addr = (void *) fp->un.fmta.daddr;
1093 break;
1094 case 11:
1095 info.si_addr = (void *) fp->un.fmtb.daddr;
1096 break;
1097 }
1098 force_sig_info (sig, &info, current);
1099 }
1100
die_if_kernel(char * str,struct pt_regs * fp,int nr)1101 void die_if_kernel (char *str, struct pt_regs *fp, int nr)
1102 {
1103 if (!(fp->sr & PS_S))
1104 return;
1105
1106 console_verbose();
1107 printk("%s: %08x\n",str,nr);
1108 printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
1109 fp->pc, fp->sr, fp, fp->a2);
1110 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
1111 fp->d0, fp->d1, fp->d2, fp->d3);
1112 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
1113 fp->d4, fp->d5, fp->a0, fp->a1);
1114
1115 printk("Process %s (pid: %d, stackpage=%08lx)\n",
1116 current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
1117 show_stack((struct frame *)fp);
1118 do_exit(SIGSEGV);
1119 }
1120
1121 /*
1122 * This function is called if an error occur while accessing
1123 * user-space from the fpsp040 code.
1124 */
fpsp040_die(void)1125 asmlinkage void fpsp040_die(void)
1126 {
1127 do_exit(SIGSEGV);
1128 }
1129
1130 #ifdef CONFIG_M68KFPU_EMU
fpemu_signal(int signal,int code,void * addr)1131 asmlinkage void fpemu_signal(int signal, int code, void *addr)
1132 {
1133 siginfo_t info;
1134
1135 info.si_signo = signal;
1136 info.si_errno = 0;
1137 info.si_code = code;
1138 info.si_addr = addr;
1139 force_sig_info(signal, &info, current);
1140 }
1141 #endif
1142