Skip to content

Commit c829ccd

Browse files
committed
KVM: x86: Reject disabling of MWAIT/HLT interception when not allowed
Reject KVM_CAP_X86_DISABLE_EXITS if userspace attempts to disable MWAIT or HLT exits and KVM previously reported (via KVM_CHECK_EXTENSION) that disabling the exit(s) is not allowed. E.g. because MWAIT isn't supported or the CPU doesn't have an always-running APIC timer, or because KVM is configured to mitigate cross-thread vulnerabilities. Cc: Kechen Lu <kechenl@nvidia.com> Fixes: 4d5422c ("KVM: X86: Provide a capability to disable MWAIT intercepts") Fixes: 6f0f2d5 ("KVM: x86: Mitigate the cross-thread return address predictions bug") Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Link: https://lore.kernel.org/r/20241128013424.4096668-15-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 04cd8f8 commit c829ccd

File tree

1 file changed

+28
-26
lines changed

1 file changed

+28
-26
lines changed

arch/x86/kvm/x86.c

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4531,6 +4531,20 @@ static inline bool kvm_can_mwait_in_guest(void)
45314531
boot_cpu_has(X86_FEATURE_ARAT);
45324532
}
45334533

4534+
static u64 kvm_get_allowed_disable_exits(void)
4535+
{
4536+
u64 r = KVM_X86_DISABLE_EXITS_PAUSE;
4537+
4538+
if (!mitigate_smt_rsb) {
4539+
r |= KVM_X86_DISABLE_EXITS_HLT |
4540+
KVM_X86_DISABLE_EXITS_CSTATE;
4541+
4542+
if (kvm_can_mwait_in_guest())
4543+
r |= KVM_X86_DISABLE_EXITS_MWAIT;
4544+
}
4545+
return r;
4546+
}
4547+
45344548
#ifdef CONFIG_KVM_HYPERV
45354549
static int kvm_ioctl_get_supported_hv_cpuid(struct kvm_vcpu *vcpu,
45364550
struct kvm_cpuid2 __user *cpuid_arg)
@@ -4673,15 +4687,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
46734687
r = KVM_CLOCK_VALID_FLAGS;
46744688
break;
46754689
case KVM_CAP_X86_DISABLE_EXITS:
4676-
r = KVM_X86_DISABLE_EXITS_PAUSE;
4677-
4678-
if (!mitigate_smt_rsb) {
4679-
r |= KVM_X86_DISABLE_EXITS_HLT |
4680-
KVM_X86_DISABLE_EXITS_CSTATE;
4681-
4682-
if (kvm_can_mwait_in_guest())
4683-
r |= KVM_X86_DISABLE_EXITS_MWAIT;
4684-
}
4690+
r = kvm_get_allowed_disable_exits();
46854691
break;
46864692
case KVM_CAP_X86_SMM:
46874693
if (!IS_ENABLED(CONFIG_KVM_SMM))
@@ -6528,33 +6534,29 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
65286534
break;
65296535
case KVM_CAP_X86_DISABLE_EXITS:
65306536
r = -EINVAL;
6531-
if (cap->args[0] & ~KVM_X86_DISABLE_VALID_EXITS)
6537+
if (cap->args[0] & ~kvm_get_allowed_disable_exits())
65326538
break;
65336539

65346540
mutex_lock(&kvm->lock);
65356541
if (kvm->created_vcpus)
65366542
goto disable_exits_unlock;
65376543

6538-
if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
6539-
kvm->arch.pause_in_guest = true;
6540-
65416544
#define SMT_RSB_MSG "This processor is affected by the Cross-Thread Return Predictions vulnerability. " \
65426545
"KVM_CAP_X86_DISABLE_EXITS should only be used with SMT disabled or trusted guests."
65436546

6544-
if (!mitigate_smt_rsb) {
6545-
if (boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible() &&
6546-
(cap->args[0] & ~KVM_X86_DISABLE_EXITS_PAUSE))
6547-
pr_warn_once(SMT_RSB_MSG);
6548-
6549-
if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
6550-
kvm_can_mwait_in_guest())
6551-
kvm->arch.mwait_in_guest = true;
6552-
if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
6553-
kvm->arch.hlt_in_guest = true;
6554-
if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
6555-
kvm->arch.cstate_in_guest = true;
6556-
}
6547+
if (!mitigate_smt_rsb && boot_cpu_has_bug(X86_BUG_SMT_RSB) &&
6548+
cpu_smt_possible() &&
6549+
(cap->args[0] & ~KVM_X86_DISABLE_EXITS_PAUSE))
6550+
pr_warn_once(SMT_RSB_MSG);
65576551

6552+
if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
6553+
kvm->arch.pause_in_guest = true;
6554+
if (cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT)
6555+
kvm->arch.mwait_in_guest = true;
6556+
if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
6557+
kvm->arch.hlt_in_guest = true;
6558+
if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
6559+
kvm->arch.cstate_in_guest = true;
65586560
r = 0;
65596561
disable_exits_unlock:
65606562
mutex_unlock(&kvm->lock);

0 commit comments

Comments
 (0)