From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 537EB17BA6 for ; Fri, 28 Nov 2025 11:32:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764329530; cv=none; b=OFPvAmuRznIsQMiXtFFi90dq2EfhCLlVekv2c2B09kHomLTd0m7kLMm8L0gXjTwvjtFcz77qesRJpSQ2xDu9GOajOk3QDFas/EGDRdWQplHAEUi/2e2NPBsY3F+EngTvT0I157oChQDPD578ybV4l02YVfQpUGfO03diRT1sIH8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764329530; c=relaxed/simple; bh=PH9qCvIxP5Gd7Wg9ykwfGd0sVXYgzsKz06bqLv2zGpo=; h=Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=h/bL+lkjAQIvjH3YpKafFNsyKK8vdDqqhib6kQ8Qtd4I2qx+pk4nTaW/e2cN82N/XQrs/it5AFnbx3zJiNFrCKLRKlGDtkm2GNruIrwTQ+v0kXd5islvoptG6wNsybpM5R8klJ6wG38clf5EKymjinGzEaS8I/kb+aKtKzC875k= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=C57wGFre; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=a4cxZ640; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="C57wGFre"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="a4cxZ640" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1764329527; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1Vcj5UK3urZHkUpSELefbaUtytPM/ccTzW6aPhYWxGI=; b=C57wGFreXxR4J+1WLD9cA19QPkheq5nBtsyoQZjmCLjv5quY/VKLHumGBn73PxvmJg9uYw CSYd90ZZOg74hDFK/bpshmYb3pA3Tniwlg35CiwMCKyTdQ3akRIETHmjjsvcOpmTiR+44S 5sfON6IpJr3SD8sZ8mgudzJ3+LOKr7M= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-371-j0fCDKlZOaatDGgJP4w1yQ-1; Fri, 28 Nov 2025 06:32:05 -0500 X-MC-Unique: j0fCDKlZOaatDGgJP4w1yQ-1 X-Mimecast-MFC-AGG-ID: j0fCDKlZOaatDGgJP4w1yQ_1764329524 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-477cf25ceccso15377605e9.0 for ; Fri, 28 Nov 2025 03:32:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1764329524; x=1764934324; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:subject:cc:to:from:date:from:to:cc:subject:date :message-id:reply-to; bh=1Vcj5UK3urZHkUpSELefbaUtytPM/ccTzW6aPhYWxGI=; b=a4cxZ640qcbTkjNrWRwIAOmoousMgdTxKyMfppOdYm/K3Kb2N8wy4iT+gMMF/cNMRW qEpaxith++gW4YEOWuF4JT0aBW8nquW2sz3A/eG85jWBo6kCNWFV+2cPZvVSIH3pg3Vw 1vOcOBy4b4LtFRq3qKuvtJ8NU68iTkIYAE+N87S4i2EO54zSUXeqDi3k9yQcOCqZgpOB MueSpJQYcIRkpuKN71luX0yXe9GAw3S1iTuw3scptuWdFrUv0aClRmmM6jfhI35nF6eP E1MrrZ0+sa0l+aYSeLTdJWhCc7y3oYUNYi5UkJy19uWT7UFM20t0oAE8oQgN/J/yj/H8 wSdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764329524; x=1764934324; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=1Vcj5UK3urZHkUpSELefbaUtytPM/ccTzW6aPhYWxGI=; b=NVWyjaNnAW+v7G8lqzZqLNNg0tovmMVYmKA+kvkL8U/lo2K8SxZHetRkeo9HgFyMMZ P4p5feCu42KgIHzXKw1ZPF4nO5t6m7qIy8gbd82UbOwOaVDXLFoFFQmslN5lZoLE1Ybz eHLY8S2l9UM73M0MVmO6czOhlmbSjIozDdJKUT7wsNSjI88+FNrkDUnIIm2SAhQengOq mISv+2dEWBaWhC1PTbVikV+qY8pyOMSSCqKIeYUl1ORXkmE84mXC0SWznr3IFLlK48g0 YHvW+moPJHC3696FrGpRpCjTzOnzckubooz9i9jPhpUwqzXMLQyrL6q9/4uBZkO22dOq AWSA== X-Forwarded-Encrypted: i=1; AJvYcCWdOVUZI7+H/Xom9hkFoXBkU3rjCsY/UGJJgX/WabVAe0k6ATFhRpL7AQs5EhSJ+meF+nNHw/HewZRQv8A=@vger.kernel.org X-Gm-Message-State: AOJu0Yy/ZAzm8zxgRTEFQyWYiJzzXUvcbvFKB5Sb7e5Fc0evYPUEcuUg lH6M/RvPGvezPV+amUwoT+Hkrp2nmFmnV26woza9rSZiCn/Gben4uEw2HLy9soK1ZJ8EoZs320M lfki9ZEg9Ms7ovXW6aQXXxj7wWTOne3a4os3hTF4oIbdeuOvXmD85pG1fUoFbg1rJHA== X-Gm-Gg: ASbGncvEGXIriBCM39ZeDP3Ezce6qRgS7E9Dn6qXwQoWvGdRDDWT4xLSX8e40TONCTK KTjDGTx5ZYBw9/Dvm/efGO8eVRoT4Q/bh1pookJIHjuz9dB2zSNFrV32yI9YcdhpUi2Nj5w3uxG 2MxOVfvo0KEkX1ANxzUbzfNP9tMI5F9LUGV/m3/C5QlnbHspfoEWc7tofnVwJNUn2GSZ0p5S7OP jk4Hou8QuA3MsDaVOlXIgGH4zcjRAdcRqzvWIqH4xaNDfpraENfyNYi1WuhzQtV1ff3Bg5vULFy r/UBsPS9lVULZq4aNi8/Sv8jbn8KRJpkQtVtU+p0hBlBNxzIC8noIdUqwEXXOy9S5rTwQg== X-Received: by 2002:a05:600c:354e:b0:477:fcb:2256 with SMTP id 5b1f17b1804b1-47904b12eb0mr153976305e9.17.1764329524079; Fri, 28 Nov 2025 03:32:04 -0800 (PST) X-Google-Smtp-Source: AGHT+IEWkc4kOG4p3NtsM6z+yEwf0TGATNAUUXhu/bxP0XKAceBdDB2zOizod+FJpyGIilCUno76XA== X-Received: by 2002:a05:600c:354e:b0:477:fcb:2256 with SMTP id 5b1f17b1804b1-47904b12eb0mr153975875e9.17.1764329523559; Fri, 28 Nov 2025 03:32:03 -0800 (PST) Received: from imammedo ([213.175.46.86]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4791163e36csm77779385e9.9.2025.11.28.03.32.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Nov 2025 03:32:03 -0800 (PST) Date: Fri, 28 Nov 2025 12:32:02 +0100 From: Igor Mammedov To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Jim Mattson , mlevitsk@redhat.com Subject: Re: [PATCH 5/5] KVM: x86: Defer runtime updates of dynamic CPUID bits until CPUID emulation Message-ID: <20251128123202.68424a95@imammedo> In-Reply-To: <20241211013302.1347853-6-seanjc@google.com> References: <20241211013302.1347853-1-seanjc@google.com> <20241211013302.1347853-6-seanjc@google.com> X-Mailer: Claws Mail 4.3.1 (GTK 3.24.51; x86_64-redhat-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Tue, 10 Dec 2024 17:33:02 -0800 Sean Christopherson wrote: Sean, this patch broke vCPU hotplug (still broken with current master), after repeated plug/unplug of the same vCPU in a loop, QEMU exits due to error in vcpu initialization: r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); if (r) { goto fail; } Reproducer (host in question is Haswell but it's been seen on other hosts as well): for it to trigger the issue it must be Q35 machine with UEFI firmware (the rest doesn't seem to matter) === #!/bin/sh /tmp/qemu_build/qemu-system-x86_64 -M q35,pflash0=drive_ovmf_code,pflash1=drive_ovmf_vars \ -m 16G -cpu host -smp 1,maxcpus=2 -enable-kvm \ -blockdev node-name=file_ovmf_code,driver=file,filename=edk2-x86_64-secure-code.fd,auto-read-only=on,discard=unmap \ -blockdev node-name=drive_ovmf_code,driver=raw,read-only=on,file=file_ovmf_code \ -blockdev node-name=file_ovmf_vars,driver=file,filename=myOVMF_VARS.fd,auto-read-only=on,discard=unmap \ -blockdev node-name=drive_ovmf_vars,driver=raw,read-only=off,file=file_ovmf_vars \ -monitor unix:/tmp/monitor2,server,nowait -snapshot \ ./rhel10-efi.qcow2 & sleep 120 i=0 while [ $i -lt 3 ] do echo "====== The $(($i+1)) iterations ======" echo "info cpus" | nc -U /tmp/monitor2 sleep 2 echo "device_add host-x86_64-cpu,core-id=1,thread-id=0,socket-id=0,id=core1" | nc -U /tmp/monitor2 sleep 6 echo "info cpus" | nc -U /tmp/monitor2 sleep 2 echo "device_del core1" | nc -U /tmp/monitor2 sleep 6 echo "info cpus" | nc -U /tmp/monitor2 sleep 2 ((i++)) done === > Defer runtime CPUID updates until the next non-faulting CPUID emulation > or KVM_GET_CPUID2, which are the only paths in KVM that consume the > dynamic entries. Deferring the updates is especially beneficial to > nested VM-Enter/VM-Exit, as KVM will almost always detect multiple state > changes, not to mention the updates don't need to be realized while L2 is > active, as CPUID is a mandatory intercept on both Intel and AMD. > > Deferring CPUID updates shaves several hundred cycles from nested VMX > roundtrips, as measured from L2 executing CPUID in a tight loop: > > SKX 6850 => 6450 > ICX 9000 => 8800 > EMR 7900 => 7700 > > Alternatively, KVM could update only the CPUID leaves that are affected > by the state change, e.g. update XSAVE info only if XCR0 or XSS changes, > but that adds non-trivial complexity and doesn't solve the underlying > problem of nested transitions potentially changing both XCR0 and XSS, on > both nested VM-Enter and VM-Exit. > > KVM could also skip updates entirely while L2 is active, because again > CPUID is a mandatory intercept. However, simply skipping updates if L2 > is active is *very* subtly dangerous and complex. Most KVM updates are > triggered by changes to the current vCPU state, which may be L2 state > whereas performing updates only for L1 would requiring detecting changes > to L1 state. KVM would need to either track relevant L1 state, or defer > runtime CPUID updates until the next nested VM-Exit. The former is ugly > and complex, while the latter comes with similar dangers to deferring all > CPUID updates, and would only address the nested VM-Enter path. > > To guard against using stale data, disallow querying dynamic CPUID feature > bits, i.e. features that KVM updates at runtime, via a compile-time > assertion in guest_cpu_cap_has(). Exempt MWAIT from the rule, as the > MISC_ENABLE_NO_MWAIT means that MWAIT is _conditionally_ a dynamic CPUID > feature. > > Note, the rule could be enforced for MWAIT as well, e.g. by querying guest > CPUID in kvm_emulate_monitor_mwait, but there's no obvious advtantage to > doing so, and allowing MWAIT for guest_cpuid_has() opens up a different can > of worms. MONITOR/MWAIT can't be virtualized (for a reasonable definition), > and the nature of the MWAIT_NEVER_UD_FAULTS and MISC_ENABLE_NO_MWAIT quirks > means checking X86_FEATURE_MWAIT outside of kvm_emulate_monitor_mwait() is > wrong for other reasons. > > Beyond the aforementioned feature bits, the only other dynamic CPUID > (sub)leaves are the XSAVE sizes, and similar to MWAIT, consuming those > CPUID entries in KVM is all but guaranteed to be a bug. The layout for an > actual XSAVE buffer depends on the format (compacted or not) and > potentially the features that are actually enabled. E.g. see the logic in > fpstate_clear_xstate_component() needed to poke into the guest's effective > XSAVE state to clear MPX state on INIT. KVM does consume > CPUID.0xD.0.{EAX,EDX} in kvm_check_cpuid() and cpuid_get_supported_xcr0(), > but not EBX, which is the only dynamic output register in the leaf. > > Signed-off-by: Sean Christopherson > --- > arch/x86/include/asm/kvm_host.h | 1 + > arch/x86/kvm/cpuid.c | 12 ++++++++++-- > arch/x86/kvm/cpuid.h | 9 ++++++++- > arch/x86/kvm/lapic.c | 2 +- > arch/x86/kvm/smm.c | 2 +- > arch/x86/kvm/svm/sev.c | 2 +- > arch/x86/kvm/svm/svm.c | 2 +- > arch/x86/kvm/vmx/vmx.c | 2 +- > arch/x86/kvm/x86.c | 6 +++--- > 9 files changed, 27 insertions(+), 11 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 81ce8cd5814a..23cc5c10060e 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -871,6 +871,7 @@ struct kvm_vcpu_arch { > > int cpuid_nent; > struct kvm_cpuid_entry2 *cpuid_entries; > + bool cpuid_dynamic_bits_dirty; > bool is_amd_compatible; > > /* > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c > index 7f5fa6665969..54ba1a75b779 100644 > --- a/arch/x86/kvm/cpuid.c > +++ b/arch/x86/kvm/cpuid.c > @@ -195,6 +195,7 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu) > } > > static u32 kvm_apply_cpuid_pv_features_quirk(struct kvm_vcpu *vcpu); > +static void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu); > > /* Check whether the supplied CPUID data is equal to what is already set for the vCPU. */ > static int kvm_cpuid_check_equal(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2, > @@ -299,10 +300,12 @@ static __always_inline void kvm_update_feature_runtime(struct kvm_vcpu *vcpu, > guest_cpu_cap_change(vcpu, x86_feature, has_feature); > } > > -void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) > +static void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) > { > struct kvm_cpuid_entry2 *best; > > + vcpu->arch.cpuid_dynamic_bits_dirty = false; > + > best = kvm_find_cpuid_entry(vcpu, 1); > if (best) { > kvm_update_feature_runtime(vcpu, best, X86_FEATURE_OSXSAVE, > @@ -332,7 +335,6 @@ void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) > cpuid_entry_has(best, X86_FEATURE_XSAVEC))) > best->ebx = xstate_required_size(vcpu->arch.xcr0, true); > } > -EXPORT_SYMBOL_GPL(kvm_update_cpuid_runtime); > > static bool kvm_cpuid_has_hyperv(struct kvm_vcpu *vcpu) > { > @@ -645,6 +647,9 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu, > if (cpuid->nent < vcpu->arch.cpuid_nent) > return -E2BIG; > > + if (vcpu->arch.cpuid_dynamic_bits_dirty) > + kvm_update_cpuid_runtime(vcpu); > + > if (copy_to_user(entries, vcpu->arch.cpuid_entries, > vcpu->arch.cpuid_nent * sizeof(struct kvm_cpuid_entry2))) > return -EFAULT; > @@ -1983,6 +1988,9 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, > struct kvm_cpuid_entry2 *entry; > bool exact, used_max_basic = false; > > + if (vcpu->arch.cpuid_dynamic_bits_dirty) > + kvm_update_cpuid_runtime(vcpu); > + > entry = kvm_find_cpuid_entry_index(vcpu, function, index); > exact = !!entry; > > diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h > index 67d80aa72d50..d2884162a46a 100644 > --- a/arch/x86/kvm/cpuid.h > +++ b/arch/x86/kvm/cpuid.h > @@ -11,7 +11,6 @@ extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly; > void kvm_set_cpu_caps(void); > > void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu); > -void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu); > struct kvm_cpuid_entry2 *kvm_find_cpuid_entry_index(struct kvm_vcpu *vcpu, > u32 function, u32 index); > struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, > @@ -232,6 +231,14 @@ static __always_inline bool guest_cpu_cap_has(struct kvm_vcpu *vcpu, > { > unsigned int x86_leaf = __feature_leaf(x86_feature); > > + /* > + * Except for MWAIT, querying dynamic feature bits is disallowed, so > + * that KVM can defer runtime updates until the next CPUID emulation. > + */ > + BUILD_BUG_ON(x86_feature == X86_FEATURE_APIC || > + x86_feature == X86_FEATURE_OSXSAVE || > + x86_feature == X86_FEATURE_OSPKE); > + > return vcpu->arch.cpu_caps[x86_leaf] & __feature_bit(x86_feature); > } > > diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c > index ae81ae27d534..cf74c87b8b3f 100644 > --- a/arch/x86/kvm/lapic.c > +++ b/arch/x86/kvm/lapic.c > @@ -2585,7 +2585,7 @@ static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value) > vcpu->arch.apic_base = value; > > if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > > if (!apic) > return; > diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c > index e0ab7df27b66..699e551ec93b 100644 > --- a/arch/x86/kvm/smm.c > +++ b/arch/x86/kvm/smm.c > @@ -358,7 +358,7 @@ void enter_smm(struct kvm_vcpu *vcpu) > goto error; > #endif > > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > kvm_mmu_reset_context(vcpu); > return; > error: > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index 09be12a44288..5e4581ed0ef1 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -3274,7 +3274,7 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm) > > if (kvm_ghcb_xcr0_is_valid(svm)) { > vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb); > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > } > > /* Copy the GHCB exit information into the VMCB fields */ > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index 07911ddf1efe..6a350cee2f6c 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -1936,7 +1936,7 @@ void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) > vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR); > > if ((cr4 ^ old_cr4) & (X86_CR4_OSXSAVE | X86_CR4_PKE)) > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > } > > static void svm_set_segment(struct kvm_vcpu *vcpu, > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index cf872d8691b5..b5f3c5628bfd 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -3516,7 +3516,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) > vmcs_writel(GUEST_CR4, hw_cr4); > > if ((cr4 ^ old_cr4) & (X86_CR4_OSXSAVE | X86_CR4_PKE)) > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > } > > void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg) > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index dc8829712edd..10b7d8c01e4d 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -1264,7 +1264,7 @@ static int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) > vcpu->arch.xcr0 = xcr0; > > if ((xcr0 ^ old_xcr0) & XFEATURE_MASK_EXTEND) > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > return 0; > } > > @@ -3899,7 +3899,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > if (!guest_cpu_cap_has(vcpu, X86_FEATURE_XMM3)) > return 1; > vcpu->arch.ia32_misc_enable_msr = data; > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > } else { > vcpu->arch.ia32_misc_enable_msr = data; > } > @@ -3934,7 +3934,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > if (data & ~kvm_caps.supported_xss) > return 1; > vcpu->arch.ia32_xss = data; > - kvm_update_cpuid_runtime(vcpu); > + vcpu->arch.cpuid_dynamic_bits_dirty = true; > break; > case MSR_SMI_COUNT: > if (!msr_info->host_initiated)