Import 2.3.18pre1
[davej-history.git] / arch / sparc64 / kernel / traps.c
blobf4f2287df7498f31838bb8317557db104c6577f6
1 /* $Id: traps.c,v 1.62 1999/08/31 19:25:35 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 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
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 #ifdef CONFIG_KMOD
30 #include <linux/kmod.h>
31 #endif
33 /* #define SYSCALL_TRACING */
34 /* #define VERBOSE_SYSCALL_TRACING */
35 /* #define DEBUG_FPU */
37 #ifdef SYSCALL_TRACING
38 #ifdef VERBOSE_SYSCALL_TRACING
39 struct sdesc {
40 int scall_num;
41 char *name;
42 int num_args;
43 char arg_is_string[6];
44 } sdesc_entries[] = {
45 { 0, "setup", 0, },
46 { 1, "exit", 1, { 0, } },
47 { 2, "fork", 0, },
48 { 3, "read", 3, { 0, 0, 0, } },
49 { 4, "write", 3, { 0, 0, 0, } },
50 { 5, "open", 3, { 1, 0, 0, } },
51 { 6, "close", 1, { 0, } },
52 { 7, "wait4", 4, { 0, 0, 0, 0, } },
53 { 8, "creat", 2, { 1, 0, } },
54 { 9, "link", 2, { 1, 1, } },
55 { 10, "unlink", 1, { 1, } },
56 { 11, "execv", 2, { 1, 0, } },
57 { 12, "chdir", 1, { 1, } },
58 { 15, "chmod", 2, { 1, 0, } },
59 { 16, "chown", 3, { 1, 0, 0, } },
60 { 17, "brk", 1, { 0, } },
61 { 19, "lseek", 3, { 0, 0, 0, } },
62 { 27, "alarm", 1, { 0, } },
63 { 29, "pause", 0, },
64 { 33, "access", 2, { 1, 0, } },
65 { 36, "sync", 0, },
66 { 37, "kill", 2, { 0, 0, } },
67 { 38, "stat", 2, { 1, 0, } },
68 { 40, "lstat", 2, { 1, 0, } },
69 { 41, "dup", 1, { 0, } },
70 { 42, "pipd", 0, },
71 { 54, "ioctl", 3, { 0, 0, 0, } },
72 { 57, "symlink", 2, { 1, 1, } },
73 { 58, "readlink", 3, { 1, 0, 0, } },
74 { 59, "execve", 3, { 1, 0, 0, } },
75 { 60, "umask", 1, { 0, } },
76 { 62, "fstat", 2, { 0, 0, } },
77 { 64, "getpagesize", 0, },
78 { 71, "mmap", 6, { 0, 0, 0, 0, 0, 0, } },
79 { 73, "munmap", 2, { 0, 0, } },
80 { 74, "mprotect", 3, { 0, 0, 0, } },
81 { 83, "setitimer", 3, { 0, 0, 0, } },
82 { 90, "dup2", 2, { 0, 0, } },
83 { 92, "fcntl", 3, { 0, 0, 0, } },
84 { 93, "select", 5, { 0, 0, 0, 0, 0, } },
85 { 97, "socket", 3, { 0, 0, 0, } },
86 { 98, "connect", 3, { 0, 0, 0, } },
87 { 99, "accept", 3, { 0, 0, 0, } },
88 { 101, "send", 4, { 0, 0, 0, 0, } },
89 { 102, "recv", 4, { 0, 0, 0, 0, } },
90 { 104, "bind", 3, { 0, 0, 0, } },
91 { 105, "setsockopt", 5, { 0, 0, 0, 0, 0, } },
92 { 106, "listen", 2, { 0, 0, } },
93 { 120, "readv", 3, { 0, 0, 0, } },
94 { 121, "writev", 3, { 0, 0, 0, } },
95 { 123, "fchown", 3, { 0, 0, 0, } },
96 { 124, "fchmod", 2, { 0, 0, } },
97 { 128, "rename", 2, { 1, 1, } },
98 { 129, "truncate", 2, { 1, 0, } },
99 { 130, "ftruncate", 2, { 0, 0, } },
100 { 131, "flock", 2, { 0, 0, } },
101 { 136, "mkdir", 2, { 1, 0, } },
102 { 137, "rmdir", 1, { 1, } },
103 { 146, "killpg", 1, { 0, } },
104 { 157, "statfs", 2, { 1, 0, } },
105 { 158, "fstatfs", 2, { 0, 0, } },
106 { 159, "umount", 1, { 1, } },
107 { 167, "mount", 5, { 1, 1, 1, 0, 0, } },
108 { 174, "getdents", 3, { 0, 0, 0, } },
109 { 176, "fchdir", 2, { 0, 0, } },
110 { 198, "sigaction", 3, { 0, 0, 0, } },
111 { 201, "sigsuspend", 1, { 0, } },
112 { 206, "socketcall", 2, { 0, 0, } },
113 { 216, "sigreturn", 0, },
114 { 230, "newselect", 5, { 0, 0, 0, 0, 0, } },
115 { 236, "llseek", 5, { 0, 0, 0, 0, 0, } },
116 { 251, "sysctl", 1, { 0, } },
118 #define NUM_SDESC_ENTRIES (sizeof(sdesc_entries) / sizeof(sdesc_entries[0]))
119 #endif
121 #ifdef VERBOSE_SYSCALL_TRACING
122 static char scall_strbuf[512];
123 #endif
125 void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
127 #ifdef VERBOSE_SYSCALL_TRACING
128 struct sdesc *sdp;
129 int i;
130 #endif
132 #if 0
133 if (!current->pid) return;
134 #endif
135 printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
136 current->comm, current->pid, regs->tpc, (int)g1);
137 #ifdef VERBOSE_SYSCALL_TRACING
138 sdp = NULL;
139 for(i = 0; i < NUM_SDESC_ENTRIES; i++)
140 if(sdesc_entries[i].scall_num == g1) {
141 sdp = &sdesc_entries[i];
142 break;
144 if(sdp) {
145 printk("%s(", sdp->name);
146 for(i = 0; i < sdp->num_args; i++) {
147 if(i)
148 printk(",");
149 if(!sdp->arg_is_string[i]) {
150 if (current->thread.flags & SPARC_FLAG_32BIT)
151 printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]);
152 else
153 printk("%016lx", regs->u_regs[UREG_I0 + i]);
154 } else {
155 if (current->thread.flags & SPARC_FLAG_32BIT)
156 strncpy_from_user(scall_strbuf,
157 (char *)(regs->u_regs[UREG_I0 + i] & 0xffffffff),
158 512);
159 else
160 strncpy_from_user(scall_strbuf,
161 (char *)regs->u_regs[UREG_I0 + i],
162 512);
163 printk("%s", scall_strbuf);
166 printk(") ");
168 #endif
171 unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
173 #if 0
174 if (current->pid)
175 #endif
176 printk("ret[%016lx]\n", retval);
177 return retval;
179 #endif /* SYSCALL_TRACING */
181 #if 1
182 void rtrap_check(struct pt_regs *regs)
184 register unsigned long pgd_phys asm("o1");
185 register unsigned long pgd_cache asm("o2");
186 register unsigned long g1_or_g3 asm("o3");
187 register unsigned long g2 asm("o4");
188 unsigned long ctx;
190 #if 0
191 do {
192 unsigned long test;
193 __asm__ __volatile__("rdpr %%pstate, %0"
194 : "=r" (test));
195 if((test & PSTATE_MG) != 0 ||
196 (test & PSTATE_IE) == 0) {
197 printk("rtrap_check: Bogus pstate[%016lx]\n", test);
198 return;
200 } while(0);
201 #endif
203 __asm__ __volatile__("
204 rdpr %%pstate, %%o5
205 wrpr %%o5, %4, %%pstate
206 or %%g1, %%g3, %2
207 mov %%g2, %3
208 mov %%g7, %0
209 mov %5, %1
210 ldxa [%1] %6, %1
211 wrpr %%o5, 0x0, %%pstate"
212 : "=r" (pgd_phys), "=r" (pgd_cache),
213 "=r" (g1_or_g3), "=r" (g2)
214 : "i" (PSTATE_IE | PSTATE_MG), "i" (TSB_REG),
215 "i" (ASI_DMMU)
216 : "o5");
218 ctx = spitfire_get_secondary_context();
220 if((pgd_phys != __pa(current->mm->pgd)) ||
221 ((pgd_cache != 0) &&
222 (pgd_cache != pgd_val(current->mm->pgd[0])<<11UL)) ||
223 (g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) ||
224 #define KERN_HIGHBITS ((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
225 #define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
226 (g2 != (KERN_HIGHBITS | KERN_LOWBITS)) ||
227 #undef KERN_HIGHBITS
228 #undef KERN_LOWBITS
229 ((ctx != (current->mm->context & 0x3ff)) ||
230 (ctx == 0) ||
231 (CTX_HWBITS(current->mm->context) != ctx))) {
232 printk("SHIT[%s:%d]: "
233 "(PP[%016lx] CACH[%016lx] CTX[%lx] g1g3[%016lx] g2[%016lx]) ",
234 current->comm, current->pid,
235 pgd_phys, pgd_cache, ctx, g1_or_g3, g2);
236 printk("SHIT[%s:%d]: "
237 "[PP[%016lx] CACH[%016lx] CTX[%lx]] PC[%016lx:%016lx]\n",
238 current->comm, current->pid,
239 __pa(current->mm->pgd),
240 pgd_val(current->mm->pgd[0]),
241 current->mm->context & 0x3ff,
242 regs->tpc, regs->tnpc);
243 show_regs(regs);
244 #if 1
245 __sti();
246 while(1)
247 barrier();
248 #endif
251 #endif
253 void bad_trap (struct pt_regs *regs, long lvl)
255 lock_kernel ();
256 if (lvl < 0x100) {
257 char buffer[24];
259 sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl);
260 die_if_kernel (buffer, regs);
262 if (regs->tstate & TSTATE_PRIV)
263 die_if_kernel ("Kernel bad trap", regs);
264 current->thread.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
265 current->thread.sig_address = regs->tpc;
266 force_sig(SIGILL, current);
267 unlock_kernel ();
270 void bad_trap_tl1 (struct pt_regs *regs, long lvl)
272 char buffer[24];
274 lock_kernel();
275 sprintf (buffer, "Bad trap %lx at tl>0", lvl);
276 die_if_kernel (buffer, regs);
277 unlock_kernel();
280 void instruction_access_exception (struct pt_regs *regs,
281 unsigned long sfsr, unsigned long sfar)
283 lock_kernel();
284 if (regs->tstate & TSTATE_PRIV) {
285 #if 1
286 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
287 sfsr, sfar);
288 #endif
289 die_if_kernel("Iax", regs);
291 current->thread.sig_desc = SUBSIG_ILLINST;
292 current->thread.sig_address = regs->tpc;
293 force_sig(SIGILL, current);
294 unlock_kernel();
297 void data_access_exception (struct pt_regs *regs,
298 unsigned long sfsr, unsigned long sfar)
300 if (regs->tstate & TSTATE_PRIV) {
301 /* Test if this comes from uaccess places. */
302 unsigned long fixup, g2;
304 g2 = regs->u_regs[UREG_G2];
305 if ((fixup = search_exception_table (regs->tpc, &g2))) {
306 /* Ouch, somebody is trying ugly VM hole tricks on us... */
307 #ifdef DEBUG_EXCEPTIONS
308 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
309 printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
310 "g2<%016lx>\n", regs->tpc, fixup, g2);
311 #endif
312 regs->tpc = fixup;
313 regs->tnpc = regs->tpc + 4;
314 regs->u_regs[UREG_G2] = g2;
315 return;
317 /* Shit... */
318 #if 1
319 printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
320 sfsr, sfar);
321 #endif
322 die_if_kernel("Dax", regs);
324 #if 0
325 else
326 rtrap_check(regs);
327 #endif
328 lock_kernel();
329 force_sig(SIGSEGV, current);
330 unlock_kernel();
333 #ifdef CONFIG_PCI
334 /* This is really pathetic... */
335 /* #define DEBUG_PCI_POKES */
336 extern volatile int pci_poke_in_progress;
337 extern volatile int pci_poke_faulted;
338 #endif
340 /* When access exceptions happen, we must do this. */
341 static __inline__ void clean_and_reenable_l1_caches(void)
343 unsigned long va;
345 /* Clean 'em. */
346 for(va = 0; va < (PAGE_SIZE << 1); va += 32) {
347 spitfire_put_icache_tag(va, 0x0);
348 spitfire_put_dcache_tag(va, 0x0);
351 /* Re-enable. */
352 __asm__ __volatile__("flush %%g6\n\t"
353 "membar #Sync\n\t"
354 "stxa %0, [%%g0] %1\n\t"
355 "membar #Sync"
356 : /* no outputs */
357 : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |
358 LSU_CONTROL_IM | LSU_CONTROL_DM),
359 "i" (ASI_LSU_CONTROL)
360 : "memory");
363 void do_dae(struct pt_regs *regs)
365 #ifdef CONFIG_PCI
366 if(pci_poke_in_progress) {
367 #ifdef DEBUG_PCI_POKES
368 prom_printf(" (POKE tpc[%016lx] tnpc[%016lx] ",
369 regs->tpc, regs->tnpc);
370 #endif
371 pci_poke_faulted = 1;
372 regs->tnpc = regs->tpc + 4;
375 #ifdef DEBUG_PCI_POKES
376 prom_printf("PCI) ");
377 /* prom_halt(); */
378 #endif
379 clean_and_reenable_l1_caches();
380 return;
382 #endif
383 clean_and_reenable_l1_caches();
384 lock_kernel();
385 force_sig(SIGSEGV, current);
386 unlock_kernel();
389 void do_iae(struct pt_regs *regs)
391 clean_and_reenable_l1_caches();
393 lock_kernel();
394 force_sig(SIGSEGV, current);
395 unlock_kernel();
398 static char ecc_syndrome_table[] = {
399 0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,
400 0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,
401 0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,
402 0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,
403 0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,
404 0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,
405 0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,
406 0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,
407 0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,
408 0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,
409 0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,
410 0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
411 0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,
412 0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,
413 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,
414 0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
415 0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,
416 0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,
417 0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,
418 0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,
419 0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,
420 0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
421 0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,
422 0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
423 0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,
424 0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,
425 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,
426 0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
427 0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,
428 0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
429 0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,
430 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
433 /* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
434 * in the following format. The AFAR is left as is, with
435 * reserved bits cleared, and is a raw 40-bit physical
436 * address.
438 #define CE_STATUS_UDBH_UE (1UL << (43 + 9))
439 #define CE_STATUS_UDBH_CE (1UL << (43 + 8))
440 #define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
441 #define CE_STATUS_UDBH_SHIFT 43
442 #define CE_STATUS_UDBL_UE (1UL << (33 + 9))
443 #define CE_STATUS_UDBL_CE (1UL << (33 + 8))
444 #define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
445 #define CE_STATUS_UDBL_SHIFT 33
446 #define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
447 #define CE_STATUS_AFSR_ME (1UL << 32)
448 #define CE_STATUS_AFSR_PRIV (1UL << 31)
449 #define CE_STATUS_AFSR_ISAP (1UL << 30)
450 #define CE_STATUS_AFSR_ETP (1UL << 29)
451 #define CE_STATUS_AFSR_IVUE (1UL << 28)
452 #define CE_STATUS_AFSR_TO (1UL << 27)
453 #define CE_STATUS_AFSR_BERR (1UL << 26)
454 #define CE_STATUS_AFSR_LDP (1UL << 25)
455 #define CE_STATUS_AFSR_CP (1UL << 24)
456 #define CE_STATUS_AFSR_WP (1UL << 23)
457 #define CE_STATUS_AFSR_EDP (1UL << 22)
458 #define CE_STATUS_AFSR_UE (1UL << 21)
459 #define CE_STATUS_AFSR_CE (1UL << 20)
460 #define CE_STATUS_AFSR_ETS (0xfUL << 16)
461 #define CE_STATUS_AFSR_ETS_SHIFT 16
462 #define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
463 #define CE_STATUS_AFSR_PSYND_SHIFT 0
465 /* Layout of Ecache TAG Parity Syndrome of AFSR */
466 #define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
467 #define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
468 #define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
469 #define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
471 static char *syndrome_unknown = "<Unknown>";
473 asmlinkage void cee_log(unsigned long ce_status,
474 unsigned long afar,
475 struct pt_regs *regs)
477 char memmod_str[64];
478 char *p;
479 unsigned short scode, udb_reg;
481 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
482 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",
483 smp_processor_id(),
484 (ce_status & CE_STATUS_AFSR_MASK),
485 afar,
486 ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
487 ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
489 udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
490 if (udb_reg & (1 << 8)) {
491 scode = ecc_syndrome_table[udb_reg & 0xff];
492 if (prom_getunumber(scode, afar,
493 memmod_str, sizeof(memmod_str)) == -1)
494 p = syndrome_unknown;
495 else
496 p = memmod_str;
497 printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "
498 "Memory Module \"%s\"\n",
499 smp_processor_id(), scode, p);
502 udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);
503 if (udb_reg & (1 << 8)) {
504 scode = ecc_syndrome_table[udb_reg & 0xff];
505 if (prom_getunumber(scode, afar,
506 memmod_str, sizeof(memmod_str)) == -1)
507 p = syndrome_unknown;
508 else
509 p = memmod_str;
510 printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "
511 "Memory Module \"%s\"\n",
512 smp_processor_id(), scode, p);
516 void do_fpe_common(struct pt_regs *regs)
518 if(regs->tstate & TSTATE_PRIV) {
519 regs->tpc = regs->tnpc;
520 regs->tnpc += 4;
521 } else {
522 current->thread.sig_address = regs->tpc;
523 current->thread.sig_desc = SUBSIG_FPERROR;
524 send_sig(SIGFPE, current, 1);
528 void do_fpieee(struct pt_regs *regs)
530 #ifdef DEBUG_FPU
531 printk("fpieee %016lx\n", current->thread.xfsr[0]);
532 #endif
533 do_fpe_common(regs);
536 extern int do_mathemu(struct pt_regs *, struct fpustate *);
538 void do_fpother(struct pt_regs *regs)
540 struct fpustate *f = FPUSTATE;
541 int ret = 0;
543 switch ((current->thread.xfsr[0] & 0x1c000)) {
544 case (2 << 14): /* unfinished_FPop */
545 case (3 << 14): /* unimplemented_FPop */
546 ret = do_mathemu(regs, f);
547 break;
549 if (ret) return;
550 #ifdef DEBUG_FPU
551 printk("fpother %016lx\n", current->thread.xfsr[0]);
552 #endif
553 do_fpe_common(regs);
556 void do_tof(struct pt_regs *regs)
558 if(regs->tstate & TSTATE_PRIV)
559 die_if_kernel("Penguin overflow trap from kernel mode", regs);
560 current->thread.sig_address = regs->tpc;
561 current->thread.sig_desc = SUBSIG_TAG; /* as good as any */
562 send_sig(SIGEMT, current, 1);
565 void do_div0(struct pt_regs *regs)
567 send_sig(SIGILL, current, 1);
570 void instruction_dump (unsigned int *pc)
572 int i;
574 if((((unsigned long) pc) & 3))
575 return;
577 printk("Instruction DUMP:");
578 for(i = -3; i < 6; i++)
579 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
580 printk("\n");
583 void user_instruction_dump (unsigned int *pc)
585 int i;
586 unsigned int buf[9];
588 if((((unsigned long) pc) & 3))
589 return;
591 if(copy_from_user(buf, pc - 3, sizeof(buf)))
592 return;
594 printk("Instruction DUMP:");
595 for(i = 0; i < 9; i++)
596 printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
597 printk("\n");
600 void die_if_kernel(char *str, struct pt_regs *regs)
602 extern void __show_regs(struct pt_regs * regs);
603 extern void smp_report_regs(void);
604 int count = 0;
605 struct reg_window *lastrw;
607 /* Amuse the user. */
608 printk(
609 " \\|/ ____ \\|/\n"
610 " \"@'/ .. \\`@\"\n"
611 " /_| \\__/ |_\\\n"
612 " \\__U_/\n");
614 printk("%s(%d): %s\n", current->comm, current->pid, str);
615 __asm__ __volatile__("flushw");
616 __show_regs(regs);
617 if(regs->tstate & TSTATE_PRIV) {
618 struct reg_window *rw = (struct reg_window *)
619 (regs->u_regs[UREG_FP] + STACK_BIAS);
621 /* Stop the back trace when we hit userland or we
622 * find some badly aligned kernel stack.
624 lastrw = (struct reg_window *)current;
625 while(rw &&
626 count++ < 30 &&
627 rw >= lastrw &&
628 (char *) rw < ((char *) current)
629 + sizeof (union task_union) &&
630 !(((unsigned long) rw) & 0x7)) {
631 printk("Caller[%016lx]\n", rw->ins[7]);
632 lastrw = rw;
633 rw = (struct reg_window *)
634 (rw->ins[6] + STACK_BIAS);
636 instruction_dump ((unsigned int *) regs->tpc);
637 } else
638 user_instruction_dump ((unsigned int *) regs->tpc);
639 #ifdef __SMP__
640 smp_report_regs();
641 #endif
643 lock_kernel(); /* Or else! */
644 if(regs->tstate & TSTATE_PRIV)
645 do_exit(SIGKILL);
646 do_exit(SIGSEGV);
649 extern int handle_popc(u32 insn, struct pt_regs *regs);
650 extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
652 void do_illegal_instruction(struct pt_regs *regs)
654 unsigned long pc = regs->tpc;
655 unsigned long tstate = regs->tstate;
656 u32 insn;
658 if(tstate & TSTATE_PRIV)
659 die_if_kernel("Kernel illegal instruction", regs);
660 if(current->thread.flags & SPARC_FLAG_32BIT)
661 pc = (u32)pc;
662 if (get_user(insn, (u32 *)pc) != -EFAULT) {
663 if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
664 if (handle_popc(insn, regs))
665 return;
666 } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
667 if (handle_ldf_stq(insn, regs))
668 return;
671 current->thread.sig_address = pc;
672 current->thread.sig_desc = SUBSIG_ILLINST;
673 send_sig(SIGILL, current, 1);
676 void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
678 if(regs->tstate & TSTATE_PRIV) {
679 extern void kernel_unaligned_trap(struct pt_regs *regs,
680 unsigned int insn,
681 unsigned long sfar, unsigned long sfsr);
683 return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr);
684 } else {
685 current->thread.sig_address = regs->tpc;
686 current->thread.sig_desc = SUBSIG_PRIVINST;
687 send_sig(SIGBUS, current, 1);
691 void do_privop(struct pt_regs *regs)
693 current->thread.sig_address = regs->tpc;
694 current->thread.sig_desc = SUBSIG_PRIVINST;
695 send_sig(SIGILL, current, 1);
698 void do_privact(struct pt_regs *regs)
700 current->thread.sig_address = regs->tpc;
701 current->thread.sig_desc = SUBSIG_PRIVINST;
702 send_sig(SIGILL, current, 1);
705 void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
706 unsigned long tstate)
708 if(tstate & TSTATE_PRIV)
709 die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
710 current->thread.sig_address = pc;
711 current->thread.sig_desc = SUBSIG_PRIVINST;
712 send_sig(SIGILL, current, 1);
715 void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
716 unsigned long psr)
718 send_sig(SIGILL, current, 1);
721 /* Trap level 1 stuff or other traps we should never see... */
722 void do_cee(struct pt_regs *regs)
724 die_if_kernel("TL0: Cache Error Exception", regs);
727 void do_cee_tl1(struct pt_regs *regs)
729 die_if_kernel("TL1: Cache Error Exception", regs);
732 void do_dae_tl1(struct pt_regs *regs)
734 die_if_kernel("TL1: Data Access Exception", regs);
737 void do_iae_tl1(struct pt_regs *regs)
739 die_if_kernel("TL1: Instruction Access Exception", regs);
742 void do_div0_tl1(struct pt_regs *regs)
744 die_if_kernel("TL1: DIV0 Exception", regs);
747 void do_fpdis_tl1(struct pt_regs *regs)
749 die_if_kernel("TL1: FPU Disabled", regs);
752 void do_fpieee_tl1(struct pt_regs *regs)
754 die_if_kernel("TL1: FPU IEEE Exception", regs);
757 void do_fpother_tl1(struct pt_regs *regs)
759 die_if_kernel("TL1: FPU Other Exception", regs);
762 void do_ill_tl1(struct pt_regs *regs)
764 die_if_kernel("TL1: Illegal Instruction Exception", regs);
767 void do_irq_tl1(struct pt_regs *regs)
769 die_if_kernel("TL1: IRQ Exception", regs);
772 void do_lddfmna_tl1(struct pt_regs *regs)
774 die_if_kernel("TL1: LDDF Exception", regs);
777 void do_stdfmna_tl1(struct pt_regs *regs)
779 die_if_kernel("TL1: STDF Exception", regs);
782 void do_paw(struct pt_regs *regs)
784 die_if_kernel("TL0: Phys Watchpoint Exception", regs);
787 void do_paw_tl1(struct pt_regs *regs)
789 die_if_kernel("TL1: Phys Watchpoint Exception", regs);
792 void do_vaw(struct pt_regs *regs)
794 die_if_kernel("TL0: Virt Watchpoint Exception", regs);
797 void do_vaw_tl1(struct pt_regs *regs)
799 die_if_kernel("TL1: Virt Watchpoint Exception", regs);
802 void do_tof_tl1(struct pt_regs *regs)
804 die_if_kernel("TL1: Tag Overflow Exception", regs);
807 #ifdef CONFIG_EC_FLUSH_TRAP
808 void cache_flush_trap(struct pt_regs *regs)
810 #ifndef __SMP__
811 unsigned node = linux_cpus[get_cpuid()].prom_node;
812 #else
813 #error cache_flush_trap not supported on sparc64/SMP yet
814 #endif
816 #if 0
817 /* Broken */
818 int size = prom_getintdefault(node, "ecache-size", 512*1024);
819 int i, j;
820 unsigned long addr;
821 struct page *page, *end;
823 regs->tpc = regs->tnpc;
824 regs->tnpc = regs->tnpc + 4;
825 if (!capable(CAP_SYS_ADMIN)) return;
826 size >>= PAGE_SHIFT;
827 addr = PAGE_OFFSET - PAGE_SIZE;
828 page = mem_map - 1;
829 end = mem_map + max_mapnr;
830 for (i = 0; i < size; i++) {
831 do {
832 addr += PAGE_SIZE;
833 page++;
834 if (page >= end)
835 return;
836 } while (!PageReserved(page));
837 /* E-Cache line size is 64B. Let us pollute it :)) */
838 for (j = 0; j < PAGE_SIZE; j += 64)
839 __asm__ __volatile__ ("ldx [%0 + %1], %%g1" : : "r" (j), "r" (addr) : "g1");
841 #endif
843 #endif
845 void trap_init(void)
847 /* Attach to the address space of init_task. */
848 atomic_inc(&init_mm.mm_count);
849 current->active_mm = &init_mm;
851 /* NOTE: Other cpus have this done as they are started
852 * up on SMP.