From: David Woodhouse <[email protected]> kvm_vcpu_ioctl_set_cpuid() runs kvm_vcpu_after_set_cpuid() on every plane twin, but only the calling vCPU is loaded. The vendor callback writes VMCS/VMCB controls, and on VMX those writes go to whatever VMCS is loaded on the current pCPU: the caller's, not the twin's. The twin's controls shadow is updated anyway, so the stale values in its real VMCS can never be corrected later; a twin created before KVM_SET_CPUID2 keeps its empty-CPUID controls (RDSEED/RDRAND exiting among them), and the guest's higher VTL takes a spurious #UD on its first RDSEED.
Swap the twin in as the loaded vCPU around its update. Plane ioctls all share the common vCPU mutex, so the twin cannot be loaded elsewhere concurrently. Signed-off-by: David Woodhouse <[email protected]> Assisted-by: LLM --- arch/x86/kvm/cpuid.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index fe8a793b1643..f744e7845843 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -592,7 +592,20 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2, #ifdef CONFIG_KVM_XEN v->arch.xen.cpuid = kvm_get_hypervisor_cpuid(vcpu, XEN_SIGNATURE); #endif + /* + * The ioctl loaded the calling vCPU; updating a twin's + * VMCS/VMCB controls requires that twin to be the loaded + * one, so swap it in around the update. + */ + if (v != vcpu) { + vcpu_put(vcpu); + vcpu_load(v); + } kvm_vcpu_after_set_cpuid(v); + if (v != vcpu) { + vcpu_put(v); + vcpu_load(vcpu); + } } success: -- 2.50.1

