diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-12-15 17:13:26 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-12-15 17:13:26 -0500 |
commit | 7e1548a597ef7e26d5d62f8be3be6da9e101b26c (patch) | |
tree | fe6cbf4d9a3c1afdba04fb276fef0f932403727c /arch/arm/mm | |
parent | 1f7f569c0ae6e619504095eabf796edd712d943d (diff) | |
parent | 2619bc327417f549f1c89d5ef9b4a4aa768f41a2 (diff) |
Merge branch 'omap3-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6 into devel
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/alignment.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index c5a57fbf095d..3a398befed41 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c | |||
@@ -71,6 +71,10 @@ static unsigned long ai_dword; | |||
71 | static unsigned long ai_multi; | 71 | static unsigned long ai_multi; |
72 | static int ai_usermode; | 72 | static int ai_usermode; |
73 | 73 | ||
74 | #define UM_WARN (1 << 0) | ||
75 | #define UM_FIXUP (1 << 1) | ||
76 | #define UM_SIGNAL (1 << 2) | ||
77 | |||
74 | #ifdef CONFIG_PROC_FS | 78 | #ifdef CONFIG_PROC_FS |
75 | static const char *usermode_action[] = { | 79 | static const char *usermode_action[] = { |
76 | "ignored", | 80 | "ignored", |
@@ -755,7 +759,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
755 | user: | 759 | user: |
756 | ai_user += 1; | 760 | ai_user += 1; |
757 | 761 | ||
758 | if (ai_usermode & 1) | 762 | if (ai_usermode & UM_WARN) |
759 | printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " | 763 | printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " |
760 | "Address=0x%08lx FSR 0x%03x\n", current->comm, | 764 | "Address=0x%08lx FSR 0x%03x\n", current->comm, |
761 | task_pid_nr(current), instrptr, | 765 | task_pid_nr(current), instrptr, |
@@ -763,10 +767,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
763 | thumb_mode(regs) ? tinstr : instr, | 767 | thumb_mode(regs) ? tinstr : instr, |
764 | addr, fsr); | 768 | addr, fsr); |
765 | 769 | ||
766 | if (ai_usermode & 2) | 770 | if (ai_usermode & UM_FIXUP) |
767 | goto fixup; | 771 | goto fixup; |
768 | 772 | ||
769 | if (ai_usermode & 4) | 773 | if (ai_usermode & UM_SIGNAL) |
770 | force_sig(SIGBUS, current); | 774 | force_sig(SIGBUS, current); |
771 | else | 775 | else |
772 | set_cr(cr_no_alignment); | 776 | set_cr(cr_no_alignment); |
@@ -797,6 +801,22 @@ static int __init alignment_init(void) | |||
797 | res->write_proc = proc_alignment_write; | 801 | res->write_proc = proc_alignment_write; |
798 | #endif | 802 | #endif |
799 | 803 | ||
804 | /* | ||
805 | * ARMv6 and later CPUs can perform unaligned accesses for | ||
806 | * most single load and store instructions up to word size. | ||
807 | * LDM, STM, LDRD and STRD still need to be handled. | ||
808 | * | ||
809 | * Ignoring the alignment fault is not an option on these | ||
810 | * CPUs since we spin re-faulting the instruction without | ||
811 | * making any progress. | ||
812 | */ | ||
813 | if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) { | ||
814 | cr_alignment &= ~CR_A; | ||
815 | cr_no_alignment &= ~CR_A; | ||
816 | set_cr(cr_alignment); | ||
817 | ai_usermode = UM_FIXUP; | ||
818 | } | ||
819 | |||
800 | hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); | 820 | hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); |
801 | hook_fault_code(3, do_alignment, SIGILL, "alignment exception"); | 821 | hook_fault_code(3, do_alignment, SIGILL, "alignment exception"); |
802 | 822 | ||