]>
Commit | Line | Data |
---|---|---|
c8fb49aa GKH |
1 | From 2e5767a27337812f6850b3fa362419e2f085e5c3 Mon Sep 17 00:00:00 2001 |
2 | From: Huacai Chen <chenhc@lemote.com> | |
3 | Date: Wed, 16 Jul 2014 09:19:16 +0800 | |
4 | Subject: MIPS: Remove BUG_ON(!is_fpu_owner()) in do_ade() | |
5 | ||
6 | From: Huacai Chen <chenhc@lemote.com> | |
7 | ||
8 | commit 2e5767a27337812f6850b3fa362419e2f085e5c3 upstream. | |
9 | ||
10 | In do_ade(), is_fpu_owner() isn't preempt-safe. For example, when an | |
11 | unaligned ldc1 is executed, do_cpu() is called and then FPU will be | |
12 | enabled (and TIF_USEDFPU will be set for the current process). Then, | |
13 | do_ade() is called because the access is unaligned. If the current | |
14 | process is preempted at this time, TIF_USEDFPU will be cleard. So when | |
15 | the process is scheduled again, BUG_ON(!is_fpu_owner()) is triggered. | |
16 | ||
17 | This small program can trigger this BUG in a preemptible kernel: | |
18 | ||
19 | int main (int argc, char *argv[]) | |
20 | { | |
21 | double u64[2]; | |
22 | ||
23 | while (1) { | |
24 | asm volatile ( | |
25 | ".set push \n\t" | |
26 | ".set noreorder \n\t" | |
27 | "ldc1 $f3, 4(%0) \n\t" | |
28 | ".set pop \n\t" | |
29 | ::"r"(u64): | |
30 | ); | |
31 | } | |
32 | ||
33 | return 0; | |
34 | } | |
35 | ||
36 | V2: Remove the BUG_ON() unconditionally due to Paul's suggestion. | |
37 | ||
38 | Signed-off-by: Huacai Chen <chenhc@lemote.com> | |
39 | Signed-off-by: Jie Chen <chenj@lemote.com> | |
40 | Signed-off-by: Rui Wang <wangr@lemote.com> | |
41 | Cc: John Crispin <john@phrozen.org> | |
42 | Cc: Steven J. Hill <Steven.Hill@imgtec.com> | |
43 | Cc: linux-mips@linux-mips.org | |
44 | Cc: Fuxin Zhang <zhangfx@lemote.com> | |
45 | Cc: Zhangjin Wu <wuzhangjin@gmail.com> | |
46 | Signed-off-by: Ralf Baechle <ralf@linux-mips.org> | |
47 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
48 | ||
49 | --- | |
50 | arch/mips/kernel/unaligned.c | 1 - | |
51 | 1 file changed, 1 deletion(-) | |
52 | ||
53 | --- a/arch/mips/kernel/unaligned.c | |
54 | +++ b/arch/mips/kernel/unaligned.c | |
55 | @@ -690,7 +690,6 @@ static void emulate_load_store_insn(stru | |
56 | case sdc1_op: | |
57 | die_if_kernel("Unaligned FP access in kernel code", regs); | |
58 | BUG_ON(!used_math()); | |
59 | - BUG_ON(!is_fpu_owner()); | |
60 | ||
61 | lose_fpu(1); /* Save FPU state for the emulator. */ | |
62 | res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, |