hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/arch/x86/kernel/fpu/core.c
....@@ -25,17 +25,7 @@
2525 */
2626 union fpregs_state init_fpstate __read_mostly;
2727
28
-/*
29
- * Track whether the kernel is using the FPU state
30
- * currently.
31
- *
32
- * This flag is used:
33
- *
34
- * - by IRQ context code to potentially use the FPU
35
- * if it's unused.
36
- *
37
- * - to debug kernel_fpu_begin()/end() correctness
38
- */
28
+/* Track in-kernel FPU usage */
3929 static DEFINE_PER_CPU(bool, in_kernel_fpu);
4030
4131 /*
....@@ -43,42 +33,37 @@
4333 */
4434 DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
4535
46
-static bool kernel_fpu_disabled(void)
47
-{
48
- return this_cpu_read(in_kernel_fpu);
49
-}
50
-
51
-static bool interrupted_kernel_fpu_idle(void)
52
-{
53
- return !kernel_fpu_disabled();
54
-}
55
-
56
-/*
57
- * Were we in user mode (or vm86 mode) when we were
58
- * interrupted?
59
- *
60
- * Doing kernel_fpu_begin/end() is ok if we are running
61
- * in an interrupt context from user mode - we'll just
62
- * save the FPU state as required.
63
- */
64
-static bool interrupted_user_mode(void)
65
-{
66
- struct pt_regs *regs = get_irq_regs();
67
- return regs && user_mode(regs);
68
-}
69
-
7036 /*
7137 * Can we use the FPU in kernel mode with the
7238 * whole "kernel_fpu_begin/end()" sequence?
73
- *
74
- * It's always ok in process context (ie "not interrupt")
75
- * but it is sometimes ok even from an irq.
7639 */
7740 bool irq_fpu_usable(void)
7841 {
79
- return !in_interrupt() ||
80
- interrupted_user_mode() ||
81
- interrupted_kernel_fpu_idle();
42
+ if (WARN_ON_ONCE(in_nmi()))
43
+ return false;
44
+
45
+ /* In kernel FPU usage already active? */
46
+ if (this_cpu_read(in_kernel_fpu))
47
+ return false;
48
+
49
+ /*
50
+ * When not in NMI or hard interrupt context, FPU can be used in:
51
+ *
52
+ * - Task context except from within fpregs_lock()'ed critical
53
+ * regions.
54
+ *
55
+ * - Soft interrupt processing context which cannot happen
56
+ * while in a fpregs_lock()'ed critical region.
57
+ */
58
+ if (!in_irq())
59
+ return true;
60
+
61
+ /*
62
+ * In hard interrupt context it's safe when soft interrupts
63
+ * are enabled, which means the interrupt did not hit in
64
+ * a fpregs_lock()'ed critical region.
65
+ */
66
+ return !softirq_count();
8267 }
8368 EXPORT_SYMBOL(irq_fpu_usable);
8469