[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260115232154.3021475-2-jmattson@google.com>
Date: Thu, 15 Jan 2026 15:21:40 -0800
From: Jim Mattson <jmattson@...gle.com>
To: Sean Christopherson <seanjc@...gle.com>, Paolo Bonzini <pbonzini@...hat.com>,
Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>, x86@...nel.org,
"H. Peter Anvin" <hpa@...or.com>, Shuah Khan <shuah@...nel.org>, kvm@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-kselftest@...r.kernel.org
Cc: Jim Mattson <jmattson@...gle.com>
Subject: [PATCH v2 1/8] KVM: x86: nSVM: Redirect IA32_PAT accesses to either
hPAT or gPAT
When the vCPU is in guest mode with nested NPT enabled, guest accesses to
IA32_PAT are redirected to the gPAT register, which is stored in
vmcb02->save.g_pat.
Non-guest accesses (e.g. from userspace) to IA32_PAT are always redirected
to hPAT, which is stored in vcpu->arch.pat.
This is architected behavior. It also makes it possible to restore a new
checkpoint on an old kernel with reasonable semantics. After the restore,
gPAT will be lost, and L2 will run on L1's PAT. Note that the old kernel
would have always run L2 on L1's PAT.
Signed-off-by: Jim Mattson <jmattson@...gle.com>
---
arch/x86/kvm/svm/svm.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 7041498a8091..3f8581adf0c1 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -2846,6 +2846,13 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_AMD64_DE_CFG:
msr_info->data = svm->msr_decfg;
break;
+ case MSR_IA32_CR_PAT:
+ if (!msr_info->host_initiated && is_guest_mode(vcpu) &&
+ nested_npt_enabled(svm))
+ msr_info->data = svm->vmcb->save.g_pat; /* gPAT */
+ else
+ msr_info->data = vcpu->arch.pat; /* hPAT */
+ break;
default:
return kvm_get_msr_common(vcpu, msr_info);
}
@@ -2929,14 +2936,24 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
break;
case MSR_IA32_CR_PAT:
- ret = kvm_set_msr_common(vcpu, msr);
- if (ret)
- break;
+ if (!kvm_pat_valid(data))
+ return 1;
- svm->vmcb01.ptr->save.g_pat = data;
- if (is_guest_mode(vcpu))
- nested_vmcb02_compute_g_pat(svm);
- vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
+ if (!msr->host_initiated && is_guest_mode(vcpu) &&
+ nested_npt_enabled(svm)) {
+ svm->vmcb->save.g_pat = data; /* gPAT */
+ vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
+ } else {
+ vcpu->arch.pat = data; /* hPAT */
+ if (npt_enabled) {
+ svm->vmcb01.ptr->save.g_pat = data;
+ vmcb_mark_dirty(svm->vmcb01.ptr, VMCB_NPT);
+ if (is_guest_mode(vcpu)) {
+ svm->vmcb->save.g_pat = data;
+ vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
+ }
+ }
+ }
break;
case MSR_IA32_SPEC_CTRL:
if (!msr->host_initiated &&
--
2.52.0.457.g6b5491de43-goog
Powered by blists - more mailing lists