[ARM] Fix alignment fault handling for ARMv6 and later CPUs

On ARMv6 and later CPUs, it is possible for userspace processes to
get stuck on a misaligned load or store due to the "ignore fault"
setting; unlike previous CPUs, retrying the instruction without
the 'A' bit set does not always cause the load to succeed.

We have no real option but to default to fixing up alignment faults
on these CPUs, and having the CPU fix up those misaligned accesses
which it can.

Reported-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Russell King and committed by Russell King baa745a3 794baba6

+23 -3
+23 -3
arch/arm/mm/alignment.c
··· 70 static unsigned long ai_multi; 71 static int ai_usermode; 72 73 #ifdef CONFIG_PROC_FS 74 static const char *usermode_action[] = { 75 "ignored", ··· 758 user: 759 ai_user += 1; 760 761 - if (ai_usermode & 1) 762 printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " 763 "Address=0x%08lx FSR 0x%03x\n", current->comm, 764 task_pid_nr(current), instrptr, ··· 766 thumb_mode(regs) ? tinstr : instr, 767 addr, fsr); 768 769 - if (ai_usermode & 2) 770 goto fixup; 771 772 - if (ai_usermode & 4) 773 force_sig(SIGBUS, current); 774 else 775 set_cr(cr_no_alignment); ··· 799 res->read_proc = proc_alignment_read; 800 res->write_proc = proc_alignment_write; 801 #endif 802 803 hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); 804 hook_fault_code(3, do_alignment, SIGILL, "alignment exception");
··· 70 static unsigned long ai_multi; 71 static int ai_usermode; 72 73 + #define UM_WARN (1 << 0) 74 + #define UM_FIXUP (1 << 1) 75 + #define UM_SIGNAL (1 << 2) 76 + 77 #ifdef CONFIG_PROC_FS 78 static const char *usermode_action[] = { 79 "ignored", ··· 754 user: 755 ai_user += 1; 756 757 + if (ai_usermode & UM_WARN) 758 printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " 759 "Address=0x%08lx FSR 0x%03x\n", current->comm, 760 task_pid_nr(current), instrptr, ··· 762 thumb_mode(regs) ? tinstr : instr, 763 addr, fsr); 764 765 + if (ai_usermode & UM_FIXUP) 766 goto fixup; 767 768 + if (ai_usermode & UM_SIGNAL) 769 force_sig(SIGBUS, current); 770 else 771 set_cr(cr_no_alignment); ··· 795 res->read_proc = proc_alignment_read; 796 res->write_proc = proc_alignment_write; 797 #endif 798 + 799 + /* 800 + * ARMv6 and later CPUs can perform unaligned accesses for 801 + * most single load and store instructions up to word size. 802 + * LDM, STM, LDRD and STRD still need to be handled. 803 + * 804 + * Ignoring the alignment fault is not an option on these 805 + * CPUs since we spin re-faulting the instruction without 806 + * making any progress. 807 + */ 808 + if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) { 809 + cr_alignment &= ~CR_A; 810 + cr_no_alignment &= ~CR_A; 811 + set_cr(cr_alignment); 812 + ai_usermode = UM_FIXUP; 813 + } 814 815 hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); 816 hook_fault_code(3, do_alignment, SIGILL, "alignment exception");