Skip to content

Commit f0dccc9

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
x86/fpu/xstate: Support dynamic supervisor feature for LBR
Last Branch Records (LBR) registers are used to log taken branches and other control flows. In perf with call stack mode, LBR information is used to reconstruct a call stack. To get the complete call stack, perf has to save/restore all LBR registers during a context switch. Due to the large number of the LBR registers, e.g., the current platform has 96 LBR registers, this process causes a high CPU overhead. To reduce the CPU overhead during a context switch, an LBR state component that contains all the LBR related registers is introduced in hardware. All LBR registers can be saved/restored together using one XSAVES/XRSTORS instruction. However, the kernel should not save/restore the LBR state component at each context switch, like other state components, because of the following unique features of LBR: - The LBR state component only contains valuable information when LBR is enabled in the perf subsystem, but for most of the time, LBR is disabled. - The size of the LBR state component is huge. For the current platform, it's 808 bytes. If the kernel saves/restores the LBR state at each context switch, for most of the time, it is just a waste of space and cycles. To efficiently support the LBR state component, it is desired to have: - only context-switch the LBR when the LBR feature is enabled in perf. - only allocate an LBR-specific XSAVE buffer on demand. (Besides the LBR state, a legacy region and an XSAVE header have to be included in the buffer as well. There is a total of (808+576) byte overhead for the LBR-specific XSAVE buffer. The overhead only happens when the perf is actively using LBRs. There is still a space-saving, on average, when it replaces the constant 808 bytes of overhead for every task, all the time on the systems that support architectural LBR.) - be able to use XSAVES/XRSTORS for accessing LBR at run time. However, the IA32_XSS should not be adjusted at run time. (The XCR0 | IA32_XSS are used to determine the requested-feature bitmap (RFBM) of XSAVES.) A solution, called dynamic supervisor feature, is introduced to address this issue, which - does not allocate a buffer in each task->fpu; - does not save/restore a state component at each context switch; - sets the bit corresponding to the dynamic supervisor feature in IA32_XSS at boot time, and avoids setting it at run time. - dynamically allocates a specific buffer for a state component on demand, e.g. only allocates LBR-specific XSAVE buffer when LBR is enabled in perf. (Note: The buffer has to include the LBR state component, a legacy region and a XSAVE header space.) (Implemented in a later patch) - saves/restores a state component on demand, e.g. manually invokes the XSAVES/XRSTORS instruction to save/restore the LBR state to/from the buffer when perf is active and a call stack is required. (Implemented in a later patch) A new mask XFEATURE_MASK_DYNAMIC and a helper xfeatures_mask_dynamic() are introduced to indicate the dynamic supervisor feature. For the systems which support the Architecture LBR, LBR is the only dynamic supervisor feature for now. For the previous systems, there is no dynamic supervisor feature available. Signed-off-by: Kan Liang <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Dave Hansen <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent a063bf2 commit f0dccc9

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ enum xfeature {
114114
XFEATURE_Hi16_ZMM,
115115
XFEATURE_PT_UNIMPLEMENTED_SO_FAR,
116116
XFEATURE_PKRU,
117+
XFEATURE_RSRVD_COMP_10,
118+
XFEATURE_RSRVD_COMP_11,
119+
XFEATURE_RSRVD_COMP_12,
120+
XFEATURE_RSRVD_COMP_13,
121+
XFEATURE_RSRVD_COMP_14,
122+
XFEATURE_LBR,
117123

118124
XFEATURE_MAX,
119125
};
@@ -128,6 +134,7 @@ enum xfeature {
128134
#define XFEATURE_MASK_Hi16_ZMM (1 << XFEATURE_Hi16_ZMM)
129135
#define XFEATURE_MASK_PT (1 << XFEATURE_PT_UNIMPLEMENTED_SO_FAR)
130136
#define XFEATURE_MASK_PKRU (1 << XFEATURE_PKRU)
137+
#define XFEATURE_MASK_LBR (1 << XFEATURE_LBR)
131138

132139
#define XFEATURE_MASK_FPSSE (XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
133140
#define XFEATURE_MASK_AVX512 (XFEATURE_MASK_OPMASK \

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@
3535
/* All currently supported supervisor features */
3636
#define XFEATURE_MASK_SUPERVISOR_SUPPORTED (0)
3737

38+
/*
39+
* A supervisor state component may not always contain valuable information,
40+
* and its size may be huge. Saving/restoring such supervisor state components
41+
* at each context switch can cause high CPU and space overhead, which should
42+
* be avoided. Such supervisor state components should only be saved/restored
43+
* on demand. The on-demand dynamic supervisor features are set in this mask.
44+
*
45+
* Unlike the existing supported supervisor features, a dynamic supervisor
46+
* feature does not allocate a buffer in task->fpu, and the corresponding
47+
* supervisor state component cannot be saved/restored at each context switch.
48+
*
49+
* To support a dynamic supervisor feature, a developer should follow the
50+
* dos and don'ts as below:
51+
* - Do dynamically allocate a buffer for the supervisor state component.
52+
* - Do manually invoke the XSAVES/XRSTORS instruction to save/restore the
53+
* state component to/from the buffer.
54+
* - Don't set the bit corresponding to the dynamic supervisor feature in
55+
* IA32_XSS at run time, since it has been set at boot time.
56+
*/
57+
#define XFEATURE_MASK_DYNAMIC (XFEATURE_MASK_LBR)
58+
3859
/*
3960
* Unsupported supervisor features. When a supervisor feature in this mask is
4061
* supported in the future, move it to the supported supervisor feature mask.
@@ -43,6 +64,7 @@
4364

4465
/* All supervisor states including supported and unsupported states. */
4566
#define XFEATURE_MASK_SUPERVISOR_ALL (XFEATURE_MASK_SUPERVISOR_SUPPORTED | \
67+
XFEATURE_MASK_DYNAMIC | \
4668
XFEATURE_MASK_SUPERVISOR_UNSUPPORTED)
4769

