diff options
Diffstat (limited to 'arch/arm/mm/fault.c')
-rw-r--r-- | arch/arm/mm/fault.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index e25b4fd8412c..65bfe84b6d67 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -372,49 +372,50 @@ do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
372 | static struct fsr_info { | 372 | static struct fsr_info { |
373 | int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); | 373 | int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs); |
374 | int sig; | 374 | int sig; |
375 | int code; | ||
375 | const char *name; | 376 | const char *name; |
376 | } fsr_info[] = { | 377 | } fsr_info[] = { |
377 | /* | 378 | /* |
378 | * The following are the standard ARMv3 and ARMv4 aborts. ARMv5 | 379 | * The following are the standard ARMv3 and ARMv4 aborts. ARMv5 |
379 | * defines these to be "precise" aborts. | 380 | * defines these to be "precise" aborts. |
380 | */ | 381 | */ |
381 | { do_bad, SIGSEGV, "vector exception" }, | 382 | { do_bad, SIGSEGV, 0, "vector exception" }, |
382 | { do_bad, SIGILL, "alignment exception" }, | 383 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, |
383 | { do_bad, SIGKILL, "terminal exception" }, | 384 | { do_bad, SIGKILL, 0, "terminal exception" }, |
384 | { do_bad, SIGILL, "alignment exception" }, | 385 | { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, |
385 | { do_bad, SIGBUS, "external abort on linefetch" }, | 386 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, |
386 | { do_translation_fault, SIGSEGV, "section translation fault" }, | 387 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, |
387 | { do_bad, SIGBUS, "external abort on linefetch" }, | 388 | { do_bad, SIGBUS, 0, "external abort on linefetch" }, |
388 | { do_page_fault, SIGSEGV, "page translation fault" }, | 389 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, |
389 | { do_bad, SIGBUS, "external abort on non-linefetch" }, | 390 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, |
390 | { do_bad, SIGSEGV, "section domain fault" }, | 391 | { do_bad, SIGSEGV, SEGV_ACCERR, "section domain fault" }, |
391 | { do_bad, SIGBUS, "external abort on non-linefetch" }, | 392 | { do_bad, SIGBUS, 0, "external abort on non-linefetch" }, |
392 | { do_bad, SIGSEGV, "page domain fault" }, | 393 | { do_bad, SIGSEGV, SEGV_ACCERR, "page domain fault" }, |
393 | { do_bad, SIGBUS, "external abort on translation" }, | 394 | { do_bad, SIGBUS, 0, "external abort on translation" }, |
394 | { do_sect_fault, SIGSEGV, "section permission fault" }, | 395 | { do_sect_fault, SIGSEGV, SEGV_ACCERR, "section permission fault" }, |
395 | { do_bad, SIGBUS, "external abort on translation" }, | 396 | { do_bad, SIGBUS, 0, "external abort on translation" }, |
396 | { do_page_fault, SIGSEGV, "page permission fault" }, | 397 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "page permission fault" }, |
397 | /* | 398 | /* |
398 | * The following are "imprecise" aborts, which are signalled by bit | 399 | * The following are "imprecise" aborts, which are signalled by bit |
399 | * 10 of the FSR, and may not be recoverable. These are only | 400 | * 10 of the FSR, and may not be recoverable. These are only |
400 | * supported if the CPU abort handler supports bit 10. | 401 | * supported if the CPU abort handler supports bit 10. |
401 | */ | 402 | */ |
402 | { do_bad, SIGBUS, "unknown 16" }, | 403 | { do_bad, SIGBUS, 0, "unknown 16" }, |
403 | { do_bad, SIGBUS, "unknown 17" }, | 404 | { do_bad, SIGBUS, 0, "unknown 17" }, |
404 | { do_bad, SIGBUS, "unknown 18" }, | 405 | { do_bad, SIGBUS, 0, "unknown 18" }, |
405 | { do_bad, SIGBUS, "unknown 19" }, | 406 | { do_bad, SIGBUS, 0, "unknown 19" }, |
406 | { do_bad, SIGBUS, "lock abort" }, /* xscale */ | 407 | { do_bad, SIGBUS, 0, "lock abort" }, /* xscale */ |
407 | { do_bad, SIGBUS, "unknown 21" }, | 408 | { do_bad, SIGBUS, 0, "unknown 21" }, |
408 | { do_bad, SIGBUS, "imprecise external abort" }, /* xscale */ | 409 | { do_bad, SIGBUS, BUS_OBJERR, "imprecise external abort" }, /* xscale */ |
409 | { do_bad, SIGBUS, "unknown 23" }, | 410 | { do_bad, SIGBUS, 0, "unknown 23" }, |
410 | { do_bad, SIGBUS, "dcache parity error" }, /* xscale */ | 411 | { do_bad, SIGBUS, 0, "dcache parity error" }, /* xscale */ |
411 | { do_bad, SIGBUS, "unknown 25" }, | 412 | { do_bad, SIGBUS, 0, "unknown 25" }, |
412 | { do_bad, SIGBUS, "unknown 26" }, | 413 | { do_bad, SIGBUS, 0, "unknown 26" }, |
413 | { do_bad, SIGBUS, "unknown 27" }, | 414 | { do_bad, SIGBUS, 0, "unknown 27" }, |
414 | { do_bad, SIGBUS, "unknown 28" }, | 415 | { do_bad, SIGBUS, 0, "unknown 28" }, |
415 | { do_bad, SIGBUS, "unknown 29" }, | 416 | { do_bad, SIGBUS, 0, "unknown 29" }, |
416 | { do_bad, SIGBUS, "unknown 30" }, | 417 | { do_bad, SIGBUS, 0, "unknown 30" }, |
417 | { do_bad, SIGBUS, "unknown 31" } | 418 | { do_bad, SIGBUS, 0, "unknown 31" } |
418 | }; | 419 | }; |
419 | 420 | ||
420 | void __init | 421 | void __init |
@@ -435,15 +436,19 @@ asmlinkage void | |||
435 | do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | 436 | do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) |
436 | { | 437 | { |
437 | const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6); | 438 | const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6); |
439 | struct siginfo info; | ||
438 | 440 | ||
439 | if (!inf->fn(addr, fsr, regs)) | 441 | if (!inf->fn(addr, fsr, regs)) |
440 | return; | 442 | return; |
441 | 443 | ||
442 | printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", | 444 | printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", |
443 | inf->name, fsr, addr); | 445 | inf->name, fsr, addr); |
444 | force_sig(inf->sig, current); | 446 | |
445 | show_pte(current->mm, addr); | 447 | info.si_signo = inf->sig; |
446 | die_if_kernel("Oops", regs, 0); | 448 | info.si_errno = 0; |
449 | info.si_code = inf->code; | ||
450 | info.si_addr = (void __user *)addr; | ||
451 | notify_die("", regs, &info, fsr, 0); | ||
447 | } | 452 | } |
448 | 453 | ||
449 | asmlinkage void | 454 | asmlinkage void |