]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: x86: Define KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT
authorJim Mattson <jmattson@google.com>
Tue, 7 Apr 2026 19:03:24 +0000 (12:03 -0700)
committerSean Christopherson <seanjc@google.com>
Thu, 14 May 2026 12:45:07 +0000 (05:45 -0700)
Define a quirk to control whether nested SVM shares L1's PAT with L2
(legacy behavior) or gives L2 its own independent gPAT (correct behavior
per the APM).

When the quirk is enabled (default), L2 shares L1's PAT, preserving the
legacy KVM behavior. When userspace disables the quirk, KVM correctly
virtualizes the PAT for nested SVM guests, giving L2 a separate gPAT as
specified in the AMD architecture.

Signed-off-by: Jim Mattson <jmattson@google.com>
Link: https://patch.msgid.link/20260407190343.325299-2-jmattson@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Documentation/virt/kvm/api.rst
arch/x86/include/asm/kvm_host.h
arch/x86/include/uapi/asm/kvm.h
arch/x86/kvm/svm/svm.h

index 52bbbb553ce107bea5f34b65ee64a34319467686..59469495c8d3ae63422d40e7305ceff107c52b9e 100644 (file)
@@ -8553,6 +8553,20 @@ KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM   By default, KVM relaxes the consisten
                                            bit to be cleared.  Note that the vmcs02
                                            bit is still completely controlled by the
                                            host, regardless of the quirk setting.
+
+KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT        By default, KVM for nested SVM guests
+                                           shares the IA32_PAT MSR between L1 and
+                                           L2. This is legacy behavior and does
+                                           not match the AMD architecture
+                                           specification. When this quirk is
+                                           disabled and nested paging (NPT) is
+                                           enabled for L2, KVM correctly
+                                           virtualizes a separate guest PAT
+                                           register for L2, using the g_pat
+                                           field in the VMCB. When NPT is
+                                           disabled for L2, L1 and L2 continue
+                                           to share the IA32_PAT MSR regardless
+                                           of the quirk setting.
 ========================================   ================================================
 
 7.32 KVM_CAP_MAX_VCPU_ID
index 8a53ca619570175e99ef6452296ac4f863c3de34..ef353daeacc958fdc529be965c1c796f0ac917c0 100644 (file)
@@ -2550,7 +2550,8 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages);
         KVM_X86_QUIRK_SLOT_ZAP_ALL |           \
         KVM_X86_QUIRK_STUFF_FEATURE_MSRS |     \
         KVM_X86_QUIRK_IGNORE_GUEST_PAT |       \
-        KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM)
+        KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM |     \
+        KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT)
 
 #define KVM_X86_CONDITIONAL_QUIRKS             \
        (KVM_X86_QUIRK_CD_NW_CLEARED |          \
index 5f2b30d0405c876516094fb0c1adf837916212e0..3ada2fa9ca865789c9a99daa028b58e56b2b3e0c 100644 (file)
@@ -477,6 +477,7 @@ struct kvm_sync_regs {
 #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS       (1 << 8)
 #define KVM_X86_QUIRK_IGNORE_GUEST_PAT         (1 << 9)
 #define KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM (1 << 10)
+#define KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT    (1 << 11)
 
 #define KVM_STATE_NESTED_FORMAT_VMX    0
 #define KVM_STATE_NESTED_FORMAT_SVM    1
index 19b80ef56e2b79f503d7c4a0d4fb15bcdda12fc5..9fd2232aa8d1937f07db9137d9a2d289d21ad9df 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "cpuid.h"
 #include "kvm_cache_regs.h"
+#include "x86.h"
 
 /*
  * Helpers to convert to/from physical addresses for pages whose address is
@@ -641,6 +642,16 @@ static inline bool nested_npt_enabled(struct vcpu_svm *svm)
        return svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_NP;
 }
 
+static inline bool l2_has_separate_pat(struct kvm_vcpu *vcpu)
+{
+       /*
+        * If KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled while a vCPU
+        * is running, the L2 IA32_PAT semantics for that vCPU are undefined.
+        */
+       return nested_npt_enabled(to_svm(vcpu)) &&
+              !kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT);
+}
+
 static inline bool nested_vnmi_enabled(struct vcpu_svm *svm)
 {
        return guest_cpu_cap_has(&svm->vcpu, X86_FEATURE_VNMI) &&