x86/fpu: Add a helper to prepare AMX state for low-power CPU idle
authorChang S. Bae <chang.seok.bae@intel.com>
Wed, 8 Jun 2022 16:47:47 +0000 (09:47 -0700)
committerBorislav Petkov <bp@suse.de>
Tue, 19 Jul 2022 16:46:15 +0000 (18:46 +0200)
When a CPU enters an idle state, a non-initialized AMX register state may
be the cause of preventing a deeper low-power state. Other extended
register states whether initialized or not do not impact the CPU idle
state.

The new helper can ensure the AMX state is initialized before the CPU is
idle, and it will be used by the intel idle driver.

Check the AMX_TILE feature bit before using XGETBV1 as a chain of
dependencies was established via cpuid_deps[]: AMX->XFD->XGETBV1.

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20220608164748.11864-2-chang.seok.bae@intel.com
arch/x86/include/asm/fpu/api.h
arch/x86/include/asm/special_insns.h
arch/x86/kernel/fpu/core.c

index 6b0f31fb53f7e27e6d21a2076914a808b24c0685..503a577814b2e5a7b47c1f5069a76c3e568ff6b7 100644 (file)
@@ -164,4 +164,6 @@ static inline bool fpstate_is_confidential(struct fpu_guest *gfpu)
 /* prctl */
 extern long fpu_xstate_prctl(int option, unsigned long arg2);
 
+extern void fpu_idle_fpregs(void);
+
 #endif /* _ASM_X86_FPU_API_H */
index 45b18eb94fa1a854933f78ed6df4371d4855bb4d..35f709f619fb4fc2278ddbe09c3ef72f20e1cfcb 100644 (file)
@@ -295,6 +295,15 @@ static inline int enqcmds(void __iomem *dst, const void *src)
        return 0;
 }
 
+static inline void tile_release(void)
+{
+       /*
+        * Instruction opcode for TILERELEASE; supported in binutils
+        * version >= 2.36.
+        */
+       asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0");
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_SPECIAL_INSNS_H */
index 0531d6a06df5fc57bd96ddcaf27d9371fed996fb..3b28c5b25e12ce754d899cbfb90eb93aa8a42a9e 100644 (file)
@@ -851,3 +851,17 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr)
         */
        return 0;
 }
+
+/*
+ * Initialize register state that may prevent from entering low-power idle.
+ * This function will be invoked from the cpuidle driver only when needed.
+ */
+void fpu_idle_fpregs(void)
+{
+       /* Note: AMX_TILE being enabled implies XGETBV1 support */
+       if (cpu_feature_enabled(X86_FEATURE_AMX_TILE) &&
+           (xfeatures_in_use() & XFEATURE_MASK_XTILE)) {
+               tile_release();
+               fpregs_deactivate(&current->thread.fpu);
+       }
+}