diff options
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r-- | arch/mips/kernel/unaligned.c | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 18c4a3c45a31..8b9c34ffae18 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -77,6 +77,7 @@ | |||
77 | #include <linux/signal.h> | 77 | #include <linux/signal.h> |
78 | #include <linux/smp.h> | 78 | #include <linux/smp.h> |
79 | #include <linux/sched.h> | 79 | #include <linux/sched.h> |
80 | #include <linux/debugfs.h> | ||
80 | #include <asm/asm.h> | 81 | #include <asm/asm.h> |
81 | #include <asm/branch.h> | 82 | #include <asm/branch.h> |
82 | #include <asm/byteorder.h> | 83 | #include <asm/byteorder.h> |
@@ -87,9 +88,18 @@ | |||
87 | #define STR(x) __STR(x) | 88 | #define STR(x) __STR(x) |
88 | #define __STR(x) #x | 89 | #define __STR(x) #x |
89 | 90 | ||
90 | #ifdef CONFIG_PROC_FS | 91 | enum { |
91 | unsigned long unaligned_instructions; | 92 | UNALIGNED_ACTION_QUIET, |
93 | UNALIGNED_ACTION_SIGNAL, | ||
94 | UNALIGNED_ACTION_SHOW, | ||
95 | }; | ||
96 | #ifdef CONFIG_DEBUG_FS | ||
97 | static u32 unaligned_instructions; | ||
98 | static u32 unaligned_action; | ||
99 | #else | ||
100 | #define unaligned_action UNALIGNED_ACTION_QUIET | ||
92 | #endif | 101 | #endif |
102 | extern void show_registers(struct pt_regs *regs); | ||
93 | 103 | ||
94 | static inline int emulate_load_store_insn(struct pt_regs *regs, | 104 | static inline int emulate_load_store_insn(struct pt_regs *regs, |
95 | void __user *addr, unsigned int __user *pc, | 105 | void __user *addr, unsigned int __user *pc, |
@@ -459,7 +469,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs, | |||
459 | goto sigill; | 469 | goto sigill; |
460 | } | 470 | } |
461 | 471 | ||
462 | #ifdef CONFIG_PROC_FS | 472 | #ifdef CONFIG_DEBUG_FS |
463 | unaligned_instructions++; | 473 | unaligned_instructions++; |
464 | #endif | 474 | #endif |
465 | 475 | ||
@@ -516,6 +526,10 @@ asmlinkage void do_ade(struct pt_regs *regs) | |||
516 | pc = (unsigned int __user *) exception_epc(regs); | 526 | pc = (unsigned int __user *) exception_epc(regs); |
517 | if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0) | 527 | if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0) |
518 | goto sigbus; | 528 | goto sigbus; |
529 | if (unaligned_action == UNALIGNED_ACTION_SIGNAL) | ||
530 | goto sigbus; | ||
531 | else if (unaligned_action == UNALIGNED_ACTION_SHOW) | ||
532 | show_registers(regs); | ||
519 | 533 | ||
520 | /* | 534 | /* |
521 | * Do branch emulation only if we didn't forward the exception. | 535 | * Do branch emulation only if we didn't forward the exception. |
@@ -546,3 +560,24 @@ sigbus: | |||
546 | * XXX On return from the signal handler we should advance the epc | 560 | * XXX On return from the signal handler we should advance the epc |
547 | */ | 561 | */ |
548 | } | 562 | } |
563 | |||
564 | #ifdef CONFIG_DEBUG_FS | ||
565 | extern struct dentry *mips_debugfs_dir; | ||
566 | static int __init debugfs_unaligned(void) | ||
567 | { | ||
568 | struct dentry *d; | ||
569 | |||
570 | if (!mips_debugfs_dir) | ||
571 | return -ENODEV; | ||
572 | d = debugfs_create_u32("unaligned_instructions", S_IRUGO, | ||
573 | mips_debugfs_dir, &unaligned_instructions); | ||
574 | if (IS_ERR(d)) | ||
575 | return PTR_ERR(d); | ||
576 | d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR, | ||
577 | mips_debugfs_dir, &unaligned_action); | ||
578 | if (IS_ERR(d)) | ||
579 | return PTR_ERR(d); | ||
580 | return 0; | ||
581 | } | ||
582 | __initcall(debugfs_unaligned); | ||
583 | #endif | ||