diff options
author | Andre Draszik <andre.draszik@st.com> | 2009-08-24 02:01:10 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-08-24 02:01:10 -0400 |
commit | 5a0ab35e43a6e3c69893c0091fe6a78ea8b3e443 (patch) | |
tree | fe45c2734484f8889e824a5045170bd4b64db975 /arch/sh/kernel/traps_32.c | |
parent | 7436cde6b2ca71049051620c68c26522bb3403bf (diff) |
sh: cleanup of do_address_error()
This patch fixes a few problems with the existing code in do_address_error().
a) the variable used to printk()d the offending instruction wasn't
initialized correctly. This is a fix to bug 5727
b) behaviour for CONFIG_CPU_SH2A wasn't correct
c) the 'ignore address error' behaviour didn't update the PC, causing an
infinite loop.
Signed-off-by: Andre Draszik <andre.draszik@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/traps_32.c')
-rw-r--r-- | arch/sh/kernel/traps_32.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 0ad356d00ac8..c581dc31d92a 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -621,12 +621,21 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
621 | 621 | ||
622 | se_user += 1; | 622 | se_user += 1; |
623 | 623 | ||
624 | #ifndef CONFIG_CPU_SH2A | ||
625 | set_fs(USER_DS); | ||
626 | if (copy_from_user(&instruction, (u16 *)(regs->pc & ~1), 2)) { | ||
627 | set_fs(oldfs); | ||
628 | goto uspace_segv; | ||
629 | } | ||
630 | set_fs(oldfs); | ||
631 | |||
624 | /* shout about userspace fixups */ | 632 | /* shout about userspace fixups */ |
625 | if (se_usermode & 1) | 633 | if (se_usermode & 1) |
626 | printk(KERN_NOTICE "Unaligned userspace access " | 634 | printk(KERN_NOTICE "Unaligned userspace access " |
627 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | 635 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", |
628 | current->comm, current->pid, (void *)regs->pc, | 636 | current->comm, current->pid, (void *)regs->pc, |
629 | instruction); | 637 | instruction); |
638 | #endif | ||
630 | 639 | ||
631 | if (se_usermode & 2) | 640 | if (se_usermode & 2) |
632 | goto fixup; | 641 | goto fixup; |
@@ -635,7 +644,7 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
635 | goto uspace_segv; | 644 | goto uspace_segv; |
636 | else { | 645 | else { |
637 | /* ignore */ | 646 | /* ignore */ |
638 | trace_mark(kernel_arch_trap_exit, MARK_NOARGS); | 647 | regs->pc += instruction_size(instruction); |
639 | return; | 648 | return; |
640 | } | 649 | } |
641 | 650 | ||
@@ -647,15 +656,6 @@ fixup: | |||
647 | } | 656 | } |
648 | 657 | ||
649 | set_fs(USER_DS); | 658 | set_fs(USER_DS); |
650 | if (copy_from_user(&instruction, (void __user *)(regs->pc), | ||
651 | sizeof(instruction))) { | ||
652 | /* Argh. Fault on the instruction itself. | ||
653 | This should never happen non-SMP | ||
654 | */ | ||
655 | set_fs(oldfs); | ||
656 | goto uspace_segv; | ||
657 | } | ||
658 | |||
659 | tmp = handle_unaligned_access(instruction, regs, | 659 | tmp = handle_unaligned_access(instruction, regs, |
660 | &user_mem_access); | 660 | &user_mem_access); |
661 | set_fs(oldfs); | 661 | set_fs(oldfs); |