[PATCH] MIPS: Don't BUG_ON(!is_fpu_owner()) in do_ade() when preemptible

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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, &current->thread.fpu, 1,
-- 
1.9.0



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux