Skip to content

Commit da3db16

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86: Virtualize FLUSH_L1D and passthrough MSR_IA32_FLUSH_CMD
Virtualize FLUSH_L1D so that the guest can use the performant L1D flush if one of the many mitigations might require a flush in the guest, e.g. Linux provides an option to flush the L1D when switching mms. Passthrough MSR_IA32_FLUSH_CMD for write when it's supported in hardware and exposed to the guest, i.e. always let the guest write it directly if FLUSH_L1D is fully supported. Forward writes to hardware in host context on the off chance that KVM ends up emulating a WRMSR, or in the really unlikely scenario where userspace wants to force a flush. Restrict these forwarded WRMSRs to the known command out of an abundance of caution. Passing through the MSR means the guest can throw any and all values at hardware, but doing so in host context is arguably a bit more dangerous. Link: https://lkml.kernel.org/r/CALMp9eTt3xzAEoQ038bJQ9LN0ZOXrSWsN7xnNUD%2B0SS%3DWwF7Pg%40mail.gmail.com Link: https://lore.kernel.org/all/20230201132905.549148-2-eesposit@redhat.com Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20230322011440.2195485-6-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 903358c commit da3db16

6 files changed

Lines changed: 27 additions & 2 deletions

File tree

arch/x86/kvm/cpuid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ void kvm_set_cpu_caps(void)
653653
F(SPEC_CTRL_SSBD) | F(ARCH_CAPABILITIES) | F(INTEL_STIBP) |
654654
F(MD_CLEAR) | F(AVX512_VP2INTERSECT) | F(FSRM) |
655655
F(SERIALIZE) | F(TSXLDTRK) | F(AVX512_FP16) |
656-
F(AMX_TILE) | F(AMX_INT8) | F(AMX_BF16)
656+
F(AMX_TILE) | F(AMX_INT8) | F(AMX_BF16) | F(FLUSH_L1D)
657657
);
658658

659659
/* TSC_ADJUST and ARCH_CAPABILITIES are emulated in software. */

arch/x86/kvm/svm/svm.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ static const struct svm_direct_access_msrs {
9595
#endif
9696
{ .index = MSR_IA32_SPEC_CTRL, .always = false },
9797
{ .index = MSR_IA32_PRED_CMD, .always = false },
98+
{ .index = MSR_IA32_FLUSH_CMD, .always = false },
9899
{ .index = MSR_IA32_LASTBRANCHFROMIP, .always = false },
99100
{ .index = MSR_IA32_LASTBRANCHTOIP, .always = false },
100101
{ .index = MSR_IA32_LASTINTFROMIP, .always = false },
@@ -4140,6 +4141,10 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
41404141
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_PRED_CMD, 0,
41414142
!!guest_has_pred_cmd_msr(vcpu));
41424143

4144+
if (boot_cpu_has(X86_FEATURE_FLUSH_L1D))
4145+
set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0,
4146+
!!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D));
4147+
41434148
/* For sev guests, the memory encryption bit is not reserved in CR3. */
41444149
if (sev_guest(vcpu->kvm)) {
41454150
best = kvm_find_cpuid_entry(vcpu, 0x8000001F);

arch/x86/kvm/vmx/nested.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,9 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu,
654654
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
655655
MSR_IA32_PRED_CMD, MSR_TYPE_W);
656656

657+
nested_vmx_set_intercept_for_msr(vmx, msr_bitmap_l1, msr_bitmap_l0,
658+
MSR_IA32_FLUSH_CMD, MSR_TYPE_W);
659+
657660
kvm_vcpu_unmap(vcpu, &vmx->nested.msr_bitmap_map, false);
658661

659662
vmx->nested.force_msr_bitmap_recalc = false;

arch/x86/kvm/vmx/vmx.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ module_param(allow_smaller_maxphyaddr, bool, S_IRUGO);
164164
static u32 vmx_possible_passthrough_msrs[MAX_POSSIBLE_PASSTHROUGH_MSRS] = {
165165
MSR_IA32_SPEC_CTRL,
166166
MSR_IA32_PRED_CMD,
167+
MSR_IA32_FLUSH_CMD,
167168
MSR_IA32_TSC,
168169
#ifdef CONFIG_X86_64
169170
MSR_FS_BASE,
@@ -7720,6 +7721,10 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
77207721
vmx_set_intercept_for_msr(vcpu, MSR_IA32_PRED_CMD, MSR_TYPE_W,
77217722
!guest_has_pred_cmd_msr(vcpu));
77227723

7724+
if (boot_cpu_has(X86_FEATURE_FLUSH_L1D))
7725+
vmx_set_intercept_for_msr(vcpu, MSR_IA32_FLUSH_CMD, MSR_TYPE_W,
7726+
!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D));
7727+
77237728
set_cr4_guest_host_mask(vmx);
77247729

77257730
vmx_write_encls_bitmap(vcpu, NULL);

arch/x86/kvm/vmx/vmx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ struct vcpu_vmx {
369369
struct lbr_desc lbr_desc;
370370

371371
/* Save desired MSR intercept (read: pass-through) state */
372-
#define MAX_POSSIBLE_PASSTHROUGH_MSRS 15
372+
#define MAX_POSSIBLE_PASSTHROUGH_MSRS 16
373373
struct {
374374
DECLARE_BITMAP(read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
375375
DECLARE_BITMAP(write, MAX_POSSIBLE_PASSTHROUGH_MSRS);

arch/x86/kvm/x86.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
36283628

36293629
wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
36303630
break;
3631+
case MSR_IA32_FLUSH_CMD:
3632+
if (!msr_info->host_initiated &&
3633+
!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D))
3634+
return 1;
3635+
3636+
if (!boot_cpu_has(X86_FEATURE_FLUSH_L1D) || (data & ~L1D_FLUSH))
3637+
return 1;
3638+
if (!data)
3639+
break;
3640+
3641+
wrmsrl(MSR_IA32_FLUSH_CMD, L1D_FLUSH);
3642+
break;
36313643
case MSR_EFER:
36323644
return set_efer(vcpu, msr_info);
36333645
case MSR_K7_HWCR:

0 commit comments

Comments
 (0)