4870
#ifdef CONFIG_X86_64
@@ -63,6 +85,14 @@ static inline u64 xfeatures_mask_user(void)
6385
return xfeatures_mask_all & XFEATURE_MASK_USER_SUPPORTED;
6486
}
6587

88+
static inline u64 xfeatures_mask_dynamic(void)
89+
{
90+
if (!boot_cpu_has(X86_FEATURE_ARCH_LBR))
91+
return XFEATURE_MASK_DYNAMIC & ~XFEATURE_MASK_LBR;
92+
93+
return XFEATURE_MASK_DYNAMIC;
94+
}
95+
6696
extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
6797

6898
extern void __init update_regset_xstate_info(unsigned int size,

arch/x86/kernel/fpu/xstate.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,10 @@ void fpu__init_cpu_xstate(void)
233233
/*
234234
* MSR_IA32_XSS sets supervisor states managed by XSAVES.
235235
*/
236-
if (boot_cpu_has(X86_FEATURE_XSAVES))
237-
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
236+
if (boot_cpu_has(X86_FEATURE_XSAVES)) {
237+
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() |
238+
xfeatures_mask_dynamic());
239+
}
238240
}
239241

240242
static bool xfeature_enabled(enum xfeature xfeature)
@@ -598,7 +600,8 @@ static void check_xstate_against_struct(int nr)
598600
*/
599601
if ((nr < XFEATURE_YMM) ||
600602
(nr >= XFEATURE_MAX) ||
601-
(nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR)) {
603+
(nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR) ||
604+
((nr >= XFEATURE_RSRVD_COMP_10) && (nr <= XFEATURE_LBR))) {
602605
WARN_ONCE(1, "no structure for xstate: %d\n", nr);
603606
XSTATE_WARN_ON(1);
604607
}
@@ -847,8 +850,10 @@ void fpu__resume_cpu(void)
847850
* Restore IA32_XSS. The same CPUID bit enumerates support
848851
* of XSAVES and MSR_IA32_XSS.
849852
*/
850-
if (boot_cpu_has(X86_FEATURE_XSAVES))
851-
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor());
853+
if (boot_cpu_has(X86_FEATURE_XSAVES)) {
854+
wrmsrl(MSR_IA32_XSS, xfeatures_mask_supervisor() |
855+
xfeatures_mask_dynamic());
856+
}
852857
}
853858

854859
/*

0 commit comments

Comments
 (0)