]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: SVM: Skip OSVW variable updates if current CPU's errata are a subset
authorSean Christopherson <seanjc@google.com>
Thu, 13 Nov 2025 23:14:19 +0000 (15:14 -0800)
committerSean Christopherson <seanjc@google.com>
Tue, 3 Mar 2026 20:23:26 +0000 (12:23 -0800)
Elide the OSVW variable updates if the current CPU's set of errata are a
subset of the errata tracked in the global values, i.e. if no update is
needed.  There's no danger of under-reporting errata due to bailing early
as KVM is purely reducing the set of "known fixed" errata.  I.e. a racing
update on a different CPU with _more_ errata doesn't change anything if
the current CPU has the same or fewer errata relative to the status quo.

If another CPU is writing osvw_len, then "len" is guaranteed to be larger
than the new osvw_len and so the osvw_len update would be skipped anyways.

If another CPU is setting new bits in osvw_status, then "status" is
guaranteed to be a subset of the new osvw_status and the bitwise-OR would
be an effective nop anyways.

Link: https://patch.msgid.link/20251113231420.1695919-5-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c

index 7fccb3d72e1862da5968caeb239b229e82eed74b..5c4328f426049b3b7492fe74d60128a48fd9b44c 100644 (file)
@@ -424,7 +424,6 @@ static void svm_init_osvw(struct kvm_vcpu *vcpu)
 static void svm_init_os_visible_workarounds(void)
 {
        u64 len, status;
-       int err;
 
        /*
         * Get OS-Visible Workarounds (OSVW) bits.
@@ -453,20 +452,19 @@ static void svm_init_os_visible_workarounds(void)
                return;
        }
 
-       err = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &len);
-       if (!err)
-               err = native_read_msr_safe(MSR_AMD64_OSVW_STATUS, &status);
+       if (native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &len) ||
+           native_read_msr_safe(MSR_AMD64_OSVW_STATUS, &status))
+               len = status = 0;
+
+       if (status == READ_ONCE(osvw_status) && len >= READ_ONCE(osvw_len))
+               return;
 
        guard(spinlock)(&osvw_lock);
 
-       if (err) {
-               osvw_status = osvw_len = 0;
-       } else {
-               if (len < osvw_len)
-                       osvw_len = len;
-               osvw_status |= status;
-               osvw_status &= (1ULL << osvw_len) - 1;
-       }
+       if (len < osvw_len)
+               osvw_len = len;
+       osvw_status |= status;
+       osvw_status &= (1ULL << osvw_len) - 1;
 }
 
 static bool __kvm_is_svm_supported(void)