aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/alignment.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2008-12-15 17:13:26 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-12-15 17:13:26 -0500
commit7e1548a597ef7e26d5d62f8be3be6da9e101b26c (patch)
treefe6cbf4d9a3c1afdba04fb276fef0f932403727c /arch/arm/mm/alignment.c
parent1f7f569c0ae6e619504095eabf796edd712d943d (diff)
parent2619bc327417f549f1c89d5ef9b4a4aa768f41a2 (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/alignment.c')
-rw-r--r--arch/arm/mm/alignment.c26
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;
71static unsigned long ai_multi; 71static unsigned long ai_multi;
72static int ai_usermode; 72static 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
75static const char *usermode_action[] = { 79static 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