Skip to content

Commit 650ea1f

Browse files
committed
Merge tag 'x86_fpu_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fpu update from Borislav Petkov: - Add machinery to initialize AMX register state in order for AMX-capable CPUs to be able to enter deeper low-power state * tag 'x86_fpu_for_v6.0_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: intel_idle: Add a new flag to initialize the AMX state x86/fpu: Add a helper to prepare AMX state for low-power CPU idle
2 parents 92598ae + 9f01129 commit 650ea1f

4 files changed

Lines changed: 48 additions & 2 deletions

File tree

arch/x86/include/asm/fpu/api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,6 @@ static inline bool fpstate_is_confidential(struct fpu_guest *gfpu)
164164
/* prctl */
165165
extern long fpu_xstate_prctl(int option, unsigned long arg2);
166166

167+
extern void fpu_idle_fpregs(void);
168+
167169
#endif /* _ASM_X86_FPU_API_H */

arch/x86/include/asm/special_insns.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,15 @@ static inline int enqcmds(void __iomem *dst, const void *src)
295295
return 0;
296296
}
297297

298+
static inline void tile_release(void)
299+
{
300+
/*
301+
* Instruction opcode for TILERELEASE; supported in binutils
302+
* version >= 2.36.
303+
*/
304+
asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0");
305+
}
306+
298307
#endif /* __KERNEL__ */
299308

300309
#endif /* _ASM_X86_SPECIAL_INSNS_H */

arch/x86/kernel/fpu/core.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,3 +851,17 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr)
851851
*/
852852
return 0;
853853
}
854+
855+
/*
856+
* Initialize register state that may prevent from entering low-power idle.
857+
* This function will be invoked from the cpuidle driver only when needed.
858+
*/
859+
void fpu_idle_fpregs(void)
860+
{
861+
/* Note: AMX_TILE being enabled implies XGETBV1 support */
862+
if (cpu_feature_enabled(X86_FEATURE_AMX_TILE) &&
863+
(xfeatures_in_use() & XFEATURE_MASK_XTILE)) {
864+
tile_release();
865+
fpregs_deactivate(&current->thread.fpu);
866+
}
867+
}

drivers/idle/intel_idle.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include <asm/nospec-branch.h>
5757
#include <asm/mwait.h>
5858
#include <asm/msr.h>
59+
#include <asm/fpu/api.h>
5960

6061
#define INTEL_IDLE_VERSION "0.5.1"
6162

@@ -113,6 +114,11 @@ static unsigned int mwait_substates __initdata;
113114
*/
114115
#define CPUIDLE_FLAG_IBRS BIT(16)
115116

117+
/*
118+
* Initialize large xstate for the C6-state entrance.
119+
*/
120+
#define CPUIDLE_FLAG_INIT_XSTATE BIT(17)
121+
116122
/*
117123
* MWAIT takes an 8-bit "hint" in EAX "suggesting"
118124
* the C-state (top nibble) and sub-state (bottom nibble)
@@ -191,6 +197,13 @@ static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
191197
return ret;
192198
}
193199

200+
static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
201+
struct cpuidle_driver *drv, int index)
202+
{
203+
fpu_idle_fpregs();
204+
return __intel_idle(dev, drv, index);
205+
}
206+
194207
/**
195208
* intel_idle_s2idle - Ask the processor to enter the given idle state.
196209
* @dev: cpuidle device of the target CPU.
@@ -206,8 +219,12 @@ static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
206219
static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
207220
struct cpuidle_driver *drv, int index)
208221
{
209-
unsigned long eax = flg2MWAIT(drv->states[index].flags);
210222
unsigned long ecx = 1; /* break on interrupt flag */
223+
struct cpuidle_state *state = &drv->states[index];
224+
unsigned long eax = flg2MWAIT(state->flags);
225+
226+
if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
227+
fpu_idle_fpregs();
211228

212229
mwait_idle_with_hints(eax, ecx);
213230

@@ -942,7 +959,8 @@ static struct cpuidle_state spr_cstates[] __initdata = {
942959
{
943960
.name = "C6",
944961
.desc = "MWAIT 0x20",
945-
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
962+
.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
963+
CPUIDLE_FLAG_INIT_XSTATE,
946964
.exit_latency = 290,
947965
.target_residency = 800,
948966
.enter = &intel_idle,
@@ -1857,6 +1875,9 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
18571875
drv->states[drv->state_count].enter = intel_idle_ibrs;
18581876
}
18591877

1878+
if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_INIT_XSTATE)
1879+
drv->states[drv->state_count].enter = intel_idle_xstate;
1880+
18601881
if ((disabled_states_mask & BIT(drv->state_count)) ||
18611882
((icpu->use_acpi || force_use_acpi) &&
18621883
intel_idle_off_by_default(mwait_hint) &&

0 commit comments

Comments
 (0)