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)
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>
24 #include <asm/pgtable.h>
25 #include <asm/unistd.h>
26 #include <asm/uaccess.h>
27 #include <asm/fpumacro.h>
30 #include <linux/kmod.h>
33 /* #define SYSCALL_TRACING */
34 /* #define VERBOSE_SYSCALL_TRACING */
35 /* #define DEBUG_FPU */
37 #ifdef SYSCALL_TRACING
38 #ifdef VERBOSE_SYSCALL_TRACING
43 char arg_is_string
[6];
46 { 1, "exit", 1, { 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, } },
64 { 33, "access", 2, { 1, 0, } },
66 { 37, "kill", 2, { 0, 0, } },
67 { 38, "stat", 2, { 1, 0, } },
68 { 40, "lstat", 2, { 1, 0, } },
69 { 41, "dup", 1, { 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]))
121 #ifdef VERBOSE_SYSCALL_TRACING
122 static char scall_strbuf
[512];
125 void syscall_trace_entry(unsigned long g1
, struct pt_regs
*regs
)
127 #ifdef VERBOSE_SYSCALL_TRACING
133 if (!current
->pid
) return;
135 printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
136 current
->comm
, current
->pid
, regs
->tpc
, (int)g1
);
137 #ifdef VERBOSE_SYSCALL_TRACING
139 for(i
= 0; i
< NUM_SDESC_ENTRIES
; i
++)
140 if(sdesc_entries
[i
].scall_num
== g1
) {
141 sdp
= &sdesc_entries
[i
];
145 printk("%s(", sdp
->name
);
146 for(i
= 0; i
< sdp
->num_args
; i
++) {
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
]);
153 printk("%016lx", regs
->u_regs
[UREG_I0
+ i
]);
155 if (current
->thread
.flags
& SPARC_FLAG_32BIT
)
156 strncpy_from_user(scall_strbuf
,
157 (char *)(regs
->u_regs
[UREG_I0
+ i
] & 0xffffffff),
160 strncpy_from_user(scall_strbuf
,
161 (char *)regs
->u_regs
[UREG_I0
+ i
],
163 printk("%s", scall_strbuf
);
171 unsigned long syscall_trace_exit(unsigned long retval
, struct pt_regs
*regs
)
176 printk("ret[%016lx]\n", retval
);
179 #endif /* SYSCALL_TRACING */
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");
193 __asm__
__volatile__("rdpr %%pstate, %0"
195 if((test
& PSTATE_MG
) != 0 ||
196 (test
& PSTATE_IE
) == 0) {
197 printk("rtrap_check: Bogus pstate[%016lx]\n", test
);
203 __asm__
__volatile__("
205 wrpr %%o5, %4, %%pstate
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
),
218 ctx
= spitfire_get_secondary_context();
220 if((pgd_phys
!= __pa(current
->mm
->pgd
)) ||
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
)) ||
229 ((ctx
!= (current
->mm
->context
& 0x3ff)) ||
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
);
253 void bad_trap (struct pt_regs
*regs
, long lvl
)
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
);
270 void bad_trap_tl1 (struct pt_regs
*regs
, long lvl
)
275 sprintf (buffer
, "Bad trap %lx at tl>0", lvl
);
276 die_if_kernel (buffer
, regs
);
280 void instruction_access_exception (struct pt_regs
*regs
,
281 unsigned long sfsr
, unsigned long sfar
)
284 if (regs
->tstate
& TSTATE_PRIV
) {
286 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
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
);
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
);
313 regs
->tnpc
= regs
->tpc
+ 4;
314 regs
->u_regs
[UREG_G2
] = g2
;
319 printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
322 die_if_kernel("Dax", regs
);
329 force_sig(SIGSEGV
, current
);
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
;
340 /* When access exceptions happen, we must do this. */
341 static __inline__
void clean_and_reenable_l1_caches(void)
346 for(va
= 0; va
< (PAGE_SIZE
<< 1); va
+= 32) {
347 spitfire_put_icache_tag(va
, 0x0);
348 spitfire_put_dcache_tag(va
, 0x0);
352 __asm__
__volatile__("flush %%g6\n\t"
354 "stxa %0, [%%g0] %1\n\t"
357 : "r" (LSU_CONTROL_IC
| LSU_CONTROL_DC
|
358 LSU_CONTROL_IM
| LSU_CONTROL_DM
),
359 "i" (ASI_LSU_CONTROL
)
363 void do_dae(struct pt_regs
*regs
)
366 if(pci_poke_in_progress
) {
367 #ifdef DEBUG_PCI_POKES
368 prom_printf(" (POKE tpc[%016lx] tnpc[%016lx] ",
369 regs
->tpc
, regs
->tnpc
);
371 pci_poke_faulted
= 1;
372 regs
->tnpc
= regs
->tpc
+ 4;
375 #ifdef DEBUG_PCI_POKES
376 prom_printf("PCI) ");
379 clean_and_reenable_l1_caches();
383 clean_and_reenable_l1_caches();
385 force_sig(SIGSEGV
, current
);
389 void do_iae(struct pt_regs
*regs
)
391 clean_and_reenable_l1_caches();
394 force_sig(SIGSEGV
, current
);
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
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
,
475 struct pt_regs
*regs
)
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",
484 (ce_status
& CE_STATUS_AFSR_MASK
),
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
;
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
;
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
;
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
)
531 printk("fpieee %016lx\n", current
->thread
.xfsr
[0]);
536 extern int do_mathemu(struct pt_regs
*, struct fpustate
*);
538 void do_fpother(struct pt_regs
*regs
)
540 struct fpustate
*f
= FPUSTATE
;
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
);
551 printk("fpother %016lx\n", current
->thread
.xfsr
[0]);
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
)
574 if((((unsigned long) pc
) & 3))
577 printk("Instruction DUMP:");
578 for(i
= -3; i
< 6; i
++)
579 printk("%c%08x%c",i
?' ':'<',pc
[i
],i
?' ':'>');
583 void user_instruction_dump (unsigned int *pc
)
588 if((((unsigned long) pc
) & 3))
591 if(copy_from_user(buf
, pc
- 3, sizeof(buf
)))
594 printk("Instruction DUMP:");
595 for(i
= 0; i
< 9; i
++)
596 printk("%c%08x%c",i
==3?' ':'<',buf
[i
],i
==3?' ':'>');
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);
605 struct reg_window
*lastrw
;
607 /* Amuse the user. */
614 printk("%s(%d): %s\n", current
->comm
, current
->pid
, str
);
615 __asm__
__volatile__("flushw");
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
;
628 (char *) rw
< ((char *) current
)
629 + sizeof (union task_union
) &&
630 !(((unsigned long) rw
) & 0x7)) {
631 printk("Caller[%016lx]\n", rw
->ins
[7]);
633 rw
= (struct reg_window
*)
634 (rw
->ins
[6] + STACK_BIAS
);
636 instruction_dump ((unsigned int *) regs
->tpc
);
638 user_instruction_dump ((unsigned int *) regs
->tpc
);
643 lock_kernel(); /* Or else! */
644 if(regs
->tstate
& TSTATE_PRIV
)
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
;
658 if(tstate
& TSTATE_PRIV
)
659 die_if_kernel("Kernel illegal instruction", regs
);
660 if(current
->thread
.flags
& SPARC_FLAG_32BIT
)
662 if (get_user(insn
, (u32
*)pc
) != -EFAULT
) {
663 if ((insn
& 0xc1ffc000) == 0x81700000) /* POPC */ {
664 if (handle_popc(insn
, regs
))
666 } else if ((insn
& 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
667 if (handle_ldf_stq(insn
, regs
))
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
,
681 unsigned long sfar
, unsigned long sfsr
);
683 return kernel_unaligned_trap(regs
, *((unsigned int *)regs
->tpc
), sfar
, sfsr
);
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
,
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
)
811 unsigned node
= linux_cpus
[get_cpuid()].prom_node
;
813 #error cache_flush_trap not supported on sparc64/SMP yet
818 int size
= prom_getintdefault(node
, "ecache-size", 512*1024);
821 struct page
*page
, *end
;
823 regs
->tpc
= regs
->tnpc
;
824 regs
->tnpc
= regs
->tnpc
+ 4;
825 if (!capable(CAP_SYS_ADMIN
)) return;
827 addr
= PAGE_OFFSET
- PAGE_SIZE
;
829 end
= mem_map
+ max_mapnr
;
830 for (i
= 0; i
< size
; i
++) {
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");
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