aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/unaligned.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r--arch/mips/kernel/unaligned.c41
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 91enum {
91unsigned long unaligned_instructions; 92 UNALIGNED_ACTION_QUIET,
93 UNALIGNED_ACTION_SIGNAL,
94 UNALIGNED_ACTION_SHOW,
95};
96#ifdef CONFIG_DEBUG_FS
97static u32 unaligned_instructions;
98static u32 unaligned_action;
99#else
100#define unaligned_action UNALIGNED_ACTION_QUIET
92#endif 101#endif
102extern void show_registers(struct pt_regs *regs);
93 103
94static inline int emulate_load_store_insn(struct pt_regs *regs, 104static 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
565extern struct dentry *mips_debugfs_dir;
566static 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