Merge tag 'kvm-x86-pmu-6.6-fixes' of https://github.com/kvm-x86/linux into HEAD
[platform/kernel/linux-starfive.git] / arch / x86 / kvm / x86.c
index 42a4e8f..41cce50 100644 (file)
@@ -5382,26 +5382,37 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
-                                        struct kvm_xsave *guest_xsave)
-{
-       if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
-               return;
-
-       fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
-                                      guest_xsave->region,
-                                      sizeof(guest_xsave->region),
-                                      vcpu->arch.pkru);
-}
 
 static void kvm_vcpu_ioctl_x86_get_xsave2(struct kvm_vcpu *vcpu,
                                          u8 *state, unsigned int size)
 {
+       /*
+        * Only copy state for features that are enabled for the guest.  The
+        * state itself isn't problematic, but setting bits in the header for
+        * features that are supported in *this* host but not exposed to the
+        * guest can result in KVM_SET_XSAVE failing when live migrating to a
+        * compatible host without the features that are NOT exposed to the
+        * guest.
+        *
+        * FP+SSE can always be saved/restored via KVM_{G,S}ET_XSAVE, even if
+        * XSAVE/XCRO are not exposed to the guest, and even if XSAVE isn't
+        * supported by the host.
+        */
+       u64 supported_xcr0 = vcpu->arch.guest_supported_xcr0 |
+                            XFEATURE_MASK_FPSSE;
+
        if (fpstate_is_confidential(&vcpu->arch.guest_fpu))
                return;
 
-       fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu,
-                                      state, size, vcpu->arch.pkru);
+       fpu_copy_guest_fpstate_to_uabi(&vcpu->arch.guest_fpu, state, size,
+                                      supported_xcr0, vcpu->arch.pkru);
+}
+
+static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
+                                        struct kvm_xsave *guest_xsave)
+{
+       return kvm_vcpu_ioctl_x86_get_xsave2(vcpu, (void *)guest_xsave->region,
+                                            sizeof(guest_xsave->region));
 }
 
 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,