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 | ||
