In do_ade(), is_fpu_owner() isn't preempt-safe. For example, when an unaligned ldc1 is executed, do_cpu() is called and then FPU is enabled (TIF_USEDFPU is set for the current process). Then, do_ade() is called because the access is unaligned. If the current process is preempted at this time, TIF_USEDFPU will be cleard. When the process is scheduled again, BUG_ON(!is_fpu_owner()) is triggered. This small program can trigger this BUG in a preemptible kernel: --- int main (int argc, char *argv[]) { double u64[2]; while (1) { asm volatile ( ".set push \n\t" ".set noreorder \n\t" "ldc1 $f3, 4(%0) \n\t" ".set pop \n\t" ::"r"(u64): ); } return 0; } --- Signed-off-by: Huacai Chen <chenhc@xxxxxxxxxx> Signed-off-by: Jie Chen <chenj@xxxxxxxxxx> Signed-off-by: Rui Wang <wangr@xxxxxxxxxx> --- arch/mips/kernel/unaligned.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 2b35172..a6ff3c2 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -690,7 +690,8 @@ static void emulate_load_store_insn(struct pt_regs *regs, case sdc1_op: die_if_kernel("Unaligned FP access in kernel code", regs); BUG_ON(!used_math()); - BUG_ON(!is_fpu_owner()); + if (!preemptible()) + BUG_ON(!is_fpu_owner()); lose_fpu(1); /* Save FPU state for the emulator. */ res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, -- 1.9.0