[PATCH] Kprobes: prevent possible race conditions ia64 changes
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / ia64 / kernel / traps.c
blobf970359e7edf2fbb67117695c2f7b1a25f86b4d0
1 /*
2 * Architecture-specific trap handling.
4 * Copyright (C) 1998-2003 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com>
7 * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
8 */
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <linux/tty.h>
15 #include <linux/vt_kern.h> /* For unblank_screen() */
16 #include <linux/module.h> /* for EXPORT_SYMBOL */
17 #include <linux/hardirq.h>
18 #include <linux/kprobes.h>
20 #include <asm/fpswa.h>
21 #include <asm/ia32.h>
22 #include <asm/intrinsics.h>
23 #include <asm/processor.h>
24 #include <asm/uaccess.h>
25 #include <asm/kdebug.h>
27 extern spinlock_t timerlist_lock;
29 fpswa_interface_t *fpswa_interface;
30 EXPORT_SYMBOL(fpswa_interface);
32 struct notifier_block *ia64die_chain;
33 static DEFINE_SPINLOCK(die_notifier_lock);
35 int register_die_notifier(struct notifier_block *nb)
37 int err = 0;
38 unsigned long flags;
39 spin_lock_irqsave(&die_notifier_lock, flags);
40 err = notifier_chain_register(&ia64die_chain, nb);
41 spin_unlock_irqrestore(&die_notifier_lock, flags);
42 return err;
45 void __init
46 trap_init (void)
48 if (ia64_boot_param->fpswa)
49 /* FPSWA fixup: make the interface pointer a kernel virtual address: */
50 fpswa_interface = __va(ia64_boot_param->fpswa);
54 * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
55 * is acquired through the console unblank code)
57 void
58 bust_spinlocks (int yes)
60 int loglevel_save = console_loglevel;
62 if (yes) {
63 oops_in_progress = 1;
64 return;
67 #ifdef CONFIG_VT
68 unblank_screen();
69 #endif
70 oops_in_progress = 0;
72 * OK, the message is on the console. Now we call printk() without
73 * oops_in_progress set so that printk will give klogd a poke. Hold onto
74 * your hats...
76 console_loglevel = 15; /* NMI oopser may have shut the console up */
77 printk(" ");
78 console_loglevel = loglevel_save;
81 void
82 die (const char *str, struct pt_regs *regs, long err)
84 static struct {
85 spinlock_t lock;
86 u32 lock_owner;
87 int lock_owner_depth;
88 } die = {
89 .lock = SPIN_LOCK_UNLOCKED,
90 .lock_owner = -1,
91 .lock_owner_depth = 0
93 static int die_counter;
94 int cpu = get_cpu();
96 if (die.lock_owner != cpu) {
97 console_verbose();
98 spin_lock_irq(&die.lock);
99 die.lock_owner = cpu;
100 die.lock_owner_depth = 0;
101 bust_spinlocks(1);
103 put_cpu();
105 if (++die.lock_owner_depth < 3) {
106 printk("%s[%d]: %s %ld [%d]\n",
107 current->comm, current->pid, str, err, ++die_counter);
108 show_regs(regs);
109 } else
110 printk(KERN_ERR "Recursive die() failure, output suppressed\n");
112 bust_spinlocks(0);
113 die.lock_owner = -1;
114 spin_unlock_irq(&die.lock);
115 do_exit(SIGSEGV);
118 void
119 die_if_kernel (char *str, struct pt_regs *regs, long err)
121 if (!user_mode(regs))
122 die(str, regs, err);
125 void
126 __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
128 siginfo_t siginfo;
129 int sig, code;
131 /* break.b always sets cr.iim to 0, which causes problems for
132 * debuggers. Get the real break number from the original instruction,
133 * but only for kernel code. User space break.b is left alone, to
134 * preserve the existing behaviour. All break codings have the same
135 * format, so there is no need to check the slot type.
137 if (break_num == 0 && !user_mode(regs)) {
138 struct ia64_psr *ipsr = ia64_psr(regs);
139 unsigned long *bundle = (unsigned long *)regs->cr_iip;
140 unsigned long slot;
141 switch (ipsr->ri) {
142 case 0: slot = (bundle[0] >> 5); break;
143 case 1: slot = (bundle[0] >> 46) | (bundle[1] << 18); break;
144 default: slot = (bundle[1] >> 23); break;
146 break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff);
149 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
150 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
151 siginfo.si_imm = break_num;
152 siginfo.si_flags = 0; /* clear __ISR_VALID */
153 siginfo.si_isr = 0;
155 switch (break_num) {
156 case 0: /* unknown error (used by GCC for __builtin_abort()) */
157 if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
158 == NOTIFY_STOP) {
159 return;
161 die_if_kernel("bugcheck!", regs, break_num);
162 sig = SIGILL; code = ILL_ILLOPC;
163 break;
165 case 1: /* integer divide by zero */
166 sig = SIGFPE; code = FPE_INTDIV;
167 break;
169 case 2: /* integer overflow */
170 sig = SIGFPE; code = FPE_INTOVF;
171 break;
173 case 3: /* range check/bounds check */
174 sig = SIGFPE; code = FPE_FLTSUB;
175 break;
177 case 4: /* null pointer dereference */
178 sig = SIGSEGV; code = SEGV_MAPERR;
179 break;
181 case 5: /* misaligned data */
182 sig = SIGSEGV; code = BUS_ADRALN;
183 break;
185 case 6: /* decimal overflow */
186 sig = SIGFPE; code = __FPE_DECOVF;
187 break;
189 case 7: /* decimal divide by zero */
190 sig = SIGFPE; code = __FPE_DECDIV;
191 break;
193 case 8: /* packed decimal error */
194 sig = SIGFPE; code = __FPE_DECERR;
195 break;
197 case 9: /* invalid ASCII digit */
198 sig = SIGFPE; code = __FPE_INVASC;
199 break;
201 case 10: /* invalid decimal digit */
202 sig = SIGFPE; code = __FPE_INVDEC;
203 break;
205 case 11: /* paragraph stack overflow */
206 sig = SIGSEGV; code = __SEGV_PSTKOVF;
207 break;
209 case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
210 sig = SIGILL; code = __ILL_BNDMOD;
211 break;
213 case 0x80200:
214 case 0x80300:
215 if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP)
216 == NOTIFY_STOP) {
217 return;
219 sig = SIGTRAP; code = TRAP_BRKPT;
220 break;
222 default:
223 if (break_num < 0x40000 || break_num > 0x100000)
224 die_if_kernel("Bad break", regs, break_num);
226 if (break_num < 0x80000) {
227 sig = SIGILL; code = __ILL_BREAK;
228 } else {
229 sig = SIGTRAP; code = TRAP_BRKPT;
232 siginfo.si_signo = sig;
233 siginfo.si_errno = 0;
234 siginfo.si_code = code;
235 force_sig_info(sig, &siginfo, current);
239 * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
240 * and it doesn't own the fp-high register partition. When this happens, we save the
241 * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
242 * the fp-high partition of the current task (if necessary). Note that the kernel has
243 * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
244 * care of clearing psr.dfh.
246 static inline void
247 disabled_fph_fault (struct pt_regs *regs)
249 struct ia64_psr *psr = ia64_psr(regs);
251 /* first, grant user-level access to fph partition: */
252 psr->dfh = 0;
255 * Make sure that no other task gets in on this processor
256 * while we're claiming the FPU
258 preempt_disable();
259 #ifndef CONFIG_SMP
261 struct task_struct *fpu_owner
262 = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
264 if (ia64_is_local_fpu_owner(current)) {
265 preempt_enable_no_resched();
266 return;
269 if (fpu_owner)
270 ia64_flush_fph(fpu_owner);
272 #endif /* !CONFIG_SMP */
273 ia64_set_local_fpu_owner(current);
274 if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
275 __ia64_load_fpu(current->thread.fph);
276 psr->mfh = 0;
277 } else {
278 __ia64_init_fpu();
280 * Set mfh because the state in thread.fph does not match the state in
281 * the fph partition.
283 psr->mfh = 1;
285 preempt_enable_no_resched();
288 static inline int
289 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
290 struct pt_regs *regs)
292 fp_state_t fp_state;
293 fpswa_ret_t ret;
295 if (!fpswa_interface)
296 return -1;
298 memset(&fp_state, 0, sizeof(fp_state_t));
301 * compute fp_state. only FP registers f6 - f11 are used by the
302 * kernel, so set those bits in the mask and set the low volatile
303 * pointer to point to these registers.
305 fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
307 fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
309 * unsigned long (*EFI_FPSWA) (
310 * unsigned long trap_type,
311 * void *Bundle,
312 * unsigned long *pipsr,
313 * unsigned long *pfsr,
314 * unsigned long *pisr,
315 * unsigned long *ppreds,
316 * unsigned long *pifs,
317 * void *fp_state);
319 ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
320 (unsigned long *) ipsr, (unsigned long *) fpsr,
321 (unsigned long *) isr, (unsigned long *) pr,
322 (unsigned long *) ifs, &fp_state);
324 return ret.status;
328 * Handle floating-point assist faults and traps.
330 static int
331 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
333 long exception, bundle[2];
334 unsigned long fault_ip;
335 struct siginfo siginfo;
336 static int fpu_swa_count = 0;
337 static unsigned long last_time;
339 fault_ip = regs->cr_iip;
340 if (!fp_fault && (ia64_psr(regs)->ri == 0))
341 fault_ip -= 16;
342 if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
343 return -1;
345 if (jiffies - last_time > 5*HZ)
346 fpu_swa_count = 0;
347 if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
348 last_time = jiffies;
349 ++fpu_swa_count;
350 printk(KERN_WARNING
351 "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
352 current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
355 exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
356 &regs->cr_ifs, regs);
357 if (fp_fault) {
358 if (exception == 0) {
359 /* emulation was successful */
360 ia64_increment_ip(regs);
361 } else if (exception == -1) {
362 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
363 return -1;
364 } else {
365 /* is next instruction a trap? */
366 if (exception & 2) {
367 ia64_increment_ip(regs);
369 siginfo.si_signo = SIGFPE;
370 siginfo.si_errno = 0;
371 siginfo.si_code = __SI_FAULT; /* default code */
372 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
373 if (isr & 0x11) {
374 siginfo.si_code = FPE_FLTINV;
375 } else if (isr & 0x22) {
376 /* denormal operand gets the same si_code as underflow
377 * see arch/i386/kernel/traps.c:math_error() */
378 siginfo.si_code = FPE_FLTUND;
379 } else if (isr & 0x44) {
380 siginfo.si_code = FPE_FLTDIV;
382 siginfo.si_isr = isr;
383 siginfo.si_flags = __ISR_VALID;
384 siginfo.si_imm = 0;
385 force_sig_info(SIGFPE, &siginfo, current);
387 } else {
388 if (exception == -1) {
389 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
390 return -1;
391 } else if (exception != 0) {
392 /* raise exception */
393 siginfo.si_signo = SIGFPE;
394 siginfo.si_errno = 0;
395 siginfo.si_code = __SI_FAULT; /* default code */
396 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
397 if (isr & 0x880) {
398 siginfo.si_code = FPE_FLTOVF;
399 } else if (isr & 0x1100) {
400 siginfo.si_code = FPE_FLTUND;
401 } else if (isr & 0x2200) {
402 siginfo.si_code = FPE_FLTRES;
404 siginfo.si_isr = isr;
405 siginfo.si_flags = __ISR_VALID;
406 siginfo.si_imm = 0;
407 force_sig_info(SIGFPE, &siginfo, current);
410 return 0;
413 struct illegal_op_return {
414 unsigned long fkt, arg1, arg2, arg3;
417 struct illegal_op_return
418 ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
419 long arg4, long arg5, long arg6, long arg7,
420 struct pt_regs regs)
422 struct illegal_op_return rv;
423 struct siginfo si;
424 char buf[128];
426 #ifdef CONFIG_IA64_BRL_EMU
428 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
430 rv = ia64_emulate_brl(&regs, ec);
431 if (rv.fkt != (unsigned long) -1)
432 return rv;
434 #endif
436 sprintf(buf, "IA-64 Illegal operation fault");
437 die_if_kernel(buf, &regs, 0);
439 memset(&si, 0, sizeof(si));
440 si.si_signo = SIGILL;
441 si.si_code = ILL_ILLOPC;
442 si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
443 force_sig_info(SIGILL, &si, current);
444 rv.fkt = 0;
445 return rv;
448 void __kprobes
449 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
450 unsigned long iim, unsigned long itir, long arg5, long arg6,
451 long arg7, struct pt_regs regs)
453 unsigned long code, error = isr, iip;
454 struct siginfo siginfo;
455 char buf[128];
456 int result, sig;
457 static const char *reason[] = {
458 "IA-64 Illegal Operation fault",
459 "IA-64 Privileged Operation fault",
460 "IA-64 Privileged Register fault",
461 "IA-64 Reserved Register/Field fault",
462 "Disabled Instruction Set Transition fault",
463 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
464 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
465 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
468 if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
470 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
471 * the lfetch.
473 ia64_psr(&regs)->ed = 1;
474 return;
477 iip = regs.cr_iip + ia64_psr(&regs)->ri;
479 switch (vector) {
480 case 24: /* General Exception */
481 code = (isr >> 4) & 0xf;
482 sprintf(buf, "General Exception: %s%s", reason[code],
483 (code == 3) ? ((isr & (1UL << 37))
484 ? " (RSE access)" : " (data access)") : "");
485 if (code == 8) {
486 # ifdef CONFIG_IA64_PRINT_HAZARDS
487 printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
488 current->comm, current->pid,
489 regs.cr_iip + ia64_psr(&regs)->ri, regs.pr);
490 # endif
491 return;
493 break;
495 case 25: /* Disabled FP-Register */
496 if (isr & 2) {
497 disabled_fph_fault(&regs);
498 return;
500 sprintf(buf, "Disabled FPL fault---not supposed to happen!");
501 break;
503 case 26: /* NaT Consumption */
504 if (user_mode(&regs)) {
505 void __user *addr;
507 if (((isr >> 4) & 0xf) == 2) {
508 /* NaT page consumption */
509 sig = SIGSEGV;
510 code = SEGV_ACCERR;
511 addr = (void __user *) ifa;
512 } else {
513 /* register NaT consumption */
514 sig = SIGILL;
515 code = ILL_ILLOPN;
516 addr = (void __user *) (regs.cr_iip
517 + ia64_psr(&regs)->ri);
519 siginfo.si_signo = sig;
520 siginfo.si_code = code;
521 siginfo.si_errno = 0;
522 siginfo.si_addr = addr;
523 siginfo.si_imm = vector;
524 siginfo.si_flags = __ISR_VALID;
525 siginfo.si_isr = isr;
526 force_sig_info(sig, &siginfo, current);
527 return;
528 } else if (ia64_done_with_exception(&regs))
529 return;
530 sprintf(buf, "NaT consumption");
531 break;
533 case 31: /* Unsupported Data Reference */
534 if (user_mode(&regs)) {
535 siginfo.si_signo = SIGILL;
536 siginfo.si_code = ILL_ILLOPN;
537 siginfo.si_errno = 0;
538 siginfo.si_addr = (void __user *) iip;
539 siginfo.si_imm = vector;
540 siginfo.si_flags = __ISR_VALID;
541 siginfo.si_isr = isr;
542 force_sig_info(SIGILL, &siginfo, current);
543 return;
545 sprintf(buf, "Unsupported data reference");
546 break;
548 case 29: /* Debug */
549 case 35: /* Taken Branch Trap */
550 case 36: /* Single Step Trap */
551 if (fsys_mode(current, &regs)) {
552 extern char __kernel_syscall_via_break[];
554 * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
555 * need special handling; Debug trap is not supposed to happen.
557 if (unlikely(vector == 29)) {
558 die("Got debug trap in fsys-mode---not supposed to happen!",
559 &regs, 0);
560 return;
562 /* re-do the system call via break 0x100000: */
563 regs.cr_iip = (unsigned long) __kernel_syscall_via_break;
564 ia64_psr(&regs)->ri = 0;
565 ia64_psr(&regs)->cpl = 3;
566 return;
568 switch (vector) {
569 case 29:
570 siginfo.si_code = TRAP_HWBKPT;
571 #ifdef CONFIG_ITANIUM
573 * Erratum 10 (IFA may contain incorrect address) now has
574 * "NoFix" status. There are no plans for fixing this.
576 if (ia64_psr(&regs)->is == 0)
577 ifa = regs.cr_iip;
578 #endif
579 break;
580 case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
581 case 36:
582 if (notify_die(DIE_SS, "ss", &regs, vector,
583 vector, SIGTRAP) == NOTIFY_STOP)
584 return;
585 siginfo.si_code = TRAP_TRACE; ifa = 0; break;
587 siginfo.si_signo = SIGTRAP;
588 siginfo.si_errno = 0;
589 siginfo.si_addr = (void __user *) ifa;
590 siginfo.si_imm = 0;
591 siginfo.si_flags = __ISR_VALID;
592 siginfo.si_isr = isr;
593 force_sig_info(SIGTRAP, &siginfo, current);
594 return;
596 case 32: /* fp fault */
597 case 33: /* fp trap */
598 result = handle_fpu_swa((vector == 32) ? 1 : 0, &regs, isr);
599 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
600 siginfo.si_signo = SIGFPE;
601 siginfo.si_errno = 0;
602 siginfo.si_code = FPE_FLTINV;
603 siginfo.si_addr = (void __user *) iip;
604 siginfo.si_flags = __ISR_VALID;
605 siginfo.si_isr = isr;
606 siginfo.si_imm = 0;
607 force_sig_info(SIGFPE, &siginfo, current);
609 return;
611 case 34:
612 if (isr & 0x2) {
613 /* Lower-Privilege Transfer Trap */
615 * Just clear PSR.lp and then return immediately: all the
616 * interesting work (e.g., signal delivery is done in the kernel
617 * exit path).
619 ia64_psr(&regs)->lp = 0;
620 return;
621 } else {
622 /* Unimplemented Instr. Address Trap */
623 if (user_mode(&regs)) {
624 siginfo.si_signo = SIGILL;
625 siginfo.si_code = ILL_BADIADDR;
626 siginfo.si_errno = 0;
627 siginfo.si_flags = 0;
628 siginfo.si_isr = 0;
629 siginfo.si_imm = 0;
630 siginfo.si_addr = (void __user *) iip;
631 force_sig_info(SIGILL, &siginfo, current);
632 return;
634 sprintf(buf, "Unimplemented Instruction Address fault");
636 break;
638 case 45:
639 #ifdef CONFIG_IA32_SUPPORT
640 if (ia32_exception(&regs, isr) == 0)
641 return;
642 #endif
643 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
644 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
645 iip, ifa, isr);
646 force_sig(SIGSEGV, current);
647 break;
649 case 46:
650 #ifdef CONFIG_IA32_SUPPORT
651 if (ia32_intercept(&regs, isr) == 0)
652 return;
653 #endif
654 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
655 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
656 iip, ifa, isr, iim);
657 force_sig(SIGSEGV, current);
658 return;
660 case 47:
661 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
662 break;
664 default:
665 sprintf(buf, "Fault %lu", vector);
666 break;
668 die_if_kernel(buf, &regs, error);
669 force_sig(SIGILL, current);