Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / sparc64 / kernel / traps.c
blob2562df1f333a63d410705e8f906eeb678bda93c5
1 /* $Id: traps.c,v 1.68 2000/11/22 06:50:37 davem Exp $
2 * arch/sparc64/kernel/traps.c
4 * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
6 */
8 /*
9 * I like traps on v9, :))))
12 #include <linux/config.h>
13 #include <linux/sched.h> /* for jiffies */
14 #include <linux/kernel.h>
15 #include <linux/signal.h>
16 #include <linux/smp.h>
17 #include <linux/smp_lock.h>
19 #include <asm/delay.h>
20 #include <asm/system.h>
21 #include <asm/ptrace.h>
22 #include <asm/oplib.h>
23 #include <asm/page.h>
24 #include <asm/pgtable.h>
25 #include <asm/unistd.h>
26 #include <asm/uaccess.h>
27 #include <asm/fpumacro.h>
28 #include <asm/lsu.h>
29 #include <asm/psrcompat.h>
30 #ifdef CONFIG_KMOD
31 #include <linux/kmod.h>
32 #endif
34 /* #define SYSCALL_TRACING */
35 /* #define VERBOSE_SYSCALL_TRACING */
36 /* #define DEBUG_FPU */
38 #ifdef SYSCALL_TRACING
39 #ifdef VERBOSE_SYSCALL_TRACING
40 struct sdesc {
41 int scall_num;
42 char *name;
43 int num_args;
44 char arg_is_string[6];
45 } sdesc_entries[] = {
46 { 0, "setup", 0, },
47 { 1, "exit", 1, { 0, } },
48 { 2, "fork", 0, },
49 { 3, "read", 3, { 0, 0, 0, } },
50 { 4, "write", 3, { 0, 0, 0, } },
51 { 5, "open", 3, { 1, 0, 0, } },
52 { 6, "close", 1, { 0, } },
53 { 7, "wait4", 4, { 0, 0, 0, 0, } },
54 { 8, "creat", 2, { 1, 0, } },
55 { 9, "link", 2, { 1, 1, } },
56 { 10, "unlink", 1, { 1, } },
57 { 11, "execv", 2, { 1, 0, } },
58 { 12, "chdir", 1, { 1, } },
59 { 15, "chmod", 2, { 1, 0, } },
60 { 16, "chown", 3, { 1, 0, 0, } },
61 { 17, "brk", 1, { 0, } },
62 { 19, "lseek", 3, { 0, 0, 0, } },
63 { 27, "alarm", 1, { 0, } },
64 { 29, "pause", 0, },
65 { 33, "access", 2, { 1, 0, } },
66 { 36, "sync", 0, },
67 { 37, "kill", 2, { 0, 0, } },
68 { 38, "stat", 2, { 1, 0, } },
69 { 40, "lstat", 2, { 1, 0, } },
70 { 41, "dup", 1, { 0, } },
71 { 42, "pipd", 0, },
72 { 54, "ioctl", 3, { 0, 0, 0, } },
73 { 57, "symlink", 2, { 1, 1, } },
74 { 58, "readlink", 3, { 1, 0, 0, } },
75 { 59, "execve", 3, { 1, 0, 0, } },
76 { 60, "umask", 1, { 0, } },
77 { 62, "fstat", 2, { 0, 0, } },
78 { 64, "getpagesize", 0, },
79 { 71, "mmap", 6, { 0, 0, 0, 0, 0, 0, } },
80 { 73, "munmap", 2, { 0, 0, } },
81 { 74, "mprotect", 3, { 0, 0, 0, } },
82 { 83, "setitimer", 3, { 0, 0, 0, } },
83 { 90, "dup2", 2, { 0, 0, } },
84 { 92, "fcntl", 3, { 0, 0, 0, } },
85 { 93, "select", 5, { 0, 0, 0, 0, 0, } },
86 { 97, "socket", 3, { 0, 0, 0, } },
87 { 98, "connect", 3, { 0, 0, 0, } },
88 { 99, "accept", 3, { 0, 0, 0, } },
89 { 101, "send", 4, { 0, 0, 0, 0, } },
90 { 102, "recv", 4, { 0, 0, 0, 0, } },
91 { 104, "bind", 3, { 0, 0, 0, } },
92 { 105, "setsockopt", 5, { 0, 0, 0, 0, 0, } },
93 { 106, "listen", 2, { 0, 0, } },
94 { 120, "readv", 3, { 0, 0, 0, } },
95 { 121, "writev", 3, { 0, 0, 0, } },
96 { 123, "fchown", 3, { 0, 0, 0, } },
97 { 124, "fchmod", 2, { 0, 0, } },
98 { 128, "rename", 2, { 1, 1, } },
99 { 129, "truncate", 2, { 1, 0, } },
100 { 130, "ftruncate", 2, { 0, 0, } },
101 { 131, "flock", 2, { 0, 0, } },
102 { 136, "mkdir", 2, { 1, 0, } },
103 { 137, "rmdir", 1, { 1, } },
104 { 146, "killpg", 1, { 0, } },
105 { 157, "statfs", 2, { 1, 0, } },
106 { 158, "fstatfs", 2, { 0, 0, } },
107 { 159, "umount", 1, { 1, } },
108 { 167, "mount", 5, { 1, 1, 1, 0, 0, } },
109 { 174, "getdents", 3, { 0, 0, 0, } },
110 { 176, "fchdir", 2, { 0, 0, } },
111 { 198, "sigaction", 3, { 0, 0, 0, } },
112 { 201, "sigsuspend", 1, { 0, } },
113 { 206, "socketcall", 2, { 0, 0, } },
114 { 216, "sigreturn", 0, },
115 { 230, "newselect", 5, { 0, 0, 0, 0, 0, } },
116 { 236, "llseek", 5, { 0, 0, 0, 0, 0, } },
117 { 251, "sysctl", 1, { 0, } },
119 #define NUM_SDESC_ENTRIES (sizeof(sdesc_entries) / sizeof(sdesc_entries[0]))
120 #endif
122 #ifdef VERBOSE_SYSCALL_TRACING
123 static char scall_strbuf[512];
124 #endif
126 void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
128 #ifdef VERBOSE_SYSCALL_TRACING
129 struct sdesc *sdp;
130 int i;
131 #endif
133 #if 0
134 if (!current->pid) return;
135 #endif
136 printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
137 current->comm, current->pid, regs->tpc, (int)g1);
138 #ifdef VERBOSE_SYSCALL_TRACING
139 sdp = NULL;
140 for(i = 0; i < NUM_SDESC_ENTRIES; i++)
141 if(sdesc_entries[i].scall_num == g1) {
142 sdp = &sdesc_entries[i];
143 break;
145 if(sdp) {
146 printk("%s(", sdp->name);
147 for(i = 0; i < sdp->num_args; i++) {
148 if(i)
149 printk(",");
150 if(!sdp->arg_is_string[i]) {
151 if (current->thread.flags & SPARC_FLAG_32BIT)
152 printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]);
153 else
154 printk("%016lx", regs->u_regs[UREG_I0 + i]);
155 } else {
156 if (current->thread.flags & SPARC_FLAG_32BIT)
157 strncpy_from_user(scall_strbuf,
158 (char *)(regs->u_regs[UREG_I0 + i] & 0xffffffff),
159 512);
160 else
161 strncpy_from_user(scall_strbuf,
162 (char *)regs->u_regs[UREG_I0 + i],
163 512);
164 printk("%s", scall_strbuf);
167 printk(") ");
169 #endif
172 unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
174 #if 0
175 if (current->pid)
176 #endif
177 printk("ret[%016lx]\n", retval);
178 return retval;
180 #endif /* SYSCALL_TRACING */
182 #if 1
183 void rtrap_check(struct pt_regs *regs)
185 register unsigned long pgd_phys asm("o1");
186 register unsigned long pgd_cache asm("o2");
187 register unsigned long g1_or_g3 asm("o3");
188 register unsigned long g2 asm("o4");
189 unsigned long ctx;
191 #if 0
192 do {
193 unsigned long test;
194 __asm__ __volatile__("rdpr %%pstate, %0"
195 : "=r" (test));
196 if((test & PSTATE_MG) != 0 ||
197 (test & PSTATE_IE) == 0) {
198 printk("rtrap_check: Bogus pstate[%016lx]\n", test);
199 return;
201 } while(0);
202 #endif
204 __asm__ __volatile__("
205 rdpr %%pstate, %%o5
206 wrpr %%o5, %4, %%pstate
207 or %%g1, %%g3, %2
208 mov %%g2, %3
209 mov %%g7, %0
210 mov %5, %1
211 ldxa [%1] %6, %1
212 wrpr %%o5, 0x0, %%pstate"
213 : "=r" (pgd_phys), "=r" (pgd_cache),
214 "=r" (g1_or_g3), "=r" (g2)
215 : "i" (PSTATE_IE | PSTATE_MG), "i" (TSB_REG),
216 "i" (ASI_DMMU)
217 : "o5");
219 ctx = spitfire_get_secondary_context();
221 if((pgd_phys != __pa(current->mm->pgd)) ||
222 ((pgd_cache != 0) &&
223 (pgd_cache != pgd_val(current->mm->pgd[0])<<11UL)) ||
224 (g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) ||
225 #define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
226 #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
227 (g2 != (KERN_HIGHBITS | KERN_LOWBITS)) ||
228 #undef KERN_HIGHBITS
229 #undef KERN_LOWBITS
230 ((ctx != (current->mm->context & 0x3ff)) ||
231 (ctx == 0) ||
232 (CTX_HWBITS(current->mm->context) != ctx))) {
233 printk("SHIT[%s:%d]: "
234 "(PP[%016lx] CACH[%016lx] CTX[%lx] g1g3[%016lx] g2[%016lx]) ",
235 current->comm, current->pid,
236 pgd_phys, pgd_cache, ctx, g1_or_g3, g2);
237 printk("SHIT[%s:%d]: "
238 "[PP[%016lx] CACH[%016lx] CTX[%lx]] PC[%016lx:%016lx]\n",
239 current->comm, current->pid,
240 __pa(current->mm->pgd),
241 pgd_val(current->mm->pgd[0]),
242 current->mm->context & 0x3ff,
243 regs->tpc, regs->tnpc);
244 show_regs(regs);
245 #if 1
246 __sti();
247 while(1)
248 barrier();
249 #endif
252 #endif
254 void bad_trap (struct pt_regs *regs, long lvl)
256 siginfo_t info;
258 if (lvl < 0x100) {
259 char buffer[24];
261 sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl);
262 die_if_kernel (buffer, regs);
264 if (regs->tstate & TSTATE_PRIV)
265 die_if_kernel ("Kernel bad trap", regs);
266 info.si_signo = SIGILL;
267 info.si_errno = 0;
268 info.si_code = ILL_ILLTRP;
269 info.si_addr = (void *)regs->tpc;
270 info.si_trapno = lvl - 0x100;
271 force_sig_info(SIGILL, &info, current);
274 void bad_trap_tl1 (struct pt_regs *regs, long lvl)
276 char buffer[24];
278 sprintf (buffer, "Bad trap %lx at tl>0", lvl);
279 die_if_kernel (buffer, regs);
282 void instruction_access_exception (struct pt_regs *regs,
283 unsigned long sfsr, unsigned long sfar)
285 siginfo_t info;
287 if (regs->tstate & TSTATE_PRIV) {
288 #if 1
289 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
290 sfsr, sfar);
291 #endif
292 die_if_kernel("Iax", regs);
294 info.si_signo = SIGSEGV;
295 info.si_errno = 0;
296 info.si_code = SEGV_MAPERR;
297 info.si_addr = (void *)regs->tpc;
298 info.si_trapno = 0;
299 force_sig_info(SIGSEGV, &info, current);
302 void data_access_exception (struct pt_regs *regs,
303 unsigned long sfsr, unsigned long sfar)
305 siginfo_t info;
307 if (regs->tstate & TSTATE_PRIV) {
308 /* Test if this comes from uaccess places. */
309 unsigned long fixup, g2;
311 g2 = regs->u_regs[UREG_G2];
312 if ((fixup = search_exception_table (regs->tpc, &g2))) {
313 /* Ouch, somebody is trying ugly VM hole tricks on us... */
314 #ifdef DEBUG_EXCEPTIONS
315 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
316 printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
317 "g2<%016lx>\n", regs->tpc, fixup, g2);
318 #endif
319 regs->tpc = fixup;
320 regs->tnpc = regs->tpc + 4;
321 regs->u_regs[UREG_G2] = g2;
322 return;
324 /* Shit... */
325 #if 1
326 printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
327 sfsr, sfar);
328 #endif
329 die_if_kernel("Dax", regs);
331 #if 0
332 else
333 rtrap_check(regs);
334 #endif
335 info.si_signo = SIGSEGV;
336 info.si_errno = 0;
337 info.si_code = SEGV_MAPERR;
338 info.si_addr = (void *)sfar;
339 info.si_trapno = 0;
340 force_sig_info(SIGSEGV, &info, current);
343 #ifdef CONFIG_PCI
344 /* This is really pathetic... */
345 /* #define DEBUG_PCI_POKES */
346 extern volatile int pci_poke_in_progress;
347 extern volatile int pci_poke_faulted;
348 #endif
350 /* When access exceptions happen, we must do this. */
351 static __inline__ void clean_and_reenable_l1_caches(void)
353 unsigned long va;
355 /* Clean 'em. */
356 for(va = 0; va < (PAGE_SIZE << 1); va += 32) {
357 spitfire_put_icache_tag(va, 0x0);
358 spitfire_put_dcache_tag(va, 0x0);
361 /* Re-enable. */
362 __asm__ __volatile__("flush %%g6\n\t"
363 "membar #Sync\n\t"
364 "stxa %0, [%%g0] %1\n\t"
365 "membar #Sync"
366 : /* no outputs */
367 : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |
368 LSU_CONTROL_IM | LSU_CONTROL_DM),
369 "i" (ASI_LSU_CONTROL)
370 : "memory");
373 void do_iae(struct pt_regs *regs)
375 siginfo_t info;
377 clean_and_reenable_l1_caches();
379 info.si_signo = SIGBUS;
380 info.si_errno = 0;
381 info.si_code = BUS_OBJERR;
382 info.si_addr = (void *)0;
383 info.si_trapno = 0;
384 force_sig_info(SIGBUS, &info, current);
387 void do_dae(struct pt_regs *regs)
389 #ifdef CONFIG_PCI
390 if(pci_poke_in_progress) {
391 #ifdef DEBUG_PCI_POKES
392 prom_printf(" (POKE tpc[%016lx] tnpc[%016lx] ",
393 regs->tpc, regs->tnpc);
394 #endif
395 pci_poke_faulted = 1;
396 regs->tnpc = regs->tpc + 4;
399 #ifdef DEBUG_PCI_POKES
400 prom_printf("PCI) ");
401 /* prom_halt(); */
402 #endif
403 clean_and_reenable_l1_caches();
404 return;
406 #endif
407 do_iae(regs);
410 static char ecc_syndrome_table[] = {
411 0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,
412 0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,
413 0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,
414 0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,
415 0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,
416 0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,
417 0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,
418 0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,
419 0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,
420 0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,
421 0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,
422 0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
423 0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,
424 0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,
425 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,
426 0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
427 0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,
428 0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,
429 0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,
430 0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,
431 0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,
432 0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
433 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,
434 0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
435 0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,
436 0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,
437 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,
438 0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
439 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,
440 0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
441 0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,
442 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
445 /* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
446 * in the following format. The AFAR is left as is, with
447 * reserved bits cleared, and is a raw 40-bit physical
448 * address.
450 #define CE_STATUS_UDBH_UE (1UL << (43 + 9))
451 #define CE_STATUS_UDBH_CE (1UL << (43 + 8))
452 #define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
453 #define CE_STATUS_UDBH_SHIFT 43
454 #define CE_STATUS_UDBL_UE (1UL << (33 + 9))
455 #define CE_STATUS_UDBL_CE (1UL << (33 + 8))
456 #define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
457 #define CE_STATUS_UDBL_SHIFT 33
458 #define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
459 #define CE_STATUS_AFSR_ME (1UL << 32)
460 #define CE_STATUS_AFSR_PRIV (1UL << 31)
461 #define CE_STATUS_AFSR_ISAP (1UL << 30)
462 #define CE_STATUS_AFSR_ETP (1UL << 29)
463 #define CE_STATUS_AFSR_IVUE (1UL << 28)
464 #define CE_STATUS_AFSR_TO (1UL << 27)
465 #define CE_STATUS_AFSR_BERR (1UL << 26)
466 #define CE_STATUS_AFSR_LDP (1UL << 25)
467 #define CE_STATUS_AFSR_CP (1UL << 24)
468 #define CE_STATUS_AFSR_WP (1UL << 23)
469 #define CE_STATUS_AFSR_EDP (1UL << 22)
470 #define CE_STATUS_AFSR_UE (1UL << 21)
471 #define CE_STATUS_AFSR_CE (1UL << 20)
472 #define CE_STATUS_AFSR_ETS (0xfUL << 16)
473 #define CE_STATUS_AFSR_ETS_SHIFT 16
474 #define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
475 #define CE_STATUS_AFSR_PSYND_SHIFT 0
477 /* Layout of Ecache TAG Parity Syndrome of AFSR */
478 #define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
479 #define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
480 #define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
481 #define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
483 static char *syndrome_unknown = "<Unknown>";
485 asmlinkage void cee_log(unsigned long ce_status,
486 unsigned long afar,
487 struct pt_regs *regs)
489 char memmod_str[64];
490 char *p;
491 unsigned short scode, udb_reg;
493 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
494 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",
495 smp_processor_id(),
496 (ce_status & CE_STATUS_AFSR_MASK),
497 afar,
498 ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
499 ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
501 udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
502 if (udb_reg & (1 << 8)) {
503 scode = ecc_syndrome_table[udb_reg & 0xff];
504 if (prom_getunumber(scode, afar,
505 memmod_str, sizeof(memmod_str)) == -1)
506 p = syndrome_unknown;
507 else
508 p = memmod_str;
509 printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "
510 "Memory Module \"%s\"\n",
511 smp_processor_id(), scode, p);
514 udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);
515 if (udb_reg & (1 << 8)) {
516 scode = ecc_syndrome_table[udb_reg & 0xff];
517 if (prom_getunumber(scode, afar,
518 memmod_str, sizeof(memmod_str)) == -1)
519 p = syndrome_unknown;
520 else
521 p = memmod_str;
522 printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "
523 "Memory Module \"%s\"\n",
524 smp_processor_id(), scode, p);
528 void do_fpe_common(struct pt_regs *regs)
530 if(regs->tstate & TSTATE_PRIV) {
531 regs->tpc = regs->tnpc;
532 regs->tnpc += 4;
533 } else {
534 unsigned long fsr = current->thread.xfsr[0];
535 siginfo_t info;
537 info.si_signo = SIGFPE;
538 info.si_errno = 0;
539 info.si_addr = (void *)regs->tpc;
540 info.si_trapno = 0;
541 info.si_code = __SI_FAULT;
542 if ((fsr & 0x1c000) == (1 << 14)) {
543 if (fsr & 0x10)
544 info.si_code = FPE_FLTINV;
545 else if (fsr & 0x08)
546 info.si_code = FPE_FLTOVF;
547 else if (fsr & 0x04)
548 info.si_code = FPE_FLTUND;
549 else if (fsr & 0x02)
550 info.si_code = FPE_FLTDIV;
551 else if (fsr & 0x01)
552 info.si_code = FPE_FLTRES;
554 force_sig_info(SIGFPE, &info, current);
558 void do_fpieee(struct pt_regs *regs)
560 #ifdef DEBUG_FPU
561 printk("fpieee %016lx\n", current->thread.xfsr[0]);
562 #endif
563 do_fpe_common(regs);
566 extern int do_mathemu(struct pt_regs *, struct fpustate *);
568 void do_fpother(struct pt_regs *regs)
570 struct fpustate *f = FPUSTATE;
571 int ret = 0;
573 switch ((current->thread.xfsr[0] & 0x1c000)) {
574 case (2 << 14): /* unfinished_FPop */
575 case (3 << 14): /* unimplemented_FPop */
576 ret = do_mathemu(regs, f);
577 break;
579 if (ret) return;
580 #ifdef DEBUG_FPU
581 printk("fpother %016lx\n", current->thread.xfsr[0]);
582 #endif
583 do_fpe_common(regs);
586 void do_tof(struct pt_regs *regs)
588 siginfo_t info;
590 if(regs->tstate & TSTATE_PRIV)
591 die_if_kernel("Penguin overflow trap from kernel mode", regs);
592 info.si_signo = SIGEMT;
593 info.si_errno = 0;
594 info.si_code = EMT_TAGOVF;
595 info.si_addr = (void *)regs->tpc;
596 info.si_trapno = 0;
597 force_sig_info(SIGEMT, &info, current);
600 void do_div0(struct pt_regs *regs)
602 siginfo_t info;
604 info.si_signo = SIGFPE;
605 info.si_errno = 0;
606 info.si_code = FPE_INTDIV;
607 info.si_addr = (void *)regs->tpc;
608 info.si_trapno = 0;
609 force_sig_info(SIGFPE, &info, current);
612 void instruction_dump (unsigned int *pc)
614 int i;
616 if((((unsigned long) pc) & 3))
617 return;
619 printk("Instruction DUMP:");
620 for(i = -3; i < 6; i++)
621 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
622 printk("\n");
625 void user_instruction_dump (unsigned int *pc)
627 int i;
628 unsigned int buf[9];
630 if((((unsigned long) pc) & 3))
631 return;
633 if(copy_from_user(buf, pc - 3, sizeof(buf)))
634 return;
636 printk("Instruction DUMP:");
637 for(i = 0; i < 9; i++)
638 printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
639 printk("\n");
642 void die_if_kernel(char *str, struct pt_regs *regs)
644 extern void __show_regs(struct pt_regs * regs);
645 extern void smp_report_regs(void);
646 int count = 0;
647 struct reg_window *lastrw;
649 /* Amuse the user. */
650 printk(
651 " \\|/ ____ \\|/\n"
652 " \"@'/ .. \\`@\"\n"
653 " /_| \\__/ |_\\\n"
654 " \\__U_/\n");
656 printk("%s(%d): %s\n", current->comm, current->pid, str);
657 __asm__ __volatile__("flushw");
658 __show_regs(regs);
659 if(regs->tstate & TSTATE_PRIV) {
660 struct reg_window *rw = (struct reg_window *)
661 (regs->u_regs[UREG_FP] + STACK_BIAS);
663 /* Stop the back trace when we hit userland or we
664 * find some badly aligned kernel stack.
666 lastrw = (struct reg_window *)current;
667 while(rw &&
668 count++ < 30 &&
669 rw >= lastrw &&
670 (char *) rw < ((char *) current)
671 + sizeof (union task_union) &&
672 !(((unsigned long) rw) & 0x7)) {
673 printk("Caller[%016lx]\n", rw->ins[7]);
674 lastrw = rw;
675 rw = (struct reg_window *)
676 (rw->ins[6] + STACK_BIAS);
678 instruction_dump ((unsigned int *) regs->tpc);
679 } else
680 user_instruction_dump ((unsigned int *) regs->tpc);
681 #ifdef CONFIG_SMP
682 smp_report_regs();
683 #endif
685 if(regs->tstate & TSTATE_PRIV)
686 do_exit(SIGKILL);
687 do_exit(SIGSEGV);
690 extern int handle_popc(u32 insn, struct pt_regs *regs);
691 extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
693 void do_illegal_instruction(struct pt_regs *regs)
695 unsigned long pc = regs->tpc;
696 unsigned long tstate = regs->tstate;
697 u32 insn;
698 siginfo_t info;
700 if(tstate & TSTATE_PRIV)
701 die_if_kernel("Kernel illegal instruction", regs);
702 if(current->thread.flags & SPARC_FLAG_32BIT)
703 pc = (u32)pc;
704 if (get_user(insn, (u32 *)pc) != -EFAULT) {
705 if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
706 if (handle_popc(insn, regs))
707 return;
708 } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
709 if (handle_ldf_stq(insn, regs))
710 return;
713 info.si_signo = SIGILL;
714 info.si_errno = 0;
715 info.si_code = ILL_ILLOPC;
716 info.si_addr = (void *)pc;
717 info.si_trapno = 0;
718 force_sig_info(SIGILL, &info, current);
721 void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
723 siginfo_t info;
725 if(regs->tstate & TSTATE_PRIV) {
726 extern void kernel_unaligned_trap(struct pt_regs *regs,
727 unsigned int insn,
728 unsigned long sfar, unsigned long sfsr);
730 return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr);
732 info.si_signo = SIGBUS;
733 info.si_errno = 0;
734 info.si_code = BUS_ADRALN;
735 info.si_addr = (void *)sfar;
736 info.si_trapno = 0;
737 force_sig_info(SIGBUS, &info, current);
740 void do_privop(struct pt_regs *regs)
742 siginfo_t info;
744 info.si_signo = SIGILL;
745 info.si_errno = 0;
746 info.si_code = ILL_PRVOPC;
747 info.si_addr = (void *)regs->tpc;
748 info.si_trapno = 0;
749 force_sig_info(SIGILL, &info, current);
752 void do_privact(struct pt_regs *regs)
754 do_privop(regs);
757 /* Trap level 1 stuff or other traps we should never see... */
758 void do_cee(struct pt_regs *regs)
760 die_if_kernel("TL0: Cache Error Exception", regs);
763 void do_cee_tl1(struct pt_regs *regs)
765 die_if_kernel("TL1: Cache Error Exception", regs);
768 void do_dae_tl1(struct pt_regs *regs)
770 die_if_kernel("TL1: Data Access Exception", regs);
773 void do_iae_tl1(struct pt_regs *regs)
775 die_if_kernel("TL1: Instruction Access Exception", regs);
778 void do_div0_tl1(struct pt_regs *regs)
780 die_if_kernel("TL1: DIV0 Exception", regs);
783 void do_fpdis_tl1(struct pt_regs *regs)
785 die_if_kernel("TL1: FPU Disabled", regs);
788 void do_fpieee_tl1(struct pt_regs *regs)
790 die_if_kernel("TL1: FPU IEEE Exception", regs);
793 void do_fpother_tl1(struct pt_regs *regs)
795 die_if_kernel("TL1: FPU Other Exception", regs);
798 void do_ill_tl1(struct pt_regs *regs)
800 die_if_kernel("TL1: Illegal Instruction Exception", regs);
803 void do_irq_tl1(struct pt_regs *regs)
805 die_if_kernel("TL1: IRQ Exception", regs);
808 void do_lddfmna_tl1(struct pt_regs *regs)
810 die_if_kernel("TL1: LDDF Exception", regs);
813 void do_stdfmna_tl1(struct pt_regs *regs)
815 die_if_kernel("TL1: STDF Exception", regs);
818 void do_paw(struct pt_regs *regs)
820 die_if_kernel("TL0: Phys Watchpoint Exception", regs);
823 void do_paw_tl1(struct pt_regs *regs)
825 die_if_kernel("TL1: Phys Watchpoint Exception", regs);
828 void do_vaw(struct pt_regs *regs)
830 die_if_kernel("TL0: Virt Watchpoint Exception", regs);
833 void do_vaw_tl1(struct pt_regs *regs)
835 die_if_kernel("TL1: Virt Watchpoint Exception", regs);
838 void do_tof_tl1(struct pt_regs *regs)
840 die_if_kernel("TL1: Tag Overflow Exception", regs);
843 #ifdef CONFIG_EC_FLUSH_TRAP
844 void cache_flush_trap(struct pt_regs *regs)
846 #ifndef CONFIG_SMP
847 unsigned node = linux_cpus[get_cpuid()].prom_node;
848 #else
849 #error cache_flush_trap not supported on sparc64/SMP yet
850 #endif
852 #if 0
853 /* Broken */
854 int size = prom_getintdefault(node, "ecache-size", 512*1024);
855 int i, j;
856 unsigned long addr;
857 struct page *page, *end;
859 regs->tpc = regs->tnpc;
860 regs->tnpc = regs->tnpc + 4;
861 if (!capable(CAP_SYS_ADMIN)) return;
862 size >>= PAGE_SHIFT;
863 addr = PAGE_OFFSET - PAGE_SIZE;
864 page = mem_map - 1;
865 end = mem_map + max_mapnr;
866 for (i = 0; i < size; i++) {
867 do {
868 addr += PAGE_SIZE;
869 page++;
870 if (page >= end)
871 return;
872 } while (!PageReserved(page));
873 /* E-Cache line size is 64B. Let us pollute it :)) */
874 for (j = 0; j < PAGE_SIZE; j += 64)
875 __asm__ __volatile__ ("ldx [%0 + %1], %%g1" : : "r" (j), "r" (addr) : "g1");
877 #endif
879 #endif
881 void do_getpsr(struct pt_regs *regs)
883 regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
884 regs->tpc = regs->tnpc;
885 regs->tnpc += 4;
888 void trap_init(void)
890 /* Attach to the address space of init_task. */
891 atomic_inc(&init_mm.mm_count);
892 current->active_mm = &init_mm;
894 /* NOTE: Other cpus have this done as they are started
895 * up on SMP.