Patch #3
Subsystems (2)
PATCH 3/6 Patch #3
336996-Speculative-Execution-Side-Channel-Mitigations.pdf defines a new MSR (IA32_FLUSH_CMD aka 0x10B) which has similar semantics to other MSRS defined in the document.
As such we implement a similar way to handle it as commit 1b86883 "x86/bugs: Read SPEC_CTRL MSR during boot and re-use reserved bits"
- that is we read at boottime the FLUSH_CMD MSR and provide an external API to retrieve this value and also to whack the L1 flush.
The semantics of this MSR is to allow "finer granularity invalidation of caching structures than existing mechanisms like WBINVD. It will writeback and invalidate the L1 data cache, including all cachelines brought in by preceding instructions, without invalidating all caches (eg. L2 or LLC). Some processors may also invalidate the first level level instruction cache on a L1D_FLUSH command. The L1 data and instruction caches may be shared across the logical processors of a core."
A copy of this document is available at
https://bugzilla.kernel.org/show_bug.cgi?id=199511
--- arch/x86/include/asm/cpu.h | 4 ++++ arch/x86/include/asm/msr-index.h | 6 ++++++ arch/x86/kernel/cpu/bugs.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+)
arch/x86/include/asm/cpu.h +4 -0
@@ -40,4 +40,8 @@ int mwait_usable(const struct cpuinfo_x86 *);unsigned int x86_family (unsigned int sig);unsigned int x86_model (unsigned int sig);unsigned int x86_stepping (unsigned int sig); + +extern u64 x86_flush_cmd_get (void ); +extern int x86_flush_l1d (void ); +#endif /* _ASM_X86_CPU_H */
arch/x86/include/asm/msr-index.h +6 -0
@@ -76,6 +76,12 @@* control required. */ +#define MSR_IA32_FLUSH_CMD 0x0000010b +#define L1D_FLUSH (1 << 0)/* +* Writeback and invalidate the +* L1 data cache. +*/ +#define MSR_IA32_BBL_CR_CTL 0x00000119#define MSR_IA32_BBL_CR_CTL3 0x0000011e
arch/x86/kernel/cpu/bugs.c +28 -0
@@ -53,6 +53,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;u64 __ro_after_init x86_amd_ls_cfg_base;u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask; +/* +* Our boot-time value of the IA32_FLUSH_CMD MSR. We read it once so that +* any writes to the IA32_FLUSH_CMD contain whatever reserved bits have been +* set. +*/ +static u64 __ro_after_init x86_flush_cmd; +void __init check_bugs (void ) {identify_boot_cpu ();
@@ -85,6 +92,10 @@ void __init check_bugs(void)l1tf_select_mitigation (); +/* Similar to SPEC_CTRL MSR, read it to account for reserved bits. */ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) +rdmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd); +#ifdef CONFIG_X86_32 /* * Check whether we are able to run this kernel safely on SMP.
@@ -682,6 +693,23 @@ static void __init l1tf_select_mitigation(void)setup_force_cpu_cap (X86_FEATURE_L1TF_PTEINV ); } + +u64 x86_flush_cmd_get (void ) +{ +return x86_flush_cmd; +} +EXPORT_SYMBOL_GPL (x86_flush_cmd_get); + +int x86_flush_l1d (void ) +{ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) { +wrmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd |L1D_FLUSH ); +return 0 ; + } +return -ENOTSUPP ; +} +EXPORT_SYMBOL_GPL (x86_flush_l1d); +#undef pr_fmt#ifdef CONFIG_SYSFS
Signature · 1 line
2.14.3
Quoted 19 lines
arch/x86/kernel/cpu/bugs.c +7
-0@@ -53,6 +53,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;u64 __ro_after_init x86_amd_ls_cfg_base;u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask; +/* +* Our boot-time value of the IA32_FLUSH_CMD MSR. We read it once so that +* any writes to the IA32_FLUSH_CMD contain whatever reserved bits have been +* set. +*/ +static u64 __ro_after_init x86_flush_cmd; +void __init check_bugs (void ) {identify_boot_cpu ();
arch/x86/kernel/cpu/bugs.c void __init check_bugs(void) · line 97
Quoted 6 lines
arch/x86/kernel/cpu/bugs.c +3
-0@@ -85,6 +92,10 @@ void __init check_bugs(void)l1tf_select_mitigation (); +/* Similar to SPEC_CTRL MSR, read it to account for reserved bits. */ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) +rdmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd);
The spec didn't mention it but the development microcode I am assuming looks to be a write-only MSR, so I changed this to:
(void)rdmsrl_safe(MSR_IA32_FLUSH_CMD, &x86_flush_cmd);
Quoted 30 lines · speck for Konrad Rzeszutek Wilk
Quoted 19 lines
arch/x86/kernel/cpu/bugs.c +7
-0@@ -53,6 +53,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;u64 __ro_after_init x86_amd_ls_cfg_base;u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask; +/* +* Our boot-time value of the IA32_FLUSH_CMD MSR. We read it once so that +* any writes to the IA32_FLUSH_CMD contain whatever reserved bits have been +* set. +*/ +static u64 __ro_after_init x86_flush_cmd; +void __init check_bugs (void ) {identify_boot_cpu ();arch/x86/kernel/cpu/bugs.c void __init check_bugs(void) · line 97
Quoted 6 lines
arch/x86/kernel/cpu/bugs.c +3
-0@@ -85,6 +92,10 @@ void __init check_bugs(void)l1tf_select_mitigation (); +/* Similar to SPEC_CTRL MSR, read it to account for reserved bits. */ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) +rdmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd);The spec didn't mention it but the development microcode I am assuming looks to be a write-only MSR, so I changed this to:
Quoted 1 line
(void)rdmsrl_safe(MSR_IA32_FLUSH_CMD, &x86_flush_cmd);
Which is pointless as my version of that magic PDF clearly says:
New MSR IA32_FLUSH_CMD (MSR 0x10B, Write-only) bit 0: L1D Flush
Thanks,
tglx
Quoted 31 lines · speck for Thomas Gleixner
Quoted 30 lines · speck for Konrad Rzeszutek Wilk
Quoted 19 lines
arch/x86/kernel/cpu/bugs.c +7
-0@@ -53,6 +53,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;u64 __ro_after_init x86_amd_ls_cfg_base;u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask; +/* +* Our boot-time value of the IA32_FLUSH_CMD MSR. We read it once so that +* any writes to the IA32_FLUSH_CMD contain whatever reserved bits have been +* set. +*/ +static u64 __ro_after_init x86_flush_cmd; +void __init check_bugs (void ) {identify_boot_cpu ();arch/x86/kernel/cpu/bugs.c void __init check_bugs(void) · line 97
Quoted 6 lines
arch/x86/kernel/cpu/bugs.c +3
-0@@ -85,6 +92,10 @@ void __init check_bugs(void)l1tf_select_mitigation (); +/* Similar to SPEC_CTRL MSR, read it to account for reserved bits. */ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) +rdmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd);The spec didn't mention it but the development microcode I am assuming looks to be a write-only MSR, so I changed this to:
Quoted 5 lines
Quoted 1 line
(void)rdmsrl_safe(MSR_IA32_FLUSH_CMD, &x86_flush_cmd);Which is pointless as my version of that magic PDF clearly says:
New MSR
IA32_FLUSH_CMD(MSR0x10B, Write-only) bit 0: L1D Flush
Duh. Indeed. <rips it out>
Quoted 4 lines
Thanks,
tglx
Quoted 14 lines · speck for konrad.wilk_at_oracle.com
arch/x86/kernel/cpu/bugs.c +7
-0+/* Similar to SPEC_CTRL MSR, read it to account for reserved bits. */ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) +rdmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd); +#ifdef CONFIG_X86_32 /* * Check whether we are able to run this kernel safely on SMP. @@ -682,6 +693,23 @@ static void __init l1tf_select_mitigation(void)setup_force_cpu_cap (X86_FEATURE_L1TF_PTEINV ); } + +u64 x86_flush_cmd_get (void ) +{
arch/x86/kernel/cpu/bugs.c static void __init l1tf_select_mitigation(void) · line 708
Quoted 10 lines
arch/x86/kernel/cpu/bugs.c +10
-0+return x86_flush_cmd; +} +EXPORT_SYMBOL_GPL (x86_flush_cmd_get); + +int x86_flush_l1d (void ) +{ +if (boot_cpu_has (X86_FEATURE_FLUSH_L1D )) { +wrmsrl (MSR_IA32_FLUSH_CMD , x86_flush_cmd |L1D_FLUSH ); +return 0 ; + }
We don't do that for PRED_CMD, we shouldn't do that here either. It's an almost guaranteed cache miss.
Paolo