2 * linux/arch/m68k/kernel/traps.c
4 * Copyright (C) 1993, 1994 by Hamish Macdonald
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
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
18 * Sets up all exception vectors
21 #include <linux/config.h>
22 #include <linux/sched.h>
23 #include <linux/signal.h>
24 #include <linux/kernel.h>
26 #include <linux/types.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>
33 #include <asm/setup.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>
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);
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
,
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,
64 /* nmi handler for the Amiga */
67 SYMBOL_NAME_STR(nmihandler
) ": rte");
70 * this must be called very early as the kernel might
71 * use some instruction that are emulated on the 060
73 void __init
base_trap_init(void)
75 /* setup the exception vector table */
76 __asm__
volatile ("movec %0,%%vbr" : : "r" ((void*)vectors
));
79 /* set up ISP entry points */
80 asmlinkage
void unimp_vec(void) asm ("_060_isp_unimp");
82 vectors
[VEC_UNIMPII
] = unimp_vec
;
86 void __init
trap_init (void)
90 for (i
= 48; i
< 64; i
++)
94 for (i
= 64; i
< 256; i
++)
95 vectors
[i
] = inthandler
;
97 #ifdef CONFIG_M68KFPU_EMU
99 vectors
[VEC_LINE11
] = fpu_emu
;
102 if (CPU_IS_040
&& !FPU_IS_EMU
) {
103 /* set up FPSP entry points */
104 asmlinkage
void dz_vec(void) asm ("dz");
105 asmlinkage
void inex_vec(void) asm ("inex");
106 asmlinkage
void ovfl_vec(void) asm ("ovfl");
107 asmlinkage
void unfl_vec(void) asm ("unfl");
108 asmlinkage
void snan_vec(void) asm ("snan");
109 asmlinkage
void operr_vec(void) asm ("operr");
110 asmlinkage
void bsun_vec(void) asm ("bsun");
111 asmlinkage
void fline_vec(void) asm ("fline");
112 asmlinkage
void unsupp_vec(void) asm ("unsupp");
114 vectors
[VEC_FPDIVZ
] = dz_vec
;
115 vectors
[VEC_FPIR
] = inex_vec
;
116 vectors
[VEC_FPOVER
] = ovfl_vec
;
117 vectors
[VEC_FPUNDER
] = unfl_vec
;
118 vectors
[VEC_FPNAN
] = snan_vec
;
119 vectors
[VEC_FPOE
] = operr_vec
;
120 vectors
[VEC_FPBRUC
] = bsun_vec
;
121 vectors
[VEC_LINE11
] = fline_vec
;
122 vectors
[VEC_FPUNSUP
] = unsupp_vec
;
125 if (CPU_IS_060
&& !FPU_IS_EMU
) {
126 /* set up IFPSP entry points */
127 asmlinkage
void snan_vec(void) asm ("_060_fpsp_snan");
128 asmlinkage
void operr_vec(void) asm ("_060_fpsp_operr");
129 asmlinkage
void ovfl_vec(void) asm ("_060_fpsp_ovfl");
130 asmlinkage
void unfl_vec(void) asm ("_060_fpsp_unfl");
131 asmlinkage
void dz_vec(void) asm ("_060_fpsp_dz");
132 asmlinkage
void inex_vec(void) asm ("_060_fpsp_inex");
133 asmlinkage
void fline_vec(void) asm ("_060_fpsp_fline");
134 asmlinkage
void unsupp_vec(void) asm ("_060_fpsp_unsupp");
135 asmlinkage
void effadd_vec(void) asm ("_060_fpsp_effadd");
137 vectors
[VEC_FPNAN
] = snan_vec
;
138 vectors
[VEC_FPOE
] = operr_vec
;
139 vectors
[VEC_FPOVER
] = ovfl_vec
;
140 vectors
[VEC_FPUNDER
] = unfl_vec
;
141 vectors
[VEC_FPDIVZ
] = dz_vec
;
142 vectors
[VEC_FPIR
] = inex_vec
;
143 vectors
[VEC_LINE11
] = fline_vec
;
144 vectors
[VEC_FPUNSUP
] = unsupp_vec
;
145 vectors
[VEC_UNIMPEA
] = effadd_vec
;
148 /* if running on an amiga, make the NMI interrupt do nothing */
150 vectors
[VEC_INT7
] = nmihandler
;
155 static inline void console_verbose(void)
157 extern int console_loglevel
;
158 console_loglevel
= 15;
162 static char *vec_names
[] = {
163 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
164 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
165 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
166 "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
167 "FORMAT ERROR", "UNINITIALIZED INTERRUPT",
168 "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
169 "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
170 "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
171 "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
172 "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
173 "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
174 "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
175 "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
176 "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
177 "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
178 "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
179 "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
180 "FPCP UNSUPPORTED OPERATION",
181 "MMU CONFIGURATION ERROR"
185 static char *space_names
[] = {
186 "Space 0", "User Data", "User Program", "Space 3",
187 "Space 4", "Super Data", "Super Program", "CPU"
190 static char *space_names
[] = {
191 "Space 0", "User Data", "User Program", "Control",
192 "Space 4", "Super Data", "Super Program", "CPU"
196 void die_if_kernel(char *,struct pt_regs
*,int);
197 asmlinkage
int do_page_fault(struct pt_regs
*regs
, unsigned long address
,
198 unsigned long error_code
);
199 int send_fault_sig(struct pt_regs
*regs
);
201 asmlinkage
void trap_c(struct frame
*fp
);
203 #if defined (CONFIG_M68060)
204 static inline void access_error060 (struct frame
*fp
)
206 unsigned long fslw
= fp
->un
.fmt4
.pc
; /* is really FSLW for access error */
209 printk("fslw=%#lx, fa=%#lx\n", fslw
, fp
->un
.fmt4
.effaddr
);
212 if (fslw
& MMU060_BPE
) {
213 /* branch prediction error -> clear branch cache */
214 __asm__
__volatile__ ("movec %/cacr,%/d0\n\t"
215 "orl #0x00400000,%/d0\n\t"
218 /* return if there's no other error */
219 if (!(fslw
& MMU060_ERR_BITS
) && !(fslw
& MMU060_SEE
))
223 if (fslw
& (MMU060_DESC_ERR
| MMU060_WP
| MMU060_SP
)) {
224 unsigned long errorcode
;
225 unsigned long addr
= fp
->un
.fmt4
.effaddr
;
227 if (fslw
& MMU060_MA
)
228 addr
= (addr
+ 7) & -8;
231 if (fslw
& MMU060_DESC_ERR
) {
232 __flush_tlb040_one(addr
);
238 printk("errorcode = %d\n", errorcode
);
240 do_page_fault(&fp
->ptregs
, addr
, errorcode
);
241 } else if (fslw
& (MMU060_SEE
)){
242 /* Software Emulation Error.
243 * fault during mem_read/mem_write in ifpsp060/os.S
245 send_fault_sig(&fp
->ptregs
);
247 printk("pc=%#lx, fa=%#lx\n", fp
->ptregs
.pc
, fp
->un
.fmt4
.effaddr
);
248 printk( "68060 access error, fslw=%lx\n", fslw
);
252 #endif /* CONFIG_M68060 */
254 #if defined (CONFIG_M68040)
255 static inline unsigned long probe040(int iswrite
, unsigned long addr
)
259 asm volatile (".chip 68040");
262 asm volatile ("ptestw (%0)" : : "a" (addr
));
264 asm volatile ("ptestr (%0)" : : "a" (addr
));
266 asm volatile ("movec %%mmusr,%0" : "=r" (mmusr
));
268 asm volatile (".chip 68k");
273 static inline int do_040writeback1(unsigned short wbs
, unsigned long wba
,
278 set_fs(MAKE_MM_SEG(wbs
));
280 switch (wbs
& WBSIZ_040
) {
282 res
= put_user(wbd
& 0xff, (char *)wba
);
285 res
= put_user(wbd
& 0xffff, (short *)wba
);
288 res
= put_user(wbd
, (int *)wba
);
293 printk("do_040writeback1, res=%d\n",res
);
299 /* after an exception in a writeback the stack frame coresponding
300 * to that exception is discarded, set a few bits in the old frame
301 * to simulate what it should look like
303 static inline void fix_xframe040(struct frame
*fp
, unsigned short wbs
)
305 fp
->un
.fmt7
.faddr
= current
->thread
.faddr
;
306 fp
->un
.fmt7
.ssw
= wbs
& 0xff;
309 static inline void do_040writebacks(struct frame
*fp
)
313 if (fp
->un
.fmt7
.wb1s
& WBV_040
)
314 printk("access_error040: cannot handle 1st writeback. oops.\n");
317 if ((fp
->un
.fmt7
.wb2s
& WBV_040
) &&
318 !(fp
->un
.fmt7
.wb2s
& WBTT_040
)) {
319 res
= do_040writeback1(fp
->un
.fmt7
.wb2s
, fp
->un
.fmt7
.wb2a
,
322 fix_xframe040(fp
, fp
->un
.fmt7
.wb2s
);
324 fp
->un
.fmt7
.wb2s
= 0;
327 /* do the 2nd wb only if the first one was succesful (except for a kernel wb) */
328 if (fp
->un
.fmt7
.wb3s
& WBV_040
&& (!res
|| fp
->un
.fmt7
.wb3s
& 4)) {
329 res
= do_040writeback1(fp
->un
.fmt7
.wb3s
, fp
->un
.fmt7
.wb3a
,
332 fix_xframe040(fp
, fp
->un
.fmt7
.wb3s
);
334 fp
->un
.fmt7
.wb3s
= 0;
338 send_fault_sig(&fp
->ptregs
);
342 * called from sigreturn(), must ensure userspace code didn't
343 * manipulate exception frame to circumvent protection, then complete
345 * we just clear TM2 to turn it into an userspace access
347 asmlinkage
void berr_040cleanup(struct frame
*fp
)
349 mm_segment_t old_fs
= get_fs();
351 fp
->un
.fmt7
.wb2s
&= ~4;
352 fp
->un
.fmt7
.wb3s
&= ~4;
354 do_040writebacks(fp
);
358 static inline void access_error040(struct frame
*fp
)
360 unsigned short ssw
= fp
->un
.fmt7
.ssw
;
361 mm_segment_t old_fs
= get_fs();
365 printk("ssw=%#x, fa=%#lx\n", ssw
, fp
->un
.fmt7
.faddr
);
366 printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp
->un
.fmt7
.wb1s
,
367 fp
->un
.fmt7
.wb2s
, fp
->un
.fmt7
.wb3s
);
368 printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
369 fp
->un
.fmt7
.wb2a
, fp
->un
.fmt7
.wb3a
,
370 fp
->un
.fmt7
.wb2d
, fp
->un
.fmt7
.wb3d
);
374 unsigned long addr
= fp
->un
.fmt7
.faddr
;
375 unsigned long errorcode
;
378 * The MMU status has to be determined AFTER the address
379 * has been corrected if there was a misaligned access (MA).
382 addr
= (addr
+ 7) & -8;
384 set_fs(MAKE_MM_SEG(ssw
));
385 /* MMU error, get the MMUSR info for this access */
386 mmusr
= probe040(!(ssw
& RW_040
), addr
);
388 printk("mmusr = %lx\n", mmusr
);
391 if (!(mmusr
& MMU_R_040
)) {
392 /* clear the invalid atc entry */
393 __flush_tlb040_one(addr
);
398 if (do_page_fault(&fp
->ptregs
, addr
, errorcode
)) {
400 printk("do_page_fault() !=0 \n");
402 if (user_mode(&fp
->ptregs
)){
403 /* delay writebacks after signal delivery */
405 printk(".. was usermode - return\n");
409 /* disable writeback into user space from kernel
410 * (if do_page_fault didn't fix the mapping,
411 * the writeback won't do good)
414 printk(".. disabling wb2\n");
416 if (fp
->un
.fmt7
.wb2a
== fp
->un
.fmt7
.faddr
)
417 fp
->un
.fmt7
.wb2s
&= ~WBV_040
;
420 printk("68040 access error, ssw=%x\n", ssw
);
424 do_040writebacks(fp
);
427 #endif /* CONFIG_M68040 */
429 #if defined(CONFIG_SUN3)
430 #include <asm/sun3mmu.h>
432 extern int mmu_emu_handle_fault (unsigned long, int, int);
434 /* sun3 version of bus_error030 */
436 extern inline void bus_error030 (struct frame
*fp
)
438 unsigned char buserr_type
= sun3_get_buserr ();
439 unsigned long addr
, errorcode
;
440 unsigned short ssw
= fp
->un
.fmtb
.ssw
;
444 printk ("Instruction fault at %#010lx\n",
446 fp
->ptregs
.format
== 0xa ? fp
->ptregs
.pc
+ 2 : fp
->un
.fmtb
.baddr
- 2
448 fp
->ptregs
.format
== 0xa ? fp
->ptregs
.pc
+ 4 : fp
->un
.fmtb
.baddr
);
450 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
451 ssw
& RW
? "read" : "write",
453 space_names
[ssw
& DFC
], fp
->ptregs
.pc
);
457 * Check if this page should be demand-mapped. This needs to go before
458 * the testing for a bad kernel-space access (demand-mapping applies
459 * to kernel accesses too).
463 && (buserr_type
& (SUN3_BUSERR_PROTERR
| SUN3_BUSERR_INVALID
))) {
464 if (mmu_emu_handle_fault (fp
->un
.fmtb
.daddr
, ssw
& RW
, 0))
468 /* Check for kernel-space pagefault (BAD). */
469 if (fp
->ptregs
.sr
& PS_S
) {
470 /* kernel fault must be a data fault to user space */
471 if (! ((ssw
& DF
) && ((ssw
& DFC
) == USER_DATA
))) {
472 // try checking the kernel mappings before surrender
473 if (mmu_emu_handle_fault (fp
->un
.fmtb
.daddr
, ssw
& RW
, 1))
475 /* instruction fault or kernel data fault! */
477 printk ("Instruction fault at %#010lx\n",
480 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
481 ssw
& RW
? "read" : "write",
483 space_names
[ssw
& DFC
], fp
->ptregs
.pc
);
485 printk ("BAD KERNEL BUSERR\n");
487 die_if_kernel("Oops", &fp
->ptregs
,0);
488 force_sig(SIGKILL
, current
);
493 if (!(ssw
& (FC
| FB
)) && !(ssw
& DF
))
494 /* not an instruction fault or data fault! BAD */
495 panic ("USER BUSERR w/o instruction or data fault");
499 /* First handle the data fault, if any. */
501 addr
= fp
->un
.fmtb
.daddr
;
503 // errorcode bit 0: 0 -> no page 1 -> protection fault
504 // errorcode bit 1: 0 -> read fault 1 -> write fault
506 // (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault
507 // (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault
509 if (buserr_type
& SUN3_BUSERR_PROTERR
)
511 else if (buserr_type
& SUN3_BUSERR_INVALID
)
515 printk ("*** unexpected busfault type=%#04x\n", buserr_type
);
516 printk ("invalid %s access at %#lx from pc %#lx\n",
517 !(ssw
& RW
) ? "write" : "read", addr
,
520 die_if_kernel ("Oops", &fp
->ptregs
, buserr_type
);
521 force_sig (SIGBUS
, current
);
525 //todo: wtf is RM bit? --m
526 if (!(ssw
& RW
) || ssw
& RM
)
529 /* Handle page fault. */
530 do_page_fault (&fp
->ptregs
, addr
, errorcode
);
532 /* Retry the data fault now. */
536 /* Now handle the instruction fault. */
538 /* Get the fault address. */
539 if (fp
->ptregs
.format
== 0xA)
540 addr
= fp
->ptregs
.pc
+ 4;
542 addr
= fp
->un
.fmtb
.baddr
;
546 if (buserr_type
& SUN3_BUSERR_INVALID
) {
547 if (!mmu_emu_handle_fault (fp
->un
.fmtb
.daddr
, 1, 0))
548 do_page_fault (&fp
->ptregs
, addr
, 0);
551 printk ("protection fault on insn access (segv).\n");
553 force_sig (SIGSEGV
, current
);
557 #if defined(CPU_M68020_OR_M68030)
558 static inline void bus_error030 (struct frame
*fp
)
560 volatile unsigned short temp
;
561 unsigned short mmusr
;
562 unsigned long addr
, errorcode
;
563 unsigned short ssw
= fp
->un
.fmtb
.ssw
;
564 int user_space_fault
= 1;
570 printk ("pid = %x ", current
->pid
);
571 printk ("SSW=%#06x ", ssw
);
574 printk ("Instruction fault at %#010lx\n",
576 fp
->ptregs
.format
== 0xa ? fp
->ptregs
.pc
+ 2 : fp
->un
.fmtb
.baddr
- 2
578 fp
->ptregs
.format
== 0xa ? fp
->ptregs
.pc
+ 4 : fp
->un
.fmtb
.baddr
);
580 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
581 ssw
& RW
? "read" : "write",
583 space_names
[ssw
& DFC
], fp
->ptregs
.pc
);
586 if (fp
->ptregs
.sr
& PS_S
) {
587 /* kernel fault must be a data fault to user space */
588 if (! ((ssw
& DF
) && ((ssw
& DFC
) == USER_DATA
))) {
589 /* instruction fault or kernel data fault! */
591 printk ("Instruction fault at %#010lx\n",
594 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
595 ssw
& RW
? "read" : "write",
597 space_names
[ssw
& DFC
], fp
->ptregs
.pc
);
599 printk ("BAD KERNEL BUSERR\n");
600 die_if_kernel("Oops",&fp
->ptregs
,0);
601 force_sig(SIGKILL
, current
);
606 if (!(ssw
& (FC
| FB
)) && !(ssw
& DF
))
607 /* not an instruction fault or data fault! BAD */
608 panic ("USER BUSERR w/o instruction or data fault");
609 user_space_fault
= 1;
611 printk("User space bus-error\n");
615 /* ++andreas: If a data fault and an instruction fault happen
616 at the same time map in both pages. */
618 /* First handle the data fault, if any. */
621 addr
= fp
->un
.fmtb
.daddr
;
624 if (user_space_fault
) {
626 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
629 : "a" (&temp
), "a" (addr
));
631 asm volatile ("ptestr #1,%1@,#7\n\t"
633 : : "a" (&temp
), "a" (addr
));
639 printk ("mmusr is %#x for addr %#lx in task %p\n",
640 mmusr
, addr
, current
);
641 printk ("descriptor address is %#lx, contents %#lx\n",
642 __va(desc
), *(unsigned long *)__va(desc
));
645 errorcode
= (mmusr
& MMU_I
) ? 0 : 1;
646 if (!(ssw
& RW
) || (ssw
& RM
))
649 if (mmusr
& (MMU_I
| MMU_WP
)) {
650 /* Don't try to do anything further if an exception was
652 if (do_page_fault (&fp
->ptregs
, addr
, errorcode
) < 0)
654 } else if (mmusr
& (MMU_B
|MMU_L
|MMU_S
)) {
655 printk ("invalid %s access at %#lx from pc %#lx\n",
656 !(ssw
& RW
) ? "write" : "read", addr
,
658 die_if_kernel("Oops",&fp
->ptregs
,mmusr
);
659 force_sig(SIGSEGV
, current
);
663 static volatile long tlong
;
666 printk ("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
667 !(ssw
& RW
) ? "write" : "read", addr
,
669 asm volatile ("ptestr #1,%1@,#0\n\t"
672 : "a" (&temp
), "a" (addr
));
675 printk ("level 0 mmusr is %#x\n", mmusr
);
677 asm volatile ("pmove %/tt0,%0@"
680 printk ("tt0 is %#lx, ", tlong
);
681 asm volatile ("pmove %/tt1,%0@"
684 printk ("tt1 is %#lx\n", tlong
);
687 printk("Unknown SIGSEGV - 1\n");
689 die_if_kernel("Oops",&fp
->ptregs
,mmusr
);
690 force_sig(SIGSEGV
, current
);
694 /* setup an ATC entry for the access about to be retried */
696 asm volatile ("ploadw %1,%0@" : /* no outputs */
697 : "a" (addr
), "d" (ssw
));
699 asm volatile ("ploadr %1,%0@" : /* no outputs */
700 : "a" (addr
), "d" (ssw
));
703 /* Now handle the instruction fault. */
705 if (!(ssw
& (FC
|FB
)))
708 /* get the fault address */
709 if (fp
->ptregs
.format
== 10)
710 addr
= fp
->ptregs
.pc
+ 4;
712 addr
= fp
->un
.fmtb
.baddr
;
716 if ((ssw
& DF
) && ((addr
^ fp
->un
.fmtb
.daddr
) & PAGE_MASK
) == 0)
717 /* Insn fault on same page as data fault. But we
718 should still create the ATC entry. */
719 goto create_atc_entry
;
722 if (user_space_fault
) {
724 asm volatile ("ptestr #1,%2@,#7,%0\n\t"
727 : "a" (&temp
), "a" (addr
));
729 asm volatile ("ptestr #1,%1@,#7\n\t"
731 : : "a" (&temp
), "a" (addr
));
737 printk ("mmusr is %#x for addr %#lx in task %p\n",
738 mmusr
, addr
, current
);
739 printk ("descriptor address is %#lx, contents %#lx\n",
740 __va(desc
), *(unsigned long *)__va(desc
));
744 do_page_fault (&fp
->ptregs
, addr
, 0);
745 else if (mmusr
& (MMU_B
|MMU_L
|MMU_S
)) {
746 printk ("invalid insn access at %#lx from pc %#lx\n",
747 addr
, fp
->ptregs
.pc
);
749 printk("Unknown SIGSEGV - 2\n");
751 die_if_kernel("Oops",&fp
->ptregs
,mmusr
);
752 force_sig(SIGSEGV
, current
);
757 /* setup an ATC entry for the access about to be retried */
758 asm volatile ("ploadr #2,%0@" : /* no outputs */
761 #endif /* CPU_M68020_OR_M68030 */
762 #endif /* !CONFIG_SUN3 */
764 asmlinkage
void buserr_c(struct frame
*fp
)
766 /* Only set esp0 if coming from user mode */
767 if (user_mode(&fp
->ptregs
))
768 current
->thread
.esp0
= (unsigned long) fp
;
771 printk ("*** Bus Error *** Format is %x\n", fp
->ptregs
.format
);
774 switch (fp
->ptregs
.format
) {
775 #if defined (CONFIG_M68060)
776 case 4: /* 68060 access error */
777 access_error060 (fp
);
780 #if defined (CONFIG_M68040)
781 case 0x7: /* 68040 access error */
782 access_error040 (fp
);
785 #if defined (CPU_M68020_OR_M68030)
792 die_if_kernel("bad frame format",&fp
->ptregs
,0);
794 printk("Unknown SIGSEGV - 4\n");
796 force_sig(SIGSEGV
, current
);
801 int kstack_depth_to_print
= 48;
803 /* MODULE_RANGE is a guess of how much space is likely to be
805 #define MODULE_RANGE (8*1024*1024)
807 static void dump_stack(struct frame
*fp
)
809 unsigned long *stack
, *endstack
, addr
, module_start
, module_end
;
810 extern char _start
, _etext
;
813 addr
= (unsigned long)&fp
->un
;
814 printk("Frame format=%X ", fp
->ptregs
.format
);
815 switch (fp
->ptregs
.format
) {
817 printk("instr addr=%08lx\n", fp
->un
.fmt2
.iaddr
);
818 addr
+= sizeof(fp
->un
.fmt2
);
821 printk("eff addr=%08lx\n", fp
->un
.fmt3
.effaddr
);
822 addr
+= sizeof(fp
->un
.fmt3
);
825 printk((CPU_IS_060
? "fault addr=%08lx fslw=%08lx\n"
826 : "eff addr=%08lx pc=%08lx\n"),
827 fp
->un
.fmt4
.effaddr
, fp
->un
.fmt4
.pc
);
828 addr
+= sizeof(fp
->un
.fmt4
);
831 printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
832 fp
->un
.fmt7
.effaddr
, fp
->un
.fmt7
.ssw
, fp
->un
.fmt7
.faddr
);
833 printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
834 fp
->un
.fmt7
.wb1s
, fp
->un
.fmt7
.wb1a
, fp
->un
.fmt7
.wb1dpd0
);
835 printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
836 fp
->un
.fmt7
.wb2s
, fp
->un
.fmt7
.wb2a
, fp
->un
.fmt7
.wb2d
);
837 printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
838 fp
->un
.fmt7
.wb3s
, fp
->un
.fmt7
.wb3a
, fp
->un
.fmt7
.wb3d
);
839 printk("push data: %08lx %08lx %08lx %08lx\n",
840 fp
->un
.fmt7
.wb1dpd0
, fp
->un
.fmt7
.pd1
, fp
->un
.fmt7
.pd2
,
842 addr
+= sizeof(fp
->un
.fmt7
);
845 printk("instr addr=%08lx\n", fp
->un
.fmt9
.iaddr
);
846 addr
+= sizeof(fp
->un
.fmt9
);
849 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
850 fp
->un
.fmta
.ssw
, fp
->un
.fmta
.isc
, fp
->un
.fmta
.isb
,
851 fp
->un
.fmta
.daddr
, fp
->un
.fmta
.dobuf
);
852 addr
+= sizeof(fp
->un
.fmta
);
855 printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
856 fp
->un
.fmtb
.ssw
, fp
->un
.fmtb
.isc
, fp
->un
.fmtb
.isb
,
857 fp
->un
.fmtb
.daddr
, fp
->un
.fmtb
.dobuf
);
858 printk("baddr=%08lx dibuf=%08lx ver=%x\n",
859 fp
->un
.fmtb
.baddr
, fp
->un
.fmtb
.dibuf
, fp
->un
.fmtb
.ver
);
860 addr
+= sizeof(fp
->un
.fmtb
);
866 stack
= (unsigned long *)addr
;
867 endstack
= (unsigned long *)PAGE_ALIGN(addr
);
869 printk("Stack from %08lx:", (unsigned long)stack
);
870 for (i
= 0; i
< kstack_depth_to_print
; i
++) {
871 if (stack
+ 1 > endstack
)
875 printk(" %08lx", *stack
++);
878 printk ("\nCall Trace:");
879 stack
= (unsigned long *) addr
;
881 module_start
= VMALLOC_START
;
882 module_end
= module_start
+ MODULE_RANGE
;
883 while (stack
+ 1 <= endstack
) {
886 * If the address is either in the text segment of the
887 * kernel, or in the region which contains vmalloc'ed
888 * memory, it *may* be the address of a calling
889 * routine; if so, print it so that someone tracing
890 * down the cause of the crash will be able to figure
891 * out the call path that was taken.
893 if (((addr
>= (unsigned long) &_start
) &&
894 (addr
<= (unsigned long) &_etext
)) ||
895 ((addr
>= module_start
) && (addr
<= module_end
))) {
898 printk(" [<%08lx>]", addr
);
903 for (i
= 0; i
< 10; i
++)
904 printk("%04x ", 0xffff & ((short *) fp
->ptregs
.pc
)[i
]);
908 void bad_super_trap (struct frame
*fp
)
911 if (fp
->ptregs
.vector
< 4*sizeof(vec_names
)/sizeof(vec_names
[0]))
912 printk ("*** %s *** FORMAT=%X\n",
913 vec_names
[(fp
->ptregs
.vector
) >> 2],
916 printk ("*** Exception %d *** FORMAT=%X\n",
917 (fp
->ptregs
.vector
) >> 2,
919 if (fp
->ptregs
.vector
>> 2 == VEC_ADDRERR
&& CPU_IS_020_OR_030
) {
920 unsigned short ssw
= fp
->un
.fmtb
.ssw
;
922 printk ("SSW=%#06x ", ssw
);
925 printk ("Pipe stage C instruction fault at %#010lx\n",
926 (fp
->ptregs
.format
) == 0xA ?
927 fp
->ptregs
.pc
+ 2 : fp
->un
.fmtb
.baddr
- 2);
929 printk ("Pipe stage B instruction fault at %#010lx\n",
930 (fp
->ptregs
.format
) == 0xA ?
931 fp
->ptregs
.pc
+ 4 : fp
->un
.fmtb
.baddr
);
933 printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
934 ssw
& RW
? "read" : "write",
935 fp
->un
.fmtb
.daddr
, space_names
[ssw
& DFC
],
938 printk ("Current process id is %d\n", current
->pid
);
939 die_if_kernel("BAD KERNEL TRAP", &fp
->ptregs
, 0);
942 asmlinkage
void trap_c(struct frame
*fp
)
947 if (fp
->ptregs
.sr
& PS_S
) {
948 if ((fp
->ptregs
.vector
>> 2) == VEC_TRACE
) {
949 /* traced a trapping instruction */
950 current
->ptrace
|= PT_DTRACE
;
956 /* send the appropriate signal to the user program */
957 switch ((fp
->ptregs
.vector
) >> 2) {
959 info
.si_code
= BUS_ADRALN
;
965 info
.si_code
= ILL_ILLOPC
;
969 info
.si_code
= ILL_PRVOPC
;
973 info
.si_code
= ILL_COPROC
;
990 info
.si_code
= ILL_ILLTRP
;
996 info
.si_code
= FPE_FLTINV
;
1000 info
.si_code
= FPE_FLTRES
;
1004 info
.si_code
= FPE_FLTDIV
;
1008 info
.si_code
= FPE_FLTUND
;
1012 info
.si_code
= FPE_FLTOVF
;
1016 info
.si_code
= FPE_INTDIV
;
1021 info
.si_code
= FPE_INTOVF
;
1024 case VEC_TRACE
: /* ptrace single step */
1025 info
.si_code
= TRAP_TRACE
;
1028 case VEC_TRAP15
: /* breakpoint */
1029 info
.si_code
= TRAP_BRKPT
;
1033 info
.si_code
= ILL_ILLOPC
;
1037 info
.si_signo
= sig
;
1039 switch (fp
->ptregs
.format
) {
1041 info
.si_addr
= (void *) fp
->ptregs
.pc
;
1044 info
.si_addr
= (void *) fp
->un
.fmt2
.iaddr
;
1047 info
.si_addr
= (void *) fp
->un
.fmt7
.effaddr
;
1050 info
.si_addr
= (void *) fp
->un
.fmt9
.iaddr
;
1053 info
.si_addr
= (void *) fp
->un
.fmta
.daddr
;
1056 info
.si_addr
= (void *) fp
->un
.fmtb
.daddr
;
1059 force_sig_info (sig
, &info
, current
);
1062 void die_if_kernel (char *str
, struct pt_regs
*fp
, int nr
)
1064 if (!(fp
->sr
& PS_S
))
1068 printk("%s: %08x\n",str
,nr
);
1069 printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
1070 fp
->pc
, fp
->sr
, fp
, fp
->a2
);
1071 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n",
1072 fp
->d0
, fp
->d1
, fp
->d2
, fp
->d3
);
1073 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n",
1074 fp
->d4
, fp
->d5
, fp
->a0
, fp
->a1
);
1076 printk("Process %s (pid: %d, stackpage=%08lx)\n",
1077 current
->comm
, current
->pid
, PAGE_SIZE
+(unsigned long)current
);
1078 dump_stack((struct frame
*)fp
);
1083 * This function is called if an error occur while accessing
1084 * user-space from the fpsp040 code.
1086 asmlinkage
void fpsp040_die(void)
1091 #ifdef CONFIG_M68KFPU_EMU
1092 asmlinkage
void fpemu_signal(int signal
, int code
, void *addr
)
1096 info
.si_signo
= signal
;
1098 info
.si_code
= code
;
1099 info
.si_addr
= addr
;
1100 force_sig_info(signal
, &info
, current
);