1/* 2 * Architecture-specific trap handling. 3 * 4 * Copyright (C) 1998-2002 Hewlett-Packard Co 5 * David Mosberger-Tang <davidm@hpl.hp.com> 6 * 7 * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE 8 */ 9 10/* 11 * fp_emulate() needs to be able to access and update all floating point registers. Those 12 * saved in pt_regs can be accessed through that structure, but those not saved, will be 13 * accessed directly. To make this work, we need to ensure that the compiler does not end 14 * up using a preserved floating point register on its own. The following achieves this 15 * by declaring preserved registers that are not marked as "fixed" as global register 16 * variables. 17 */ 18register double f2 asm ("f2"); register double f3 asm ("f3"); 19register double f4 asm ("f4"); register double f5 asm ("f5"); 20 21register long f16 asm ("f16"); register long f17 asm ("f17"); 22register long f18 asm ("f18"); register long f19 asm ("f19"); 23register long f20 asm ("f20"); register long f21 asm ("f21"); 24register long f22 asm ("f22"); register long f23 asm ("f23"); 25 26register double f24 asm ("f24"); register double f25 asm ("f25"); 27register double f26 asm ("f26"); register double f27 asm ("f27"); 28register double f28 asm ("f28"); register double f29 asm ("f29"); 29register double f30 asm ("f30"); register double f31 asm ("f31"); 30 31#include <linux/config.h> 32#include <linux/kernel.h> 33#include <linux/init.h> 34#include <linux/sched.h> 35#include <linux/vt_kern.h> /* For unblank_screen() */ 36 37#include <asm/hardirq.h> 38#include <asm/ia32.h> 39#include <asm/processor.h> 40#include <asm/uaccess.h> 41 42#include <asm/fpswa.h> 43 44extern spinlock_t timerlist_lock; 45 46static fpswa_interface_t *fpswa_interface; 47 48void __init 49trap_init (void) 50{ 51 if (ia64_boot_param->fpswa) { 52 /* FPSWA fixup: make the interface pointer a kernel virtual address: */ 53 fpswa_interface = __va(ia64_boot_param->fpswa); 54 printk("FPSWA interface at 0x%lx, revision %d.%d\n", 55 ia64_boot_param->fpswa, 56 fpswa_interface->revision >> 16, 57 fpswa_interface->revision & 0xffff); 58 } else 59 printk("No FPSWA interface\n"); 60} 61 62/* 63 * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock 64 * is acquired through the console unblank code) 65 */ 66void 67bust_spinlocks (int yes) 68{ 69 spin_lock_init(&timerlist_lock); 70 if (yes) { 71 oops_in_progress = 1; 72#ifdef CONFIG_SMP 73 global_irq_lock = 0; /* Many serial drivers do __global_cli() */ 74#endif 75 } else { 76 int loglevel_save = console_loglevel; 77#ifdef CONFIG_VT 78 unblank_screen(); 79#endif 80 oops_in_progress = 0; 81 /* 82 * OK, the message is on the console. Now we call printk() without 83 * oops_in_progress set so that printk will give klogd a poke. Hold onto 84 * your hats... 85 */ 86 console_loglevel = 15; /* NMI oopser may have shut the console up */ 87 printk(" "); 88 console_loglevel = loglevel_save; 89 } 90} 91 92void 93die (const char *str, struct pt_regs *regs, long err) 94{ 95 static struct { 96 spinlock_t lock; 97 int lock_owner; 98 int lock_owner_depth; 99 } die = { 100 lock: SPIN_LOCK_UNLOCKED, 101 lock_owner: -1, 102 lock_owner_depth: 0 103 }; 104 105 if (die.lock_owner != smp_processor_id()) { 106 console_verbose(); 107 spin_lock_irq(&die.lock); 108 die.lock_owner = smp_processor_id(); 109 die.lock_owner_depth = 0; 110 bust_spinlocks(1); 111 } 112 113 if (++die.lock_owner_depth < 3) { 114 printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); 115 show_regs(regs); 116 } else 117 printk(KERN_ERR "Recursive die() failure, output suppressed\n"); 118 119 bust_spinlocks(0); 120 die.lock_owner = -1; 121 spin_unlock_irq(&die.lock); 122 do_exit(SIGSEGV); 123} 124 125void 126die_if_kernel (char *str, struct pt_regs *regs, long err) 127{ 128 if (!user_mode(regs)) 129 die(str, regs, err); 130} 131 132void 133ia64_bad_break (unsigned long break_num, struct pt_regs *regs) 134{ 135 siginfo_t siginfo; 136 int sig, code; 137 138 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ 139 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 140 siginfo.si_imm = break_num; 141 siginfo.si_flags = 0; /* clear __ISR_VALID */ 142 siginfo.si_isr = 0; 143 144 switch (break_num) { 145 case 0: /* unknown error */ 146 sig = SIGILL; code = ILL_ILLOPC; 147 break; 148 149 case 1: /* integer divide by zero */ 150 sig = SIGFPE; code = FPE_INTDIV; 151 break; 152 153 case 2: /* integer overflow */ 154 sig = SIGFPE; code = FPE_INTOVF; 155 break; 156 157 case 3: /* range check/bounds check */ 158 sig = SIGFPE; code = FPE_FLTSUB; 159 break; 160 161 case 4: /* null pointer dereference */ 162 sig = SIGSEGV; code = SEGV_MAPERR; 163 break; 164 165 case 5: /* misaligned data */ 166 sig = SIGSEGV; code = BUS_ADRALN; 167 break; 168 169 case 6: /* decimal overflow */ 170 sig = SIGFPE; code = __FPE_DECOVF; 171 break; 172 173 case 7: /* decimal divide by zero */ 174 sig = SIGFPE; code = __FPE_DECDIV; 175 break; 176 177 case 8: /* packed decimal error */ 178 sig = SIGFPE; code = __FPE_DECERR; 179 break; 180 181 case 9: /* invalid ASCII digit */ 182 sig = SIGFPE; code = __FPE_INVASC; 183 break; 184 185 case 10: /* invalid decimal digit */ 186 sig = SIGFPE; code = __FPE_INVDEC; 187 break; 188 189 case 11: /* paragraph stack overflow */ 190 sig = SIGSEGV; code = __SEGV_PSTKOVF; 191 break; 192 193 case 0x3f000 ... 0x3ffff: /* bundle-update in progress */ 194 sig = SIGILL; code = __ILL_BNDMOD; 195 break; 196 197 default: 198 if (break_num < 0x40000 || break_num > 0x100000) 199 die_if_kernel("Bad break", regs, break_num); 200 201 if (break_num < 0x80000) { 202 sig = SIGILL; code = __ILL_BREAK; 203 } else { 204 sig = SIGTRAP; code = TRAP_BRKPT; 205 } 206 } 207 siginfo.si_signo = sig; 208 siginfo.si_errno = 0; 209 siginfo.si_code = code; 210 force_sig_info(sig, &siginfo, current); 211} 212 213/* 214 * Unimplemented system calls. This is called only for stuff that 215 * we're supposed to implement but haven't done so yet. Everything 216 * else goes to sys_ni_syscall. 217 */ 218asmlinkage long 219ia64_ni_syscall (unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, 220 unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7, 221 unsigned long stack) 222{ 223 struct pt_regs *regs = (struct pt_regs *) &stack; 224 225 printk("%s(%d): <sc%ld(%lx,%lx,%lx,%lx)>\n", current->comm, current->pid, 226 regs->r15, arg0, arg1, arg2, arg3); 227 return -ENOSYS; 228} 229 230/* 231 * disabled_fph_fault() is called when a user-level process attempts to access f32..f127 232 * and it doesn't own the fp-high register partition. When this happens, we save the 233 * current fph partition in the task_struct of the fpu-owner (if necessary) and then load 234 * the fp-high partition of the current task (if necessary). Note that the kernel has 235 * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes 236 * care of clearing psr.dfh. 237 */ 238static inline void 239disabled_fph_fault (struct pt_regs *regs) 240{ 241 struct ia64_psr *psr = ia64_psr(regs); 242 243 /* first, grant user-level access to fph partition: */ 244 psr->dfh = 0; 245#ifndef CONFIG_SMP 246 { 247 struct task_struct *fpu_owner = ia64_get_fpu_owner(); 248 249 if (fpu_owner == current) 250 return; 251 252 if (fpu_owner) 253 ia64_flush_fph(fpu_owner); 254 255 } 256#endif /* !CONFIG_SMP */ 257 ia64_set_fpu_owner(current); 258 if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { 259 __ia64_load_fpu(current->thread.fph); 260 psr->mfh = 0; 261 } else { 262 __ia64_init_fpu(); 263 /* 264 * Set mfh because the state in thread.fph does not match the state in 265 * the fph partition. 266 */ 267 psr->mfh = 1; 268 } 269} 270 271static inline int 272fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs, 273 struct pt_regs *regs) 274{ 275 struct ia64_fpreg f6_11[6]; 276 fp_state_t fp_state; 277 fpswa_ret_t ret; 278 279 if (!fpswa_interface) 280 return -1; 281 282 memset(&fp_state, 0, sizeof(fp_state_t)); 283 284 /* 285 * compute fp_state. only FP registers f6 - f11 are used by the 286 * kernel, so set those bits in the mask and set the low volatile 287 * pointer to point to these registers. 288 */ 289 fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */ 290 f6_11[0] = regs->f6; f6_11[1] = regs->f7; 291 f6_11[2] = regs->f8; f6_11[3] = regs->f9; 292 __asm__ ("stf.spill %0=f10%P0" : "=m"(f6_11[4])); 293 __asm__ ("stf.spill %0=f11%P0" : "=m"(f6_11[5])); 294 fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_11; 295 /* 296 * unsigned long (*EFI_FPSWA) ( 297 * unsigned long trap_type, 298 * void *Bundle, 299 * unsigned long *pipsr, 300 * unsigned long *pfsr, 301 * unsigned long *pisr, 302 * unsigned long *ppreds, 303 * unsigned long *pifs, 304 * void *fp_state); 305 */ 306 ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle, 307 (unsigned long *) ipsr, (unsigned long *) fpsr, 308 (unsigned long *) isr, (unsigned long *) pr, 309 (unsigned long *) ifs, &fp_state); 310 regs->f6 = f6_11[0]; regs->f7 = f6_11[1]; 311 regs->f8 = f6_11[2]; regs->f9 = f6_11[3]; 312 __asm__ ("ldf.fill f10=%0%P0" :: "m"(f6_11[4])); 313 __asm__ ("ldf.fill f11=%0%P0" :: "m"(f6_11[5])); 314 return ret.status; 315} 316 317/* 318 * Handle floating-point assist faults and traps. 319 */ 320static int 321handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) 322{ 323 long exception, bundle[2]; 324 unsigned long fault_ip; 325 struct siginfo siginfo; 326 static int fpu_swa_count = 0; 327 static unsigned long last_time; 328 329 fault_ip = regs->cr_iip; 330 if (!fp_fault && (ia64_psr(regs)->ri == 0)) 331 fault_ip -= 16; 332 if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle))) 333 return -1; 334 335 if (jiffies - last_time > 5*HZ) 336 fpu_swa_count = 0; 337 if ((++fpu_swa_count < 5) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) { 338 last_time = jiffies; 339 printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx\n", 340 current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri); 341 } 342 343 exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr, 344 ®s->cr_ifs, regs); 345 if (fp_fault) { 346 if (exception == 0) { 347 /* emulation was successful */ 348 ia64_increment_ip(regs); 349 } else if (exception == -1) { 350 printk("handle_fpu_swa: fp_emulate() returned -1\n"); 351 return -1; 352 } else { 353 /* is next instruction a trap? */ 354 if (exception & 2) { 355 ia64_increment_ip(regs); 356 } 357 siginfo.si_signo = SIGFPE; 358 siginfo.si_errno = 0; 359 siginfo.si_code = __SI_FAULT; /* default code */ 360 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 361 if (isr & 0x11) { 362 siginfo.si_code = FPE_FLTINV; 363 } else if (isr & 0x44) { 364 siginfo.si_code = FPE_FLTDIV; 365 } 366 siginfo.si_isr = isr; 367 siginfo.si_flags = __ISR_VALID; 368 siginfo.si_imm = 0; 369 force_sig_info(SIGFPE, &siginfo, current); 370 } 371 } else { 372 if (exception == -1) { 373 printk("handle_fpu_swa: fp_emulate() returned -1\n"); 374 return -1; 375 } else if (exception != 0) { 376 /* raise exception */ 377 siginfo.si_signo = SIGFPE; 378 siginfo.si_errno = 0; 379 siginfo.si_code = __SI_FAULT; /* default code */ 380 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 381 if (isr & 0x880) { 382 siginfo.si_code = FPE_FLTOVF; 383 } else if (isr & 0x1100) { 384 siginfo.si_code = FPE_FLTUND; 385 } else if (isr & 0x2200) { 386 siginfo.si_code = FPE_FLTRES; 387 } 388 siginfo.si_isr = isr; 389 siginfo.si_flags = __ISR_VALID; 390 siginfo.si_imm = 0; 391 force_sig_info(SIGFPE, &siginfo, current); 392 } 393 } 394 return 0; 395} 396 397struct illegal_op_return { 398 unsigned long fkt, arg1, arg2, arg3; 399}; 400 401struct illegal_op_return 402ia64_illegal_op_fault (unsigned long ec, unsigned long arg1, unsigned long arg2, 403 unsigned long arg3, unsigned long arg4, unsigned long arg5, 404 unsigned long arg6, unsigned long arg7, unsigned long stack) 405{ 406 struct pt_regs *regs = (struct pt_regs *) &stack; 407 struct illegal_op_return rv; 408 struct siginfo si; 409 char buf[128]; 410 411#ifdef CONFIG_IA64_BRL_EMU 412 { 413 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long); 414 415 rv = ia64_emulate_brl(regs, ec); 416 if (rv.fkt != (unsigned long) -1) 417 return rv; 418 } 419#endif 420 421 sprintf(buf, "IA-64 Illegal operation fault"); 422 die_if_kernel(buf, regs, 0); 423 424 memset(&si, 0, sizeof(si)); 425 si.si_signo = SIGILL; 426 si.si_code = ILL_ILLOPC; 427 si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 428 force_sig_info(SIGILL, &si, current); 429 rv.fkt = 0; 430 return rv; 431} 432 433void 434ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, 435 unsigned long iim, unsigned long itir, unsigned long arg5, 436 unsigned long arg6, unsigned long arg7, unsigned long stack) 437{ 438 struct pt_regs *regs = (struct pt_regs *) &stack; 439 unsigned long code, error = isr; 440 struct siginfo siginfo; 441 char buf[128]; 442 int result, sig; 443 static const char *reason[] = { 444 "IA-64 Illegal Operation fault", 445 "IA-64 Privileged Operation fault", 446 "IA-64 Privileged Register fault", 447 "IA-64 Reserved Register/Field fault", 448 "Disabled Instruction Set Transition fault", 449 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault", 450 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12", 451 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15" 452 }; 453 454 if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) { 455 /* 456 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel 457 * the lfetch. 458 */ 459 ia64_psr(regs)->ed = 1; 460 return; 461 } 462 463 switch (vector) { 464 case 24: /* General Exception */ 465 code = (isr >> 4) & 0xf; 466 sprintf(buf, "General Exception: %s%s", reason[code], 467 (code == 3) ? ((isr & (1UL << 37)) 468 ? " (RSE access)" : " (data access)") : ""); 469 if (code == 8) { 470# ifdef CONFIG_IA64_PRINT_HAZARDS 471 printk("%016lx:possible hazard, pr = %016lx\n", regs->cr_iip, regs->pr); 472# endif 473 return; 474 } 475 break; 476 477 case 25: /* Disabled FP-Register */ 478 if (isr & 2) { 479 disabled_fph_fault(regs); 480 return; 481 } 482 sprintf(buf, "Disabled FPL fault---not supposed to happen!"); 483 break; 484 485 case 26: /* NaT Consumption */ 486 if (user_mode(regs)) { 487 if (((isr >> 4) & 0xf) == 2) { 488 /* NaT page consumption */ 489 sig = SIGSEGV; 490 code = SEGV_ACCERR; 491 } else { 492 /* register NaT consumption */ 493 sig = SIGILL; 494 code = ILL_ILLOPN; 495 } 496 siginfo.si_signo = sig; 497 siginfo.si_code = code; 498 siginfo.si_errno = 0; 499 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 500 siginfo.si_imm = vector; 501 siginfo.si_flags = __ISR_VALID; 502 siginfo.si_isr = isr; 503 force_sig_info(sig, &siginfo, current); 504 return; 505 } else if (done_with_exception(regs)) 506 return; 507 sprintf(buf, "NaT consumption"); 508 break; 509 510 case 31: /* Unsupported Data Reference */ 511 if (user_mode(regs)) { 512 siginfo.si_signo = SIGILL; 513 siginfo.si_code = ILL_ILLOPN; 514 siginfo.si_errno = 0; 515 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 516 siginfo.si_imm = vector; 517 siginfo.si_flags = __ISR_VALID; 518 siginfo.si_isr = isr; 519 force_sig_info(SIGILL, &siginfo, current); 520 return; 521 } 522 sprintf(buf, "Unsupported data reference"); 523 break; 524 525 case 29: /* Debug */ 526 case 35: /* Taken Branch Trap */ 527 case 36: /* Single Step Trap */ 528 switch (vector) { 529 case 29: 530 siginfo.si_code = TRAP_HWBKPT; 531#ifdef CONFIG_ITANIUM 532 /* 533 * Erratum 10 (IFA may contain incorrect address) now has 534 * "NoFix" status. There are no plans for fixing this. 535 */ 536 if (ia64_psr(regs)->is == 0) 537 ifa = regs->cr_iip; 538#endif 539 break; 540 case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; 541 case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; 542 } 543 siginfo.si_signo = SIGTRAP; 544 siginfo.si_errno = 0; 545 siginfo.si_flags = 0; 546 siginfo.si_isr = 0; 547 siginfo.si_addr = (void *) ifa; 548 siginfo.si_imm = 0; 549 force_sig_info(SIGTRAP, &siginfo, current); 550 return; 551 552 case 32: /* fp fault */ 553 case 33: /* fp trap */ 554 result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr); 555 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) { 556 siginfo.si_signo = SIGFPE; 557 siginfo.si_errno = 0; 558 siginfo.si_code = FPE_FLTINV; 559 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 560 siginfo.si_flags = __ISR_VALID; 561 siginfo.si_isr = isr; 562 siginfo.si_imm = 0; 563 force_sig_info(SIGFPE, &siginfo, current); 564 } 565 return; 566 567 case 34: /* Unimplemented Instruction Address Trap */ 568 if (user_mode(regs)) { 569 siginfo.si_signo = SIGILL; 570 siginfo.si_code = ILL_BADIADDR; 571 siginfo.si_errno = 0; 572 siginfo.si_flags = 0; 573 siginfo.si_isr = 0; 574 siginfo.si_imm = 0; 575 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); 576 force_sig_info(SIGILL, &siginfo, current); 577 return; 578 } 579 sprintf(buf, "Unimplemented Instruction Address fault"); 580 break; 581 582 case 45: 583#ifdef CONFIG_IA32_SUPPORT 584 if (ia32_exception(regs, isr) == 0) 585 return; 586#endif 587 printk("Unexpected IA-32 exception (Trap 45)\n"); 588 printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr); 589 force_sig(SIGSEGV, current); 590 break; 591 592 case 46: 593#ifdef CONFIG_IA32_SUPPORT 594 if (ia32_intercept(regs, isr) == 0) 595 return; 596#endif 597 printk("Unexpected IA-32 intercept trap (Trap 46)\n"); 598 printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", 599 regs->cr_iip, ifa, isr, iim); 600 force_sig(SIGSEGV, current); 601 return; 602 603 case 47: 604 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16); 605 break; 606 607 default: 608 sprintf(buf, "Fault %lu", vector); 609 break; 610 } 611 die_if_kernel(buf, regs, error); 612 force_sig(SIGILL, current); 613} 614