Skip to content

Commit

Permalink
[ARM] Fix alignment fault handling for ARMv6 and later CPUs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Russell King authored and Russell King committed Dec 7, 2008
1 parent 794baba commit baa745a
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions arch/arm/mm/alignment.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ static unsigned long ai_dword;
static unsigned long ai_multi;
static int ai_usermode;

#define UM_WARN (1 << 0)
#define UM_FIXUP (1 << 1)
#define UM_SIGNAL (1 << 2)

#ifdef CONFIG_PROC_FS
static const char *usermode_action[] = {
"ignored",
Expand Down Expand Up @@ -754,18 +758,18 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
user:
ai_user += 1;

if (ai_usermode & 1)
if (ai_usermode & UM_WARN)
printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx "
"Address=0x%08lx FSR 0x%03x\n", current->comm,
task_pid_nr(current), instrptr,
thumb_mode(regs) ? 4 : 8,
thumb_mode(regs) ? tinstr : instr,
addr, fsr);

if (ai_usermode & 2)
if (ai_usermode & UM_FIXUP)
goto fixup;

if (ai_usermode & 4)
if (ai_usermode & UM_SIGNAL)
force_sig(SIGBUS, current);
else
set_cr(cr_no_alignment);
Expand Down Expand Up @@ -796,6 +800,22 @@ static int __init alignment_init(void)
res->write_proc = proc_alignment_write;
#endif

/*
* ARMv6 and later CPUs can perform unaligned accesses for
* most single load and store instructions up to word size.
* LDM, STM, LDRD and STRD still need to be handled.
*
* Ignoring the alignment fault is not an option on these
* CPUs since we spin re-faulting the instruction without
* making any progress.
*/
if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) {
cr_alignment &= ~CR_A;
cr_no_alignment &= ~CR_A;
set_cr(cr_alignment);
ai_usermode = UM_FIXUP;
}

hook_fault_code(1, do_alignment, SIGILL, "alignment exception");
hook_fault_code(3, do_alignment, SIGILL, "alignment exception");

Expand Down

0 comments on commit baa745a

Please sign in to comment.