diff options
| -rw-r--r-- | arch/arm/mm/alignment.c | 19 | 
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index d073b64ae87..724ba3bce72 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)  	if (ai_usermode & UM_SIGNAL)  		force_sig(SIGBUS, current); -	else -		set_cr(cr_no_alignment); +	else { +		/* +		 * We're about to disable the alignment trap and return to +		 * user space.  But if an interrupt occurs before actually +		 * reaching user space, then the IRQ vector entry code will +		 * notice that we were still in kernel space and therefore +		 * the alignment trap won't be re-enabled in that case as it +		 * is presumed to be always on from kernel space. +		 * Let's prevent that race by disabling interrupts here (they +		 * are disabled on the way back to user space anyway in +		 * entry-common.S) and disable the alignment trap only if +		 * there is no work pending for this thread. +		 */ +		raw_local_irq_disable(); +		if (!(current_thread_info()->flags & _TIF_WORK_MASK)) +			set_cr(cr_no_alignment); +	}  	return 0;  }  |