1 /* $Id: traps.c,v 1.59 1999/05/18 16:57:10 jj 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]; 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, } }, 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, } }, 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 voidsyscall_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
->tss
.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
->tss
.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 longsyscall_trace_exit(unsigned long retval
,struct pt_regs
*regs
) 176 printk("ret[%016lx]\n", retval
); 179 #endif/* SYSCALL_TRACING */ 182 voidrtrap_check(struct pt_regs
*regs
) 184 registerunsigned long pgd_phys
asm("o1"); 185 registerunsigned long pgd_cache
asm("o2"); 186 registerunsigned long g1_or_g3
asm("o3"); 187 registerunsigned 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]))) || 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 (current
->tss
.ctx
!= ctx
))) { 232 printk("SHIT[%s:%d]: " 233 "(PP[%016lx] CACH[%016lx] CTX[%x] 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[%x:%x]] 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, 243 regs
->tpc
, regs
->tnpc
); 254 voidbad_trap(struct pt_regs
*regs
,long lvl
) 260 sprintf(buffer
,"Bad hw trap %lx at tl0\n", lvl
); 261 die_if_kernel(buffer
, regs
); 263 if(regs
->tstate
& TSTATE_PRIV
) 264 die_if_kernel("Kernel bad trap", regs
); 265 current
->tss
.sig_desc
=SUBSIG_BADTRAP(lvl
-0x100); 266 current
->tss
.sig_address
= regs
->tpc
; 267 force_sig(SIGILL
, current
); 271 voidbad_trap_tl1(struct pt_regs
*regs
,long lvl
) 276 sprintf(buffer
,"Bad trap %lx at tl>0", lvl
); 277 die_if_kernel(buffer
, regs
); 281 voidinstruction_access_exception(struct pt_regs
*regs
, 282 unsigned long sfsr
,unsigned long sfar
) 286 printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", 289 die_if_kernel("Iax", regs
); 293 voiddata_access_exception(struct pt_regs
*regs
, 294 unsigned long sfsr
,unsigned long sfar
) 296 if(regs
->tstate
& TSTATE_PRIV
) { 297 /* Test if this comes from uaccess places. */ 298 unsigned long fixup
, g2
; 300 g2
= regs
->u_regs
[UREG_G2
]; 301 if((fixup
=search_exception_table(regs
->tpc
, &g2
))) { 302 /* Ouch, somebody is trying ugly VM hole tricks on us... */ 303 #ifdef DEBUG_EXCEPTIONS 304 printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs
->tpc
); 305 printk("EX_TABLE: insn<%016lx> fixup<%016lx> " 306 "g2<%016lx>\n", regs
->tpc
, fixup
, g2
); 309 regs
->tnpc
= regs
->tpc
+4; 310 regs
->u_regs
[UREG_G2
] = g2
; 315 printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", 318 die_if_kernel("Dax", regs
); 325 force_sig(SIGSEGV
, current
); 330 /* This is really pathetic... */ 331 /* #define DEBUG_PCI_POKES */ 332 extern volatileint pci_poke_in_progress
; 333 extern volatileint pci_poke_faulted
; 336 /* When access exceptions happen, we must do this. */ 337 static __inline__
voidclean_and_reenable_l1_caches(void) 342 for(va
=0; va
< (PAGE_SIZE
<<1); va
+=32) { 343 spitfire_put_icache_tag(va
,0x0); 344 spitfire_put_dcache_tag(va
,0x0); 348 __asm__
__volatile__("flush %%g6\n\t" 350 "stxa %0, [%%g0] %1\n\t" 353 :"r"(LSU_CONTROL_IC
| LSU_CONTROL_DC
| 354 LSU_CONTROL_IM
| LSU_CONTROL_DM
), 359 voiddo_dae(struct pt_regs
*regs
) 362 if(pci_poke_in_progress
) { 363 #ifdef DEBUG_PCI_POKES 364 prom_printf(" (POKE tpc[%016lx] tnpc[%016lx] ", 365 regs
->tpc
, regs
->tnpc
); 368 regs
->tnpc
= regs
->tpc
+4; 371 #ifdef DEBUG_PCI_POKES 372 prom_printf("PCI) "); 375 clean_and_reenable_l1_caches(); 379 clean_and_reenable_l1_caches(); 381 force_sig(SIGSEGV
, current
); 385 voiddo_iae(struct pt_regs
*regs
) 387 clean_and_reenable_l1_caches(); 390 force_sig(SIGSEGV
, current
); 394 voiddo_fpe_common(struct pt_regs
*regs
) 396 if(regs
->tstate
& TSTATE_PRIV
) { 397 regs
->tpc
= regs
->tnpc
; 400 current
->tss
.sig_address
= regs
->tpc
; 401 current
->tss
.sig_desc
= SUBSIG_FPERROR
; 402 send_sig(SIGFPE
, current
,1); 406 voiddo_fpieee(struct pt_regs
*regs
) 409 printk("fpieee %016lx\n", current
->tss
.xfsr
[0]); 414 externintdo_mathemu(struct pt_regs
*,struct fpustate
*); 416 voiddo_fpother(struct pt_regs
*regs
) 418 struct fpustate
*f
= FPUSTATE
; 421 switch((current
->tss
.xfsr
[0] &0x1c000)) { 422 case(2<<14):/* unfinished_FPop */ 423 case(3<<14):/* unimplemented_FPop */ 424 ret
=do_mathemu(regs
, f
); 429 printk("fpother %016lx\n", current
->tss
.xfsr
[0]); 434 voiddo_tof(struct pt_regs
*regs
) 436 if(regs
->tstate
& TSTATE_PRIV
) 437 die_if_kernel("Penguin overflow trap from kernel mode", regs
); 438 current
->tss
.sig_address
= regs
->tpc
; 439 current
->tss
.sig_desc
= SUBSIG_TAG
;/* as good as any */ 440 send_sig(SIGEMT
, current
,1); 443 voiddo_div0(struct pt_regs
*regs
) 445 send_sig(SIGILL
, current
,1); 448 voidinstruction_dump(unsigned int*pc
) 452 if((((unsigned long) pc
) &3)) 455 printk("Instruction DUMP:"); 456 for(i
= -3; i
<6; i
++) 457 printk("%c%08x%c",i
?' ':'<',pc
[i
],i
?' ':'>'); 461 voiduser_instruction_dump(unsigned int*pc
) 466 if((((unsigned long) pc
) &3)) 469 if(copy_from_user(buf
, pc
-3,sizeof(buf
))) 472 printk("Instruction DUMP:"); 474 printk("%c%08x%c",i
==3?' ':'<',buf
[i
],i
==3?' ':'>'); 478 voiddie_if_kernel(char*str
,struct pt_regs
*regs
) 480 externvoid__show_regs(struct pt_regs
* regs
); 481 externvoidsmp_report_regs(void); 483 struct reg_window
*lastrw
; 485 /* Amuse the user. */ 492 printk("%s(%d): %s\n", current
->comm
, current
->pid
, str
); 493 __asm__
__volatile__("flushw"); 495 if(regs
->tstate
& TSTATE_PRIV
) { 496 struct reg_window
*rw
= (struct reg_window
*) 497 (regs
->u_regs
[UREG_FP
] + STACK_BIAS
); 499 /* Stop the back trace when we hit userland or we 500 * find some badly aligned kernel stack. 502 lastrw
= (struct reg_window
*)current
; 506 (char*) rw
< ((char*) current
) 507 +sizeof(union task_union
) && 508 !(((unsigned long) rw
) &0x7)) { 509 printk("Caller[%016lx]\n", rw
->ins
[7]); 511 rw
= (struct reg_window
*) 512 (rw
->ins
[6] + STACK_BIAS
); 514 instruction_dump((unsigned int*) regs
->tpc
); 516 user_instruction_dump((unsigned int*) regs
->tpc
); 521 lock_kernel();/* Or else! */ 522 if(regs
->tstate
& TSTATE_PRIV
) 527 externinthandle_popc(u32 insn
,struct pt_regs
*regs
); 528 externinthandle_ldf_stq(u32 insn
,struct pt_regs
*regs
); 530 voiddo_illegal_instruction(struct pt_regs
*regs
) 532 unsigned long pc
= regs
->tpc
; 533 unsigned long tstate
= regs
->tstate
; 536 if(tstate
& TSTATE_PRIV
) 537 die_if_kernel("Kernel illegal instruction", regs
); 538 if(current
->tss
.flags
& SPARC_FLAG_32BIT
) 540 if(get_user(insn
, (u32
*)pc
) != -EFAULT
) { 541 if((insn
&0xc1ffc000) ==0x81700000)/* POPC */{ 542 if(handle_popc(insn
, regs
)) 544 }else if((insn
&0xc1580000) ==0xc1100000)/* LDQ/STQ */{ 545 if(handle_ldf_stq(insn
, regs
)) 549 current
->tss
.sig_address
= pc
; 550 current
->tss
.sig_desc
= SUBSIG_ILLINST
; 551 send_sig(SIGILL
, current
,1); 554 voidmem_address_unaligned(struct pt_regs
*regs
,unsigned long sfar
,unsigned long sfsr
) 556 if(regs
->tstate
& TSTATE_PRIV
) { 557 externvoidkernel_unaligned_trap(struct pt_regs
*regs
, 559 unsigned long sfar
,unsigned long sfsr
); 561 returnkernel_unaligned_trap(regs
, *((unsigned int*)regs
->tpc
), sfar
, sfsr
); 563 current
->tss
.sig_address
= regs
->tpc
; 564 current
->tss
.sig_desc
= SUBSIG_PRIVINST
; 565 send_sig(SIGBUS
, current
,1); 569 voiddo_privop(struct pt_regs
*regs
) 571 current
->tss
.sig_address
= regs
->tpc
; 572 current
->tss
.sig_desc
= SUBSIG_PRIVINST
; 573 send_sig(SIGILL
, current
,1); 576 voiddo_privact(struct pt_regs
*regs
) 578 current
->tss
.sig_address
= regs
->tpc
; 579 current
->tss
.sig_desc
= SUBSIG_PRIVINST
; 580 send_sig(SIGILL
, current
,1); 583 voiddo_priv_instruction(struct pt_regs
*regs
,unsigned long pc
,unsigned long npc
, 584 unsigned long tstate
) 586 if(tstate
& TSTATE_PRIV
) 587 die_if_kernel("Penguin instruction from Penguin mode??!?!", regs
); 588 current
->tss
.sig_address
= pc
; 589 current
->tss
.sig_desc
= SUBSIG_PRIVINST
; 590 send_sig(SIGILL
, current
,1); 593 voidhandle_hw_divzero(struct pt_regs
*regs
,unsigned long pc
,unsigned long npc
, 596 send_sig(SIGILL
, current
,1); 599 /* Trap level 1 stuff or other traps we should never see... */ 600 voiddo_cee(struct pt_regs
*regs
) 602 die_if_kernel("TL0: Cache Error Exception", regs
); 605 voiddo_cee_tl1(struct pt_regs
*regs
) 607 die_if_kernel("TL1: Cache Error Exception", regs
); 610 voiddo_dae_tl1(struct pt_regs
*regs
) 612 die_if_kernel("TL1: Data Access Exception", regs
); 615 voiddo_iae_tl1(struct pt_regs
*regs
) 617 die_if_kernel("TL1: Instruction Access Exception", regs
); 620 voiddo_div0_tl1(struct pt_regs
*regs
) 622 die_if_kernel("TL1: DIV0 Exception", regs
); 625 voiddo_fpdis_tl1(struct pt_regs
*regs
) 627 die_if_kernel("TL1: FPU Disabled", regs
); 630 voiddo_fpieee_tl1(struct pt_regs
*regs
) 632 die_if_kernel("TL1: FPU IEEE Exception", regs
); 635 voiddo_fpother_tl1(struct pt_regs
*regs
) 637 die_if_kernel("TL1: FPU Other Exception", regs
); 640 voiddo_ill_tl1(struct pt_regs
*regs
) 642 die_if_kernel("TL1: Illegal Instruction Exception", regs
); 645 voiddo_irq_tl1(struct pt_regs
*regs
) 647 die_if_kernel("TL1: IRQ Exception", regs
); 650 voiddo_lddfmna_tl1(struct pt_regs
*regs
) 652 die_if_kernel("TL1: LDDF Exception", regs
); 655 voiddo_stdfmna_tl1(struct pt_regs
*regs
) 657 die_if_kernel("TL1: STDF Exception", regs
); 660 voiddo_paw(struct pt_regs
*regs
) 662 die_if_kernel("TL0: Phys Watchpoint Exception", regs
); 665 voiddo_paw_tl1(struct pt_regs
*regs
) 667 die_if_kernel("TL1: Phys Watchpoint Exception", regs
); 670 voiddo_vaw(struct pt_regs
*regs
) 672 die_if_kernel("TL0: Virt Watchpoint Exception", regs
); 675 voiddo_vaw_tl1(struct pt_regs
*regs
) 677 die_if_kernel("TL1: Virt Watchpoint Exception", regs
); 680 voiddo_tof_tl1(struct pt_regs
*regs
) 682 die_if_kernel("TL1: Tag Overflow Exception", regs
); 685 #ifdef CONFIG_EC_FLUSH_TRAP 686 voidcache_flush_trap(struct pt_regs
*regs
) 689 unsigned node
= linux_cpus
[get_cpuid()].prom_node
; 691 #error cache_flush_trap not supported on sparc64/SMP yet 696 int size
=prom_getintdefault(node
,"ecache-size",512*1024); 699 struct page
*page
, *end
; 701 regs
->tpc
= regs
->tnpc
; 702 regs
->tnpc
= regs
->tnpc
+4; 703 if(!capable(CAP_SYS_ADMIN
))return; 705 addr
= PAGE_OFFSET
- PAGE_SIZE
; 707 end
= mem_map
+ max_mapnr
; 708 for(i
=0; i
< size
; i
++) { 714 }while(!PageReserved(page
)); 715 /* E-Cache line size is 64B. Let us pollute it :)) */ 716 for(j
=0; j
< PAGE_SIZE
; j
+=64) 717 __asm__
__volatile__("ldx [%0 + %1], %%g1": :"r"(j
),"r"(addr
) :"g1");