diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-06-29 11:55:48 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-07-10 12:33:04 -0400 |
commit | 6312e0ee45236b6882cd26b2ccc167b1b91646fc (patch) | |
tree | 1c5d17522d4232e4ee40512afffb199e7c99f6ce /arch/mips | |
parent | 2db30150fe4fe309c57087c661209c9ea0b5c21b (diff) |
[MIPS] Add some debugfs files to debug unaligned accesses
Currently a number of unaligned instructions is counted but not used.
Add /debug/mips/unaligned_instructions file to show the value.
And add /debug/mips/unaligned_action to control behavior upon an
unaligned access. Possible actions are:
0: silently fixup the unaligned access.
1: send SIGBUS.
2: dump registers, process name, etc. and fixup.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/setup.c | 16 | ||||
-rw-r--r-- | arch/mips/kernel/unaligned.c | 41 |
2 files changed, 54 insertions, 3 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 4975da0bfb63..316685fca059 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/pfn.h> | 22 | #include <linux/pfn.h> |
23 | #include <linux/debugfs.h> | ||
23 | 24 | ||
24 | #include <asm/addrspace.h> | 25 | #include <asm/addrspace.h> |
25 | #include <asm/bootinfo.h> | 26 | #include <asm/bootinfo.h> |
@@ -574,3 +575,18 @@ __setup("nodsp", dsp_disable); | |||
574 | 575 | ||
575 | unsigned long kernelsp[NR_CPUS]; | 576 | unsigned long kernelsp[NR_CPUS]; |
576 | unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; | 577 | unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3; |
578 | |||
579 | #ifdef CONFIG_DEBUG_FS | ||
580 | struct dentry *mips_debugfs_dir; | ||
581 | static int __init debugfs_mips(void) | ||
582 | { | ||
583 | struct dentry *d; | ||
584 | |||
585 | d = debugfs_create_dir("mips", NULL); | ||
586 | if (IS_ERR(d)) | ||
587 | return PTR_ERR(d); | ||
588 | mips_debugfs_dir = d; | ||
589 | return 0; | ||
590 | } | ||
591 | arch_initcall(debugfs_mips); | ||
592 | #endif | ||
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 | ||