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