On Thu, Mar 26, 2026 at 10:50 AM Jim Mattson <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
>  Documentation/virt/kvm/api.rst  | 14 ++++++++++++++
>  arch/x86/include/asm/kvm_host.h |  3 ++-
>  arch/x86/include/uapi/asm/kvm.h |  1 +
>  arch/x86/kvm/svm/svm.h          |  7 +++++++
>  4 files changed, 24 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 032516783e96..2d56f17e3760 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -8551,6 +8551,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
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index d3bdc9828133..0809d8f28208 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -2511,7 +2511,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       \

There is a missing "|" here, it's fixed in patch 3, but I think it
should be fixed up here (maybe when applied).

> +        KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT)
>
>  #define KVM_X86_CONDITIONAL_QUIRKS             \
>         (KVM_X86_QUIRK_CD_NW_CLEARED |          \
> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
> index 5f2b30d0405c..3ada2fa9ca86 100644
> --- a/arch/x86/include/uapi/asm/kvm.h
> +++ b/arch/x86/include/uapi/asm/kvm.h
> @@ -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
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index ff1e4b4dc998..67aa5d34332e 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -616,6 +616,13 @@ 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 vcpu_svm *svm)
> +{
> +       return nested_npt_enabled(svm) &&
> +               !kvm_check_has_quirk(svm->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) &&
> --
> 2.53.0.1018.g2bb0e51243-goog
>

Reply via email to