From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 522213451C1 for ; Fri, 27 Mar 2026 23:40:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654832; cv=none; b=lg8gw+WLEKmFukxr5aOVw1Rrap5DkfzR+q0Gx3nenJHFnijBDLbIHEdYFyLsLAFmxrmiwIM2n7x3eB8OMn0/vPGRvlwr3FtoqcJHOZpwfM6OSfaUWOh+xBV+xersBMl5sZPC072esLnzA0KlMMkOAoy80O/ipSkDF5E9FrPyL0Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654832; c=relaxed/simple; bh=NJXEJgy4bPsYXdgxGBE9MnVX3jvlhx2jJ8S0FqDBjHI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YTXwJWoAwRBAd63CS7+Ux65AbnFGzi15F3n9ZVsAiwTnhjDfRNnhJ+yv+nadFnMtq1CnAsbqncn2uwpWuyIL8uCjHw82En6gdBVVi/T9eVMmbyaa14NDH2LQ8KnlhI/1M7e1ilRaO+9ezposw+dTXblgWMQ9eGEWYxLsZH6Qx7Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=EBPX9jNc; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="EBPX9jNc" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2b0c8d0df40so53249105ad.2 for ; Fri, 27 Mar 2026 16:40:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654830; x=1775259630; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=uZDHXOjvuNOIQxgTZwaBEqdL2bgAcnxDW6LrcDeA+rU=; b=EBPX9jNcbQQ2/z6H3hKfEK03n0pIBKicthb1MAf3U0tLYRRgHwNP3dQ9ucNbPyQDHI 7Qb7VsKmSEq3Qiu8zTJL3kgIHobAIt70aKL7jzDFP9LJ6cCm3/yE5GP9NPf6D+KTvRwh 8yZc+gLMdFpVPg0285HGkjSVbqYVhKYWEf+atzBzO6wb8gMlxAfCWgBUP0fU3HvBXdk6 zO8RJOQrX8a0xIF20fUKArrBTwVYIQbGV9T24FX/fdGQfeOu9o1aFjVx+uhnB++3/pCm PFXDjrlzM5sy+x824gp6Tl1MitQZsGUTxBNXXzNMoti08GKBi0YwbwZ5ZZmLXMQ6GPoZ 2/AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654830; x=1775259630; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=uZDHXOjvuNOIQxgTZwaBEqdL2bgAcnxDW6LrcDeA+rU=; b=Cgg9bhLIJKsKjDa6Wgw0bf5CcGkzGaAG1xBu+kY5wx1aWrgG+/DCrBhEbkfK4l5drf rhSyWsOIuvDu/g+QY5zHWurT2JUpIjuB0KflsRm/mVouaNc2/B3sjjMtXnnqYZ3N3Avh NwtdSBlOMan/VRbR79DYP1rhopFUchuSskvfIrNG6sCKTZVIuM+00f2aL6Q6UsUDH9iq SUfv99TOPdkEdzy6WImwIqY8xJQXqJ9XhDrdzLSsKYlAIXob+zU/PKepzxCQ0eD1Km7q cPVB2LTxV3YzeUVoy0HtxQdiJI2PZW6DQhZ4XipADPzjb0OMTg5vJ5dcnlFboApVk0hq E/AA== X-Forwarded-Encrypted: i=1; AJvYcCXG/cqix16fJoDLHI7yTDxcSyIVzJ+yWMkVzgFnewXz4u/iVXyX1WL55yo/UUqYpRpI02vOCNxcq2IZJ5U=@vger.kernel.org X-Gm-Message-State: AOJu0YxyL2taNiSnuJ9lDJvwla3v7DHDLxsmWm45eR8YljwgrVB2fGkl bP6b9NkbPK1ETTJV0JAUtXkUA0LToEw7xGyBpElIcabKEWIABdWgadcyvS/81s4FuzEKZQxshk8 9ENyBhcXxSHQL9A== X-Received: from plbw4.prod.google.com ([2002:a17:902:d3c4:b0:2b0:6147:a0ee]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:4407:b0:2b0:5e10:9dbd with SMTP id d9443c01a7336-2b0cdbeb419mr45733875ad.3.1774654830227; Fri, 27 Mar 2026 16:40:30 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:08 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-2-jmattson@google.com> Subject: [PATCH v7 1/9] KVM: x86: Define KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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 | 11 +++++++++++ 4 files changed, 28 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 defaul= t, KVM relaxes the consisten bit to be cleared. Note that t= he vmcs02 bit is still completely control= led by the host, regardless of the quirk s= etting. + +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 cont= inue + to share the IA32_PAT MSR regar= dless + of the quirk setting. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 7.32 KVM_CAP_MAX_VCPU_ID diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index d3bdc9828133..0b4ab141feae 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 | \ + KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT) =20 #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/kv= m.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) =20 #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..74014110b550 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -616,6 +616,17 @@ static inline bool nested_npt_enabled(struct vcpu_svm = *svm) return svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_NP; } =20 +static inline bool l2_has_separate_pat(struct vcpu_svm *svm) +{ + /* + * 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(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) && --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D1C2239E19F for ; Fri, 27 Mar 2026 23:40:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654836; cv=none; b=S4bk/OSryzAHxpW7PZQ0L7gpP+x8r6udVJIvK1Y/KlbdHDhUpIJnvuPV8+GfNXKr2jW6nckmoal+FXS0CZh/IJDSkAayKE33zIumpeI1OcmxnsQizJFg9nnl6DJ03AMNch3+P3TTckJh4+xFhNjwyFQ+/fwH7xnwJXVBHVVQzn0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654836; c=relaxed/simple; bh=zQH8QY/cLFF1GBuomhulf/vBI5L31KzAMmoyN+E+i6E=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rZ7vQ52kEH0OrvrWMe2wqLf1/SXzgrf5dnvLsdm1qg1K5R/cGI07hzisLLfk0Gg3PCmYRe6mNr0+b0IN2U5K5lU4skVUlcXi22mERbgLHdRJO9FaIWEGBmLaINSwbwcGSSlfGQCeI7v9jK8FvVlbeCP8hsEco6FIJJW0NYYvLHk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=dbI+gFCl; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="dbI+gFCl" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2b0be75dfd4so35682365ad.1 for ; Fri, 27 Mar 2026 16:40:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654832; x=1775259632; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=bFrhht4F+Ql8p4REBNfHrn2pw253p4SlLxIhEftRqHY=; b=dbI+gFClmLUYBnwWBGa+Y5RX8u1dUTRxd3JsLFwDNKXK691O6YTDo7vxzCFoDDum3m CcISLCmAyJxD8xugTxFzE1UKrsGcgjG9l9mWLCjpEJDa74O1zG59QYQK7Si9eBnQHoup 7FoIhtj/QHWfBdyPDmGS1QYIGikJL5o1MmCrg8JBftsO8EgaKgsJL2XAfWJ2133kZ85P u/m/WNh8AbRfHz719XLd8/0bUdOQYimVwfS886kNVjuh/GYVMiCiMWa7aloGNBVPxtkW S1GeU/gufuzXONmoTwfIdwd1IDQZfbnNZJvOoPOey0cKvHOkp1wyV/YCbxJ5KD6ttqMJ AJ4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654832; x=1775259632; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=bFrhht4F+Ql8p4REBNfHrn2pw253p4SlLxIhEftRqHY=; b=biT3MG7MbN2jSaHehdV+afDCRmdHzVFslU2YGLWDzT8lwlLcgEUi7yBFJmtn1RQllv 3bhr7GAls+UVyrHOhu+tGnYsgbyiCtGcjtObC4ocn+DAFmr7L7TbU+SUMz+mzKxOQiX8 XIpm7LWD2D8Z1GE823CqetEqyvLp9937FegHqBSCn03eg7EVaX4DxZ2qVWv/Rj7VNOHw Cr79X3ADUp7nomKxuo8nByZGNAXkQiIZKi3kpeEPnzdZJX9Llugr0J+DZWScQfri9Q4u ZGcrPIhYWDm2eNgK8dOVHkYqx+372rMWAZsNXcc8aH4aN1dao052Cq9SWFWnLv0Lt1tw mIpg== X-Forwarded-Encrypted: i=1; AJvYcCU4hvua6cxtf7C9dVbuIf8XTcNwXWNgE+xizEDMeQG5dkuC1hFozdKaL16PniHodH804SY8zk1hPJmbzzk=@vger.kernel.org X-Gm-Message-State: AOJu0YyMP3+ojw9zIEVQ8OWKHu9rB0N+wX2npOkQyPjjTB4LD6r51/us /KFea5bErRRTLnjfYoVUv3ptw7KWnUibbyv/Ktv0SodoKNV5JwXJ/CgammhSwcen18OZB/xtNbI D6gR1TmF/SofIEQ== X-Received: from plbkg5.prod.google.com ([2002:a17:903:605:b0:2ae:3bca:37a5]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:e5cc:b0:2b0:b290:f2f4 with SMTP id d9443c01a7336-2b0cdd40053mr48908955ad.32.1774654831920; Fri, 27 Mar 2026 16:40:31 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:09 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-3-jmattson@google.com> Subject: [PATCH v7 2/9] KVM: x86: nSVM: Clear VMCB_NPT clean bit when updating hPAT from guest mode From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When running an L2 guest and writing to MSR_IA32_CR_PAT, the host PAT value is stored in both vmcb01's g_pat field and vmcb02's g_pat field, but the clean bit was only being cleared for vmcb02. Introduce the helper vmcb_set_gpat() which sets vmcb->save.g_pat and marks the VMCB dirty for VMCB_NPT. Use this helper in both svm_set_msr() for updating vmcb01 and in nested_vmcb02_compute_g_pat() for updating vmcb02, ensuring both VMCBs' NPT fields are properly marked dirty. Fixes: 4995a3685f1b ("KVM: SVM: Use a separate vmcb for the nested L2 guest= ") Signed-off-by: Jim Mattson --- arch/x86/kvm/svm/nested.c | 2 +- arch/x86/kvm/svm/svm.c | 3 +-- arch/x86/kvm/svm/svm.h | 6 ++++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 5ff01d2ac85e..32fa8e688c00 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -697,7 +697,7 @@ void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm) return; =20 /* FIXME: merge g_pat from vmcb01 and vmcb12. */ - svm->nested.vmcb02.ptr->save.g_pat =3D svm->vmcb01.ptr->save.g_pat; + vmcb_set_gpat(svm->nested.vmcb02.ptr, svm->vmcb01.ptr->save.g_pat); } =20 static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d2ca226871c2..af808e83173e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2979,10 +2979,9 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct= msr_data *msr) if (ret) break; =20 - svm->vmcb01.ptr->save.g_pat =3D data; + vmcb_set_gpat(svm->vmcb01.ptr, data); if (is_guest_mode(vcpu)) nested_vmcb02_compute_g_pat(svm); - vmcb_mark_dirty(svm->vmcb, VMCB_NPT); break; case MSR_IA32_SPEC_CTRL: if (!msr->host_initiated && diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 74014110b550..a1d62c3cc3d6 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -439,6 +439,12 @@ static inline bool vmcb12_is_dirty(struct vmcb_ctrl_ar= ea_cached *control, int bi return !test_bit(bit, (unsigned long *)&control->clean); } =20 +static inline void vmcb_set_gpat(struct vmcb *vmcb, u64 data) +{ + vmcb->save.g_pat =3D data; + vmcb_mark_dirty(vmcb, VMCB_NPT); +} + static __always_inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) { return container_of(vcpu, struct vcpu_svm, vcpu); --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1E3A139E196 for ; Fri, 27 Mar 2026 23:40:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654838; cv=none; b=YXeYr0VGLN28xJ/kntrecw8prZ9LiBoY8t/zBspya57IFu41Dl20/JJt7qtxE3lJUw2+gLLvwmRLTrqe/7be7NPZ8x74BTFPS6SsdAjFIfduUGbm9h/u3r6iI5sbr1g0gjFucpG//AGzAjuUpxxRC7LpdCxmaEqSwP/lDHTn9r0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654838; c=relaxed/simple; bh=RPbgJ0c4Fa9PKqVXhRieBWd7nnk0p+dj+Ta6IzkqBl8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=e56/IrtBxrT2IKHMKTbOce2bJ1wjNgapre9EY1S12EDk//B8aD7MOZlMJA8JPAB7vwQO7DaZUMn/AL+gy1FRVpFDIUwMpiYpTOf3vDTSaANL2iMVGtClcybQYCqore/ahW+D/6zepHqhIwpsy7ajo2RM4E39lN276SVGM0fEtY4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ujRbNi7H; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ujRbNi7H" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-358df8fbd1cso3293117a91.0 for ; Fri, 27 Mar 2026 16:40:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654834; x=1775259634; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=9qAI9OI68WEJnrwpx1Qcu7Sb9TsTUzYiN2XdEpiva10=; b=ujRbNi7HIUqcDr3dOn6EOjxSI9jMqWY0F60O9i23N8x50vbrLw5Z25TwNE8ZPuwekd 6G3+RU6LiP/+ewzfQeAicnbvcobIiXeKCGvGyo6q8qyhx8fP54EltRq7W4abe7kodSXN 7m4/X2LS5Zce18IO0+waXLJVSmU2B9BKEzjR4WVS8EOlBbB+bKrLOfA2lKT2PBW90K33 uMUXw9ePXZD32+DQqfjb3Im3E9Uug+9i45PaLta8vZRUL06sSM3s9EWRtJ3UFY6EjmRV NOM4Ap9k5tIYJJDAkWY/QSUwG1vXQZddGhYZ4G8E2CHKa2zSMqbFt3El6Ii4Ry6yuugt lmLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654834; x=1775259634; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=9qAI9OI68WEJnrwpx1Qcu7Sb9TsTUzYiN2XdEpiva10=; b=dFF/RhaxqGIw2CAonHNEQcHzPYl7oqTvPBsiP/vB6PrLqJb1zks/s8ZJONxWLpSh9b 3fJmE4RC/3ZAkLCa0eKvUSPy5UCBMStdmA4IlrxLBhacNZgX0C8rQz8+ptsWuIdZddwB i5SSTmErLcx6K9nYavRN01xu4w/K/9L37HKdCk3ncX5X4aMfn3YvmGHVRK/fLKKktdFM 8HUlAzvnvWABw/fftxhZtbZ3ecfcUCuUIOVRMm5W6xhkzOijgOUqNrDtY7tm4AprFkaO uLCJAcQqD+X9al7uZTKwh+AJNZhx6IYje9AvLzDt14IqoH43hEZLb4IXuoNiiI6Lu7fI cRkA== X-Forwarded-Encrypted: i=1; AJvYcCXpZtqxMi4rtczxjy91NokmihCQEvV2fYSDi8is/idKGQ+E772C3GCSQaTyK2fl23k+Vofm0IWO/EQJ378=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/ToJLTQAJsKoXU6bmbwVaiE91UXzMyuItJY/HLo4NDeBaBiXV +wze6/voV+rOj7InnBEb3q7hSkh8bxxOnE7ClXtrDqMSi6I3BNmE+AuUp/+bUndXSX6J1VkcdI8 YMWxX4HFhKopBqg== X-Received: from pjzb14.prod.google.com ([2002:a17:90a:e38e:b0:359:7e40:7d79]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3cce:b0:356:7b41:d348 with SMTP id 98e67ed59e1d1-35c300b9811mr3853636a91.20.1774654833713; Fri, 27 Mar 2026 16:40:33 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:10 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-4-jmattson@google.com> Subject: [PATCH v7 3/9] KVM: x86: nSVM: Cache and validate vmcb12 g_pat From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled and nested paging is enabled in vmcb12, validate g_pat at emulated VMRUN and cause an immediate VMEXIT with exit code VMEXIT_INVALID if it is invalid, as specified in the APM, volume 2: "Nested Paging and VMRUN/VMEXIT." Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler") Signed-off-by: Jim Mattson --- arch/x86/kvm/svm/nested.c | 23 +++++++++++++++++++---- arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 32fa8e688c00..cb837842f2c3 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -410,7 +410,8 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu = *vcpu, =20 /* Common checks that apply to both L1 and L2 state. */ static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu, - struct vmcb_save_area_cached *save) + struct vmcb_save_area_cached *save, + bool check_gpat) { if (CC(!(save->efer & EFER_SVME))) return false; @@ -445,6 +446,15 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vc= pu, if (CC(!kvm_valid_efer(vcpu, save->efer))) return false; =20 + /* + * If userspace contrives to get an invalid g_pat into vmcb02 by + * disabling KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT in a race with + * this check, it should be prepared for the KVM_EXIT_FAIL_ENTRY + * that will follow. + */ + if (check_gpat && CC(!kvm_pat_valid(save->g_pat))) + return false; + return true; } =20 @@ -452,7 +462,8 @@ int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcp= u) { struct vcpu_svm *svm =3D to_svm(vcpu); =20 - if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + if (!nested_vmcb_check_save(vcpu, &svm->nested.save, + l2_has_separate_pat(svm)) || !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) return -EINVAL; =20 @@ -562,6 +573,7 @@ static void __nested_copy_vmcb_save_to_cache(struct vmc= b_save_area_cached *to, =20 to->rax =3D from->rax; to->cr2 =3D from->cr2; + to->g_pat =3D from->g_pat; =20 svm_copy_lbrs(to, from); } @@ -1971,13 +1983,16 @@ static int svm_set_nested_state(struct kvm_vcpu *vc= pu, =20 /* * Validate host state saved from before VMRUN (see - * nested_svm_check_permissions). + * nested_svm_check_permissions). Note that the g_pat field is not + * validated, because (a) it may have been clobbered by SMM before + * KVM_GET_NESTED_STATE, and (b) it is not loaded at emulated + * #VMEXIT. */ __nested_copy_vmcb_save_to_cache(&save_cached, save); if (!(save->cr0 & X86_CR0_PG) || !(save->cr0 & X86_CR0_PE) || (save->rflags & X86_EFLAGS_VM) || - !nested_vmcb_check_save(vcpu, &save_cached)) + !nested_vmcb_check_save(vcpu, &save_cached, false)) goto out_free; =20 =20 diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index a1d62c3cc3d6..b43e37b0448c 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -161,6 +161,7 @@ struct vmcb_save_area_cached { u64 isst_addr; u64 rax; u64 cr2; + u64 g_pat; u64 dbgctl; u64 br_from; u64 br_to; --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pg1-f201.google.com (mail-pg1-f201.google.com [209.85.215.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3DBB39E6FC for ; Fri, 27 Mar 2026 23:40:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654839; cv=none; b=jsKcgzws4cr2qBItlikxwS7GPIu07j8xm+T2YOLjk0zJks78zVkG4+dSjA6Fxnv0cfq85PLGhumb+BrC/fqTslLvoR5BbJ4kqbleHYn7OQK45ouUJ1mJkFghn10moUf1MxY/Hw9h8uwODpgGNf1LwUgL3gDL1Nfq7dgqpcYpqfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654839; c=relaxed/simple; bh=NlXwBnZ1bTT+62YJ+MeeQ/QO8FkcP8rapcnFH5xIbuA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hUWUf6lxvjuAgJrSGrV6wStDxxWau8MVKwUVMKApkZL0h0AhjgiqTM5cWNol1SlHJvTHnqYu3s62Ig4xyShLfrbPR9pO4WS6NyB3DMoVReJQHuAAmA0CHdhmA6pLLL7g7ldf8Eau/J0Vhhb4J7rNS2EFys5XBYmEE19QkwOHso4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=fVG/htAD; arc=none smtp.client-ip=209.85.215.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="fVG/htAD" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-c709551ec08so4747244a12.3 for ; Fri, 27 Mar 2026 16:40:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654835; x=1775259635; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=1xllQ07LuXMkS9oh5VHlxnSe05QNYm8Ww7MJ9nxpGyM=; b=fVG/htADpTYmQ50SKYjj0FReDTfirulftJHyE6R2tRxMLA8y+v21xmPiVOSNF/VB4r IJCm/Ex1MCixC7dWywBVutv3o48J7VrTJCSXlI6ASIhtodKIExz/pPgg09YyJ5vthBOS RimIC0gZ/1tvCM+SpzOz3G3lrBzO2LbuJPJYo1qu9RxiCAq0TwYclmmN6NO/Arp4jK97 KOfPPW3lshZO7F9YKjIKxEz4JHnAiHThmuPhuIp/nkwEZE7wT5n/u3+VWG51n0A4RhBx vB+nai53OTd2P/L79bj8vHktoGjQbsCa6Gb8SbDaVRcpERVvDjFOFcfIlOCklgcIK9cO j0hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654835; x=1775259635; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=1xllQ07LuXMkS9oh5VHlxnSe05QNYm8Ww7MJ9nxpGyM=; b=UYXXOXzJDp4KJf8iOwuqaxaGAFOnKTefd3T6ti7d+ZABJbuV2Aa5LdKHTDRso16QuE U8VrunHHud1Z9RkX6evPiJcBtldcf+ZnOeWMsW0W6bHYnnsDqXktEWG02MUZLlodZ3sR SyeNY+N6b4m8Y9Qtyj8lvy/3fodimZn035YKimWbTJ2As+/KzheQLOcs/dBsMkPkEOqf PAy2tgFmxZA0s6nthlb+tBeDTdFmuVXA+9DJ16Zf31ZWQQKUzBE4CyRq673R4gYVbIg7 QFQXDB51DL0TKyYJz3U46GKG/7uhEeHnPfQmJxc+XgWU5/lgqDxZ9TEm4BRto0bc9PMA T5Fw== X-Forwarded-Encrypted: i=1; AJvYcCXOTi7sMpSreRI5Xoga5bnIoUTxMYm9SQ869F3bCKi+H/eLUgXzKWUbogbHmvkm+l9eUEzMtJeTci2reXk=@vger.kernel.org X-Gm-Message-State: AOJu0Yw2s2j71OhWJHXvb3AgI/eeszmjU4gaiSQlTRZIU7LuIAX9uR5n 7GCVVver7J6brLPr3figbLWsuekzAYFg75KGuW27KhavravDXwl57HLK261yYCzgrFZoip/c/ms MZWs5jU1wnbJE7A== X-Received: from pfjt19.prod.google.com ([2002:a05:6a00:21d3:b0:82c:6ae6:e5b]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:9a6:b0:82c:6d88:2a8e with SMTP id d2e1a72fcca58-82c95c1133emr4446772b3a.20.1774654835305; Fri, 27 Mar 2026 16:40:35 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:11 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-5-jmattson@google.com> Subject: [PATCH v7 4/9] KVM: x86: nSVM: Set vmcb02.g_pat correctly for nested NPT From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled and nested NPT is enabled in vmcb12, copy the (cached and validated) vmcb12 g_pat field to vmcb02's g_pat, giving L2 its own independent guest PAT register. When the quirk is enabled (default), or when NPT is enabled but nested NPT is disabled, copy L1's IA32_PAT MSR to the vmcb02 g_pat field, since L2 shares the IA32_PAT MSR with L1. When NPT is disabled, the g_pat field is ignored by hardware. Fixes: 15038e147247 ("KVM: SVM: obey guest PAT") Signed-off-by: Jim Mattson --- arch/x86/kvm/svm/nested.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index cb837842f2c3..8170042d5fb3 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -727,9 +727,6 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm = *svm) struct vmcb *vmcb02 =3D svm->nested.vmcb02.ptr; struct kvm_vcpu *vcpu =3D &svm->vcpu; =20 - nested_vmcb02_compute_g_pat(svm); - vmcb_mark_dirty(vmcb02, VMCB_NPT); - /* Load the nested guest state */ if (svm->nested.vmcb12_gpa !=3D svm->nested.last_vmcb12_gpa) { new_vmcb12 =3D true; @@ -760,6 +757,13 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm= *svm) vmcb_mark_dirty(vmcb02, VMCB_CET); } =20 + if (l2_has_separate_pat(svm)) { + if (unlikely(new_vmcb12 || vmcb12_is_dirty(control, VMCB_NPT))) + vmcb_set_gpat(vmcb02, svm->nested.save.g_pat); + } else if (npt_enabled) { + vmcb_set_gpat(vmcb02, vcpu->arch.pat); + } + kvm_set_rflags(vcpu, save->rflags | X86_EFLAGS_FIXED); =20 svm_set_efer(vcpu, svm->nested.save.efer); --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 241F63A0B31 for ; Fri, 27 Mar 2026 23:40:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654841; cv=none; b=Na8vcwUTj+w3jc3sqRjdt5DDKcuaDpcBBW+XBW3Rhwpuo7Gwyh4KqLICIm+pD1PjxbLWufLiIWghhiwqH/4X2hL1DiqkDqcuWLEKmXUVXfwik3Cb5XXfsyI8T0wNxlxGzXyhVgQPj536jRcybO0axWtw9/Bb0UmwpDMvKMQoiTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654841; c=relaxed/simple; bh=OuR5MnB8UCFuMwjbw9rq52TUW4H3/Wius8t683uVsjc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ILJcfG2DUCT6AmCDN828PKo08mp4afAORAuopdoru11AD+JIUpS1mnnOMStfKrmgx9E3hdX0AnS7SLf2j1SD3Gxu5Qpy56kkllxuLrnl27w3uS9CwOkkVOYm2sN4mBtTA+naqXTn9I5Z/MXTtrX649PJXx8fcEyj9LzB3aOS38E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=GENvC0uo; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="GENvC0uo" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-35d9010602bso530538a91.3 for ; Fri, 27 Mar 2026 16:40:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654837; x=1775259637; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=7y5HwBTSkwgoBBimZJGgWbMuctVLczxWfxP1tKWmKTY=; b=GENvC0uocV7kZaorplM7AuKAW/NO3vXV/4eXpLzfG6Lu4u5XBKAxWdnMe5Mi9RfOXc So3bQpiHlQSriHyws3SvFq3Ge1W1nAg8jAyZ83FFYqgo32sdlWm7KpAwweOm3Y7AwEUN DtVgfEJh9Zr9U0xWtKklZPHmOmQyMp/BacLrFCCFiMUCaWcawc5KshUsevYyi4yhBh07 cwLOK+LYlMGUer3pP80oEkE+bQlfNNpvDnoa60XAQYbXzM4wExs96X1Jk9yneWZqcGke SaVnX7FpADi6cbt88ubO88vy41HVBtwotJQGvqtXq1K9bKS21f/WUp/ODdo8NM7GjmKr +YNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654837; x=1775259637; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=7y5HwBTSkwgoBBimZJGgWbMuctVLczxWfxP1tKWmKTY=; b=eyGC2BKZ8OdJNxBntcVYvGbMmV4Pwt3oKVmMUhkqm0cQKfjYQbQFClasaDoQuSmHE4 Y+NyFqtCHeYqdXCSuyWcSTUocR9CWus0h3mXgjULl1gHc4OLq5ufof/8gRSZKR79VrLn z5hOIypI+8wet8XCyDeB29W2VlyvGlWr5DFj3jtdjLAY+bVF5Br/fHs/oJv9bIpn+KdT tahKW6tiPHUZ2gUY6k/QPysKiRF1DbW8PEfMjDl6ursgV3u4JhvNLz3auBkKmmPG2pvV 2opQ3z1j7b9tVhbHLzsgwp25IIdSfkmJ8aA6Ja4FsIFu7l0iha0TV1VckxNAL/py8+qs ivdA== X-Forwarded-Encrypted: i=1; AJvYcCXilRuBAVBuNXAaahXQ1/WoqnPxz7d4CQaBpee9CiBju6RovDKXCSM9YeN4cKmC/pnr9vdTKUaG0Kqu2a0=@vger.kernel.org X-Gm-Message-State: AOJu0YxiqBTximu0ykxJm7s8by7XZIQ8QKb7LnDGS8aWukkDvIewnmp9 br8n+WRn+rICrTmRzEU5hjPA9hJWF6i+KRjPN05zA60XMowZjX+lmADZG2pOe32AYpUOADA+M4L S2D3wuRG1SahPEA== X-Received: from pjbhv24.prod.google.com ([2002:a17:90a:e418:b0:35d:9373:e7d3]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3b4f:b0:35c:cba:3453 with SMTP id 98e67ed59e1d1-35c30076fe2mr4269476a91.22.1774654837106; Fri, 27 Mar 2026 16:40:37 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:12 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-6-jmattson@google.com> Subject: [PATCH v7 5/9] KVM: x86: nSVM: Redirect IA32_PAT accesses to either hPAT or gPAT From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled and 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's g_pat field. Non-guest accesses (e.g. from userspace) to IA32_PAT are always redirected to hPAT, which is stored in vcpu->arch.pat. Directing host-initiated accesses to hPAT ensures that KVM_GET/SET_MSRS and KVM_GET/SET_NESTED_STATE are independent of each other and can be ordered arbitrarily during save and restore. gPAT is saved and restored separately via KVM_GET/SET_NESTED_STATE. Use WARN_ON_ONCE to flag any host-initiated accesses originating from KVM itself rather than userspace. Use pr_warn_once to flag any use of the common MSR-handling code (now shared by VMX and TDX) for IA32_PAT by a vCPU that is SVM-capable. Fixes: 15038e147247 ("KVM: SVM: obey guest PAT") Signed-off-by: Jim Mattson Co-developed-by: Sean Christopherson Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/nested.c | 9 ------- arch/x86/kvm/svm/svm.c | 53 ++++++++++++++++++++++++++++++++++----- arch/x86/kvm/svm/svm.h | 1 - arch/x86/kvm/x86.c | 6 +++++ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 8170042d5fb3..ccc556eb4d2f 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -703,15 +703,6 @@ static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, = unsigned long cr3, return 0; } =20 -void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm) -{ - if (!svm->nested.vmcb02.ptr) - return; - - /* FIXME: merge g_pat from vmcb01 and vmcb12. */ - vmcb_set_gpat(svm->nested.vmcb02.ptr, svm->vmcb01.ptr->save.g_pat); -} - static bool nested_vmcb12_has_lbrv(struct kvm_vcpu *vcpu) { return guest_cpu_cap_has(vcpu, X86_FEATURE_LBRV) && diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index af808e83173e..34fd07d6ad4d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2776,6 +2776,47 @@ static bool sev_es_prevent_msr_access(struct kvm_vcp= u *vcpu, !msr_write_intercepted(vcpu, msr_info->index); } =20 +static bool svm_pat_accesses_gpat(struct kvm_vcpu *vcpu, bool from_host) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + + /* + * When nested NPT is enabled, L2 has a separate PAT from L1. Guest + * accesses to IA32_PAT while running L2 target L2's gPAT; + * host-initiated accesses always target L1's hPAT so that + * KVM_GET/SET_MSRS and KVM_GET/SET_NESTED_STATE are independent of + * each other and can be ordered arbitrarily during save and restore. + */ + WARN_ON_ONCE(from_host && vcpu->wants_to_run); + return !from_host && is_guest_mode(vcpu) && l2_has_separate_pat(svm); +} + +static u64 svm_get_pat(struct kvm_vcpu *vcpu, bool from_host) +{ + if (svm_pat_accesses_gpat(vcpu, from_host)) + return to_svm(vcpu)->vmcb->save.g_pat; + else + return vcpu->arch.pat; +} + +static void svm_set_pat(struct kvm_vcpu *vcpu, bool from_host, u64 data) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + + if (svm_pat_accesses_gpat(vcpu, from_host)) { + vmcb_set_gpat(svm->vmcb, data); + return; + } + + svm->vcpu.arch.pat =3D data; + + if (npt_enabled) { + vmcb_set_gpat(svm->vmcb01.ptr, data); + if (is_guest_mode(&svm->vcpu) && !l2_has_separate_pat(svm)) + vmcb_set_gpat(svm->vmcb, data); + } +} + static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) { struct vcpu_svm *svm =3D to_svm(vcpu); @@ -2892,6 +2933,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct = msr_data *msr_info) case MSR_AMD64_DE_CFG: msr_info->data =3D svm->msr_decfg; break; + case MSR_IA32_CR_PAT: + msr_info->data =3D svm_get_pat(vcpu, msr_info->host_initiated); + break; default: return kvm_get_msr_common(vcpu, msr_info); } @@ -2975,13 +3019,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struc= t msr_data *msr) =20 break; case MSR_IA32_CR_PAT: - ret =3D kvm_set_msr_common(vcpu, msr); - if (ret) - break; + if (!kvm_pat_valid(data)) + return 1; =20 - vmcb_set_gpat(svm->vmcb01.ptr, data); - if (is_guest_mode(vcpu)) - nested_vmcb02_compute_g_pat(svm); + svm_set_pat(vcpu, msr->host_initiated, data); break; case MSR_IA32_SPEC_CTRL: if (!msr->host_initiated && diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index b43e37b0448c..0b0279734486 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -868,7 +868,6 @@ void nested_copy_vmcb_control_to_cache(struct vcpu_svm = *svm, void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, struct vmcb_save_area *save); void nested_sync_control_from_vmcb02(struct vcpu_svm *svm); -void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm); void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vm= cb); =20 extern struct kvm_x86_nested_ops svm_nested_ops; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 0b5d48e75b65..cfb2517f692a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4025,6 +4025,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct = msr_data *msr_info) } break; case MSR_IA32_CR_PAT: + if (!(efer_reserved_bits & EFER_SVME)) + pr_warn_once("%s: MSR_IA32_CR_PAT should be handled by AMD vendor-speci= fic code\n", __func__); + if (!kvm_pat_valid(data)) return 1; =20 @@ -4436,6 +4439,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct = msr_data *msr_info) break; } case MSR_IA32_CR_PAT: + if (!(efer_reserved_bits & EFER_SVME)) + pr_warn_once("%s: MSR_IA32_CR_PAT should be handled by AMD vendor-speci= fic code\n", __func__); + msr_info->data =3D vcpu->arch.pat; break; case MSR_MTRRcap: --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F37F83A4528 for ; Fri, 27 Mar 2026 23:40:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654842; cv=none; b=cQe/TrDFuUjEQw0xxWx1d3YMb8VPVLdt/jjILWqXoRICa8KTTC77YlJXzXRvmWvQg+NzPgLPljwrfvba2KYXaHTJtAdF/+w1LpaocfjNg6+ryAMuv2eYxXwhjE2lI5F6Acijk5jq2vtuh5Asu0hW6rF+AGMPDcm6geVRpT5OVm8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654842; c=relaxed/simple; bh=JZ6+GCnob6DoER6tsgVX1H+2aBiZ/Ru6GqazViOYorE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tGzMU6oAK0+s4Wx+AuVpq/g0iCQ2lqcVuKrdKl2GuJc++ylt8SAFb0kjYE+xfvghMu7z+2xuR0GbC9K/58lXKR7lhT+JvbyGoVNTn1nQRxbsW1vu92nzvaxzC44Z92Y6kDLqqEjVnIFk15gVysaAlDe24Jccum4GGuhrs3V06Oc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=qpIhd2O2; arc=none smtp.client-ip=209.85.214.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qpIhd2O2" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2b0b0aae381so32994675ad.2 for ; Fri, 27 Mar 2026 16:40:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654839; x=1775259639; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/5S/h4cOpTQz2572kh2nJElR+n8F1U4MUPv9k7NHcKE=; b=qpIhd2O2L0zS4SJogUKVUPAZmgD8tzPVNiNC+3yeI9nHH9s6V7izgeSmbBI6rmI3b0 SiyN0AQbkxmiohOC0qJc6FwRiBnGa6AQ0BOAuKcZWK7H998U/Uw1F7htI7DqTvvC7wkv 73t04DeGuEpszXB9Ja7g5WGf/DSAPqhe0X3BevdtS+8uv03kWkzTg8P6sUZIGaVJEQvr cH/tRMPADU77jv9xtqJi9S49ekbzpfLQdFapSwob7A0OZihz6yTEPz7JOMs36hMJx9xh xbg2m+kK9G6ljCOx9+eA5X6tajDUEVmDbY8Re+0MhO6L61kmRWXzsUJLnRapIde4BZsO nWfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654839; x=1775259639; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/5S/h4cOpTQz2572kh2nJElR+n8F1U4MUPv9k7NHcKE=; b=ipsXNvSBX8nBOQtYx+agk15bMyOpkDeIjK5U3ocjzP0kMzI7teZLX5VI4jkFK1GbiO 86Nj2lOw2TdF2ozkkJq071w2IwC9d9FzWeG7K+oqfCy903Zg7kuRosQJN6NFueJI83J3 b8B13VfMB9iid2f6FBH9F4odmTubVy7rCqhhVkZb+RhcgreAwloLNIBnQL/fe64soJEV GLfFwloOiShwS1YZaB8ndaJVVk9cYwIpPqmv7xfSqmkunYBQD3O+j+2zazSCe7K8krqs eLLGndlX8B82rydioGxgr8L3yjqMveRc5OY2GirCHCQ1jd80fwB2/8XDFFcch4t6VtPV kDlw== X-Forwarded-Encrypted: i=1; AJvYcCVXHsIAmhetj6vIsf3wf5G0+ctEisN89Q/p5qOBE5vk29/QOFSWpM4yeudFLjsvlPF7w3Vz792KYtrECYE=@vger.kernel.org X-Gm-Message-State: AOJu0YzXv4kysV1ExjZ0s1y/knd8QizemE3aw690oEeAxD/rl0s2tg8d hUKPII54eC3Zg81qmfywyljFuO7vwDIAjT9AqjkptF2F9UnytrvuAKxLY4cRBUlW0xwlsel0wTb 1KkjbAoYZ2Cp3FA== X-Received: from plge14.prod.google.com ([2002:a17:902:cf4e:b0:2b0:5cd7:c89a]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2405:b0:2b0:ac1e:9737 with SMTP id d9443c01a7336-2b0cdc3dabcmr45964875ad.12.1774654838782; Fri, 27 Mar 2026 16:40:38 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:13 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-7-jmattson@google.com> Subject: [PATCH v7 6/9] KVM: x86: nSVM: Save gPAT to vmcb12.g_pat on VMEXIT From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" According to the APM volume 3 pseudo-code for "VMRUN," when nested paging is enabled in the vmcb, the guest PAT register (gPAT) is saved to the vmcb on emulated VMEXIT. When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled and the vCPU is in guest mode with nested NPT enabled, save the vmcb02 g_pat field to the vmcb12 g_pat field on emulated VMEXIT. Fixes: 15038e147247 ("KVM: SVM: obey guest PAT") Signed-off-by: Jim Mattson --- arch/x86/kvm/svm/nested.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index ccc556eb4d2f..add57f2a2d9f 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1248,6 +1248,9 @@ static int nested_svm_vmexit_update_vmcb12(struct kvm= _vcpu *vcpu) vmcb12->save.dr6 =3D svm->vcpu.arch.dr6; vmcb12->save.cpl =3D vmcb02->save.cpl; =20 + if (l2_has_separate_pat(svm)) + vmcb12->save.g_pat =3D vmcb02->save.g_pat; + if (guest_cpu_cap_has(vcpu, X86_FEATURE_SHSTK)) { vmcb12->save.s_cet =3D vmcb02->save.s_cet; vmcb12->save.isst_addr =3D vmcb02->save.isst_addr; --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73D013A545E for ; Fri, 27 Mar 2026 23:40:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654843; cv=none; b=GoyUzrWCVmTgRRS2BNmH/c4CbFd5BrEEQH3OxBwwr38x1/FemsCtUmS5OoYdvBkVdv17PcmPcTVy0yN8/pzLWt33U/1GQ/q3783ChEu2DOucUed6x65DKJYeHmFZlKs+MtP3sYgcZRPBSA/+fs2WhH6S1f3fxlmuFqaCVFXjvYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654843; c=relaxed/simple; bh=XLgtzGzP42ljoyiyAMkJfrzmvotKaPs/WCkAxsvyobc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TdP37IKzeJoNDjSyzoQ1tUeOf4jsRl+4WOBT4iK/vAgrivLvuIjQl0e16O+YM+ocTysvGLtMGh8aIqRxexsDfKGZrlcOz5AgC2+kk3nOReG8v38rXJr7+jm9c46LZqog4slUX0Ga4OLkFqOtYRuPmJi8V7w+j1GzxonNIrGBvvs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Bvnuhllz; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Bvnuhllz" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-35c0f03b2a1so7139405a91.2 for ; Fri, 27 Mar 2026 16:40:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654841; x=1775259641; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=fcHCPa7TDJvI9dVBUyhh6A4BV1v5Np3TWFrOmkOsocE=; b=Bvnuhllz2ehGQX+RdVTSoGv3BpfjRGsZ/xyAPrtu3k1GTlmhStDM6+WIHOJmHlaafu FJcohwPpcezZpzs/2alKmnJM0N06pQ2flMoUoGCBlJSy880uE7wh1sIC9sw0gXhGkm6V g4Q9wqdPJbfStpyKz5YbUuMl6Q+sSrD7jDkJZ3Eq86yZE7Xje6O0d1qsl5RJHVPfi+xn g80IwGVuCNe5g181E42ys+3J8NqgrZx+uvPcOkfruYEKyUjY2O7w2u6evvF7bie35gmY 4nzxdZYafHwaIzSrS9ivVSCZDY23LqsE9T+6EbGHZ34xXw4HIgnwkkU4TWh3lSlE3Q/u gBfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654841; x=1775259641; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=fcHCPa7TDJvI9dVBUyhh6A4BV1v5Np3TWFrOmkOsocE=; b=WhWdqE8lX7kDo4zOqu43RgfZiJcZP0lOjlBRuq8/MJ9yFvxgjEm+yZ/TSl4559uueb ch4qQ0eTKTgte+5Kz/QOtOK86+Cr/lwLXhrotueEVHuP/LLemfdn3Iot0jV7nYuV4sA/ KLX9MekaxOGCugkL+czwMLEsi/7Xsq2Utro/rcKBT6qw+Tg2OpVzdBRQjm9ofslbSs1d R4mxNpnPQIFBMLAddH8IwKZc/DyL73XsKc5+Ow+FLoir9jYXENchI4flBlSVSS02Cmeq 2jh6mC5VkFwk3mxt2QKxj+1bQI5xaO86MiN0bjkNqhAi3Po669Oh7NCU9m2OMUNuo4AX Xe7Q== X-Forwarded-Encrypted: i=1; AJvYcCU5tlVMo7/aR2PkZ2AVDxzcafMu9gWU5j606MN0gKpr8yalydawwVbZQ9Gwhii1qWOzLGHarNV3UWB5VGk=@vger.kernel.org X-Gm-Message-State: AOJu0Ywwki1DdQF1NGqReFqmktUpv5k0b9SkmqLJ1YRDzu5dIpLvqgtO zxm5ZeADb/+0FnsfMFwmZ5GTVeyqCzx5pzpPx6vMK++QtJHWCg3/iZHDuNVF2Dt9tmRkylm7AKN J4rKauaMAAXnAAA== X-Received: from pjub23.prod.google.com ([2002:a17:90a:cc17:b0:35d:94b3:bd6b]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:164a:b0:35b:8d89:7199 with SMTP id 98e67ed59e1d1-35c2ffb5174mr4008593a91.15.1774654840484; Fri, 27 Mar 2026 16:40:40 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:14 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-8-jmattson@google.com> Subject: [PATCH v7 7/9] KVM: Documentation: document KVM_{GET,SET}_NESTED_STATE for SVM From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Document the nested state constants and structures for SVM that were added by commit cc440cdad5b7 ("KVM: nSVM: implement KVM_GET_NESTED_STATE and KVM_SET_NESTED_STATE"). Fixes: cc440cdad5b7 ("KVM: nSVM: implement KVM_GET_NESTED_STATE and KVM_SET= _NESTED_STATE") Signed-off-by: Jim Mattson --- Documentation/virt/kvm/api.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 2d56f17e3760..0a2d873ca5a3 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -4942,10 +4942,13 @@ Errors: #define KVM_STATE_NESTED_FORMAT_SVM 1 =20 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000 + #define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000 =20 #define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_VMX_SMM_VMXON 0x00000002 =20 + #define KVM_STATE_NESTED_GIF_SET 0x00000100 + #define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001 =20 struct kvm_vmx_nested_state_hdr { @@ -4960,11 +4963,19 @@ Errors: __u64 preemption_timer_deadline; }; =20 + struct kvm_svm_nested_state_hdr { + __u64 vmcb_pa; + }; + struct kvm_vmx_nested_state_data { __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; }; =20 + struct kvm_svm_nested_state_data { + __u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE]; + }; + This ioctl copies the vcpu's nested virtualization state from the kernel to userspace. =20 --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pj1-f74.google.com (mail-pj1-f74.google.com [209.85.216.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CDEA93A4513 for ; Fri, 27 Mar 2026 23:40:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654844; cv=none; b=hciMVoLNUnXb02XUckzgyiej1YhNxMgo1/tjojeIDcATcDaG35+F280KKkSBFRTB5PxuE2B+a0myhBoO4AcK1EFFVWJH59m8FeNy9w7UiYnk6TCuzqvhoZJDvbPnsWmoBiKWZ6OrfVelZRNc8314iWhSsHAvXud2/neurOq7k3E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654844; c=relaxed/simple; bh=ZvxNNPnPmX7wYJVvYk5hMj+puG16Eo/l6nqfvIOJDnw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=O/nSJsbBYT5RcozqeS7STVHC+e5iSAAXRCMHvUL80u+MYq8dTVasCfOlMyXGB+WSS60f7sSBZ1u7lFDVOcK67jZpGhrZ66R4L2EbKU1kyrxOsIPnUDYDU/WALqnhY0L5yOOQEyCLC73CYujpwX11R7MAQMMDU/gHfj/zGPQRqt8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tmojgP9e; arc=none smtp.client-ip=209.85.216.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tmojgP9e" Received: by mail-pj1-f74.google.com with SMTP id 98e67ed59e1d1-35d9467e85aso158196a91.0 for ; Fri, 27 Mar 2026 16:40:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654842; x=1775259642; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=orVw3BFMtlEwOndHFsmUNVe5beJCJOsEnJ6vfIk60cg=; b=tmojgP9emI4mtKMvbsMYALuTLkpyDtr+5liMbtyFjUHERstqna5BwJQyH7RlEo/rg2 sY8OwbruhsXDA8aKgDicW/maKTxaFD+/CvoDkL/JNnXDWjDyt/Ij6Az7c9XHJ3/f7gv6 NhNRtlKtcs0WOhC8SkfI7FFw6FHmWzPK6zDXE1JKco+wlLBjRwwo3iOCH8Mztte/P3Xr aIraqNHgz/m+oV0IC1AJj679/clAN+wP2gAaxIU9dEGH4vTvvr06LS8cOgiON6D1bovU bz/T2T47SWqkKFNCSF7nEHFcRbNkl7NtVrPzLrKVqxZved/uQYbm21IYR5tfPeYZlt+W QnOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654842; x=1775259642; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=orVw3BFMtlEwOndHFsmUNVe5beJCJOsEnJ6vfIk60cg=; b=TN8ot/KxHp3tH22+TVK9sQ3etnHbz66oFm3vOhEJ+6lRAjhAj7O9yZI5FlcnzHaJoT LCqjlmDsVh3u0ITMnMOt5ZT26lrB+OHRIuAmBkTqkkx6Rb9JW4MAO1eBBj+klVA8zMYQ sa1w27lDYVoPAzYCf7nwCu1fAySu5k00BPnsh70g1NWFNGGE87K927ROTjbYeO+pe3Z9 tAlXLMNITaGr6JMy9PYBwtG//FXxvQ/cveFo4OXyQFoYsa2Xg+LetpQDdqRwWe7eIk8C gu145N6/V+7ZO0kvztC/ESvkcwosIPbheU1YghvMv8vPNlePGcFQMqyrzCBB2oTNeta4 LkWw== X-Forwarded-Encrypted: i=1; AJvYcCVRi/4T0mRtz4PL30kf1t3l52TCjZg+Ub33mOo5UlavQdqg7nvlL/AzsszEzmhbp6gF+KTTLWwQtADwXZs=@vger.kernel.org X-Gm-Message-State: AOJu0YzQmeF2qFEadZuVBpfnId7NuIg4QF13kUV+Yb3w4Msuztmc773/ nzW5VIDP9du0xltqG6dtlWCA4dKUwOjaO+oc5WXuqt4+w8svdgmjO/UL1XyEXKTOFnIk2b7HvUb yff823ZynpnoBzg== X-Received: from pjur6.prod.google.com ([2002:a17:90a:d406:b0:35c:251c:2305]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90a:d44d:b0:35b:e4f8:7cc5 with SMTP id 98e67ed59e1d1-35c300b9405mr3788148a91.25.1774654841889; Fri, 27 Mar 2026 16:40:41 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:15 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-9-jmattson@google.com> Subject: [PATCH v7 8/9] KVM: x86: nSVM: Save/restore gPAT with KVM_{GET,SET}_NESTED_STATE From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a 'gpat' field to kvm_svm_nested_state_hdr to carry L2's guest PAT value across save and restore. When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled and the vCPU is in guest mode with nested NPT enabled, save vmcb02's g_pat into the header on KVM_GET_NESTED_STATE, and restore it on KVM_SET_NESTED_STATE. Host-initiated accesses to IA32_PAT (via KVM_GET/SET_MSRS) always target L1's hPAT, so they cannot be used to save or restore gPAT. The separate header field ensures that KVM_GET/SET_MSRS and KVM_GET/SET_NESTED_STATE are independent and can be ordered arbitrarily during save and restore. Note that struct kvm_svm_nested_state_hdr is included in a union padded to 120 bytes, so there is room to add the gpat field without changing any offsets. Fixes: cc440cdad5b7 ("KVM: nSVM: implement KVM_GET_NESTED_STATE and KVM_SET= _NESTED_STATE") Signed-off-by: Jim Mattson --- Documentation/virt/kvm/api.rst | 1 + arch/x86/include/uapi/asm/kvm.h | 1 + arch/x86/kvm/svm/nested.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 0a2d873ca5a3..d6bbb7bad173 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -4965,6 +4965,7 @@ Errors: =20 struct kvm_svm_nested_state_hdr { __u64 vmcb_pa; + __u64 gpat; }; =20 struct kvm_vmx_nested_state_data { diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 3ada2fa9ca86..1585ec804066 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -533,6 +533,7 @@ struct kvm_svm_nested_state_data { =20 struct kvm_svm_nested_state_hdr { __u64 vmcb_pa; + __u64 gpat; }; =20 /* for KVM_CAP_NESTED_STATE */ diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index add57f2a2d9f..54399e642745 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1865,6 +1865,9 @@ static int svm_get_nested_state(struct kvm_vcpu *vcpu, /* First fill in the header and copy it out. */ if (is_guest_mode(vcpu)) { kvm_state.hdr.svm.vmcb_pa =3D svm->nested.vmcb12_gpa; + kvm_state.hdr.svm.gpat =3D 0; + if (l2_has_separate_pat(svm)) + kvm_state.hdr.svm.gpat =3D svm->vmcb->save.g_pat; kvm_state.size +=3D KVM_STATE_NESTED_SVM_VMCB_SIZE; kvm_state.flags |=3D KVM_STATE_NESTED_GUEST_MODE; =20 @@ -1918,6 +1921,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, struct vmcb_save_area_cached save_cached; struct vmcb_ctrl_area_cached ctl_cached; unsigned long cr0; + bool use_separate_l2_pat; int ret; =20 BUILD_BUG_ON(sizeof(struct vmcb_control_area) + sizeof(struct vmcb_save_a= rea) > @@ -1993,6 +1997,18 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, !nested_vmcb_check_save(vcpu, &save_cached, false)) goto out_free; =20 + /* + * Validate gPAT when the shared PAT quirk is disabled (i.e. L2 + * has its own gPAT). This is done separately from the + * vmcb_save_area_cached validation above, because gPAT is L2 + * state, but the vmcb_save_area_cached is populated with L1 state. + */ + use_separate_l2_pat =3D + (ctl_cached.misc_ctl & SVM_MISC_ENABLE_NP) && + !kvm_check_has_quirk(vcpu->kvm, + KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT); + if (use_separate_l2_pat && !kvm_pat_valid(kvm_state->hdr.svm.gpat)) + goto out_free; =20 /* * All checks done, we can enter guest mode. Userspace provides @@ -2017,6 +2033,10 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, nested_copy_vmcb_control_to_cache(svm, ctl); =20 svm_switch_vmcb(svm, &svm->nested.vmcb02); + + if (use_separate_l2_pat) + vmcb_set_gpat(svm->vmcb, kvm_state->hdr.svm.gpat); + nested_vmcb02_prepare_control(svm); =20 /* --=20 2.53.0.1018.g2bb0e51243-goog From nobody Thu Apr 2 00:12:46 2026 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 679C23A7F4F for ; Fri, 27 Mar 2026 23:40:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654846; cv=none; b=VM0hx3CfCRCXwipGcaxpmLby2MOLcXkKPml5H3/JXu9Yeh1fGhTZAAOpY3jXwIaJyAw02bx6QmbDdC/IDV6NSnhLoHjo5KbRm2u5QMANLBx/vRUnHnCFOsMNN4io5Rd2foAGaN8wX+VrSQxn2yu3SEcR9OAzO3mhokA6qXl3UY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774654846; c=relaxed/simple; bh=J6e0QheWsV205OBFE1w2/3od2KuiGQ8chN9jIhmli0w=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=lDIq9kZhBSvXEGbzSqmoOWPBfoAacX5AQO1uYYFJvpU5YBgSMgRoSBIVozE1yAU2jh0xdc7vqg1fpuZnTFcq8/YSK1TRlOsaC6FB0IcRis9P9Q2EgtawEsIGLY82WWwTklMxwV683gSJPBjBNYv8LKMrVcmORycIiMbmrChZfq0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=mNPutH1g; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mNPutH1g" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2b0b339b8dbso34560995ad.0 for ; Fri, 27 Mar 2026 16:40:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1774654844; x=1775259644; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=PZ/TyFghnFVNjOubdAxCNj3tm5pGnzmt2n9T/T2hdlg=; b=mNPutH1gy08p4LL2m3AjDen9ugQBFEVe9oxykdIqndcxd1csVsfHi2+yGqFI3Z/NqZ v+I4R6/HR3T/TuAErGeQZi2hisXIO9peEqNuIbTecQm8Js+bEYiER3C8rYPH1z7gqY1B 2f3M3KxmrgSlbja4XLFVm+Ib5p1PSaIj4uZeTHjfsKN0w0jn71CJM8wWseSPb6F4aDQ6 oDir4eyB3rclVSH3PhjgqtCamV513Lr/BJ0nU6O8fBSrbw9CC3dthZbetF1xTMl/kKGc HYnJ8acCC47Ih4hjL4PdACP1OGUUOyS8tI9FZbquy5IZJQRJ9CWE6Jh1++dPsCzCs2gP u98Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774654844; x=1775259644; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=PZ/TyFghnFVNjOubdAxCNj3tm5pGnzmt2n9T/T2hdlg=; b=FGMiVuRWxn4Way/5bFEaVlJWy17+CyU0/vl0h//3Hg2j/RXWq+r7BazMYnMFFbgjFy +ei0QCGPIUtTbWdPkDRxTrSWVAss7+ix7ARNXxtZSuDaLqK27aOVSsdrUC5fIxJgqFA7 K9k6/qit6mYFclMlKnfUlgZr2JutDhsP4nOGkvURUwO2O2hQUZYldNIBrMfnkp3c337p Ds/zjpWSPFvqpmFyxjw71wMzAHwX0+doPd00+hBNQunz3if4HMPiQF2m2C2O/MjpNipE HV+woJVnwvwOMe1Aj6W5T5JusEYdaIYBHIMCFddojaRKvV9ceozsgwS0VQ+HksHqwLXA kUeg== X-Forwarded-Encrypted: i=1; AJvYcCW29CqyoSH6wR+cENeSsxAuz2GYexRW68v8rY4vLnPXQ3UvTRB3jUTMvwqLSMZKtH3D10GYIf0EcHx2C7U=@vger.kernel.org X-Gm-Message-State: AOJu0YwXPw7vuCzFS8rkTCXH2AEgnFYTSejzWoOLwtFWXaEyq5+YDbEU gmSjoOI+zF5HrlwD1MiTed/kPttfRhje7RIJRHZu0brRuFaB1U3Z1F6eI9wOM5xCorr0zTK6Huy RbMVUPQAaiKRUNw== X-Received: from plkq5.prod.google.com ([2002:a17:902:edc5:b0:2b0:ac4d:59ec]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:c94c:b0:2b0:5075:96d1 with SMTP id d9443c01a7336-2b0cdcc7f67mr46645085ad.24.1774654843374; Fri, 27 Mar 2026 16:40:43 -0700 (PDT) Date: Fri, 27 Mar 2026 16:40:16 -0700 In-Reply-To: <20260327234023.2659476-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260327234023.2659476-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Message-ID: <20260327234023.2659476-10-jmattson@google.com> Subject: [PATCH v7 9/9] KVM: selftests: nSVM: Add svm_nested_pat test From: Jim Mattson To: Paolo Bonzini , Jonathan Corbet , Shuah Khan , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kvm@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Yosry Ahmed Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT is disabled, verify that KVM correctly virtualizes the host PAT MSR and the guest PAT register for nested SVM guests. With nested NPT disabled: * L1 and L2 share the same PAT * The vmcb12.g_pat is ignored With nested NPT enabled: * An invalid g_pat in vmcb12 causes VMEXIT_INVALID * RDMSR(IA32_PAT) from L2 returns the value of the guest PAT register * WRMSR(IA32_PAT) from L2 is reflected in vmcb12's g_pat on VMEXIT * RDMSR(IA32_PAT) from L1 returns the value of the host PAT MSR * Save/restore with the vCPU in guest mode preserves both hPAT and gPAT Signed-off-by: Jim Mattson --- tools/arch/x86/include/uapi/asm/kvm.h | 2 + tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/x86/svm_nested_pat_test.c | 304 ++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_nested_pat_test.c diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include= /uapi/asm/kvm.h index 7ceff6583652..be6f428a79aa 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -476,6 +476,7 @@ struct kvm_sync_regs { #define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7) #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8) #define KVM_X86_QUIRK_IGNORE_GUEST_PAT (1 << 9) +#define KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT (1 << 11) =20 #define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_SVM 1 @@ -530,6 +531,7 @@ struct kvm_svm_nested_state_data { =20 struct kvm_svm_nested_state_hdr { __u64 vmcb_pa; + __u64 gpat; }; =20 /* for KVM_CAP_NESTED_STATE */ diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 3d372d78a275..88871572ee9d 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -113,6 +113,7 @@ TEST_GEN_PROGS_x86 +=3D x86/svm_vmcall_test TEST_GEN_PROGS_x86 +=3D x86/svm_int_ctl_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_clear_efer_svme TEST_GEN_PROGS_x86 +=3D x86/svm_nested_invalid_vmcb12_gpa +TEST_GEN_PROGS_x86 +=3D x86/svm_nested_pat_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_shutdown_test TEST_GEN_PROGS_x86 +=3D x86/svm_nested_soft_inject_test TEST_GEN_PROGS_x86 +=3D x86/svm_lbr_nested_state diff --git a/tools/testing/selftests/kvm/x86/svm_nested_pat_test.c b/tools/= testing/selftests/kvm/x86/svm_nested_pat_test.c new file mode 100644 index 000000000000..704f31a079a9 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_nested_pat_test.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * KVM nested SVM PAT test + * + * Copyright (C) 2026, Google LLC. + * + * Test that KVM correctly virtualizes the PAT MSR and VMCB g_pat field + * for nested SVM guests: + * + * o With nested NPT disabled: + * - L1 and L2 share the same PAT + * - The vmcb12.g_pat is ignored + * o With nested NPT enabled: + * - Invalid g_pat in vmcb12 should cause VMEXIT_INVALID + * - L2 should see vmcb12.g_pat via RDMSR, not L1's PAT + * - L2's writes to PAT should be saved to vmcb12 on exit + * - L1's PAT should be restored after #VMEXIT from L2 + * - State save/restore should preserve both L1's and L2's PAT values + */ +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" +#include "svm_util.h" + +#define L2_GUEST_STACK_SIZE 256 + +#define PAT_DEFAULT 0x0007040600070406ULL +#define L1_PAT_VALUE 0x0007040600070404ULL /* Change PA0 to WT */ +#define L2_VMCB12_PAT 0x0606060606060606ULL /* All WB */ +#define L2_PAT_MODIFIED 0x0606060606060604ULL /* Change PA0 to WT */ +#define INVALID_PAT_VALUE 0x0808080808080808ULL /* 8 is reserved */ + +/* + * Shared state between L1 and L2 for verification. + */ +struct pat_test_data { + uint64_t l2_pat_read; + uint64_t l2_pat_after_write; + uint64_t l1_pat_after_vmexit; + uint64_t vmcb12_gpat_after_exit; + bool l2_done; +}; + +static struct pat_test_data *pat_data; + +static void l2_guest_code(void) +{ + pat_data->l2_pat_read =3D rdmsr(MSR_IA32_CR_PAT); + wrmsr(MSR_IA32_CR_PAT, L2_PAT_MODIFIED); + pat_data->l2_pat_after_write =3D rdmsr(MSR_IA32_CR_PAT); + pat_data->l2_done =3D true; + vmmcall(); +} + +static void l2_guest_code_saverestoretest(void) +{ + pat_data->l2_pat_read =3D rdmsr(MSR_IA32_CR_PAT); + + GUEST_SYNC(1); + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), pat_data->l2_pat_read); + + wrmsr(MSR_IA32_CR_PAT, L2_PAT_MODIFIED); + pat_data->l2_pat_after_write =3D rdmsr(MSR_IA32_CR_PAT); + + GUEST_SYNC(2); + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), L2_PAT_MODIFIED); + + pat_data->l2_done =3D true; + vmmcall(); +} + +static void l2_guest_code_multi_vmentry(void) +{ + pat_data->l2_pat_read =3D rdmsr(MSR_IA32_CR_PAT); + wrmsr(MSR_IA32_CR_PAT, L2_PAT_MODIFIED); + pat_data->l2_pat_after_write =3D rdmsr(MSR_IA32_CR_PAT); + vmmcall(); + + pat_data->l2_pat_read =3D rdmsr(MSR_IA32_CR_PAT); + pat_data->l2_done =3D true; + vmmcall(); +} + +static struct vmcb *l1_common_setup(struct svm_test_data *svm, + struct pat_test_data *data, + void *l2_guest_code, + void *l2_guest_stack) +{ + struct vmcb *vmcb =3D svm->vmcb; + + pat_data =3D data; + + wrmsr(MSR_IA32_CR_PAT, L1_PAT_VALUE); + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), L1_PAT_VALUE); + + generic_svm_setup(svm, l2_guest_code, l2_guest_stack); + + vmcb->save.g_pat =3D L2_VMCB12_PAT; + vmcb->control.intercept &=3D ~(1ULL << INTERCEPT_MSR_PROT); + + return vmcb; +} + +static void l1_assert_l2_state(struct pat_test_data *data, uint64_t expect= ed_pat_read) +{ + GUEST_ASSERT(data->l2_done); + GUEST_ASSERT_EQ(data->l2_pat_read, expected_pat_read); + GUEST_ASSERT_EQ(data->l2_pat_after_write, L2_PAT_MODIFIED); +} + +static void l1_svm_code_npt_disabled(struct svm_test_data *svm, + struct pat_test_data *data) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb; + + vmcb =3D l1_common_setup(svm, data, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + l1_assert_l2_state(data, L1_PAT_VALUE); + + data->l1_pat_after_vmexit =3D rdmsr(MSR_IA32_CR_PAT); + GUEST_ASSERT_EQ(data->l1_pat_after_vmexit, L2_PAT_MODIFIED); + + GUEST_DONE(); +} + +static void l1_svm_code_invalid_gpat(struct svm_test_data *svm, + struct pat_test_data *data) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb; + + vmcb =3D l1_common_setup(svm, data, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + vmcb->save.g_pat =3D INVALID_PAT_VALUE; + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_ERR); + GUEST_ASSERT(!data->l2_done); + + GUEST_DONE(); +} + +static void l1_svm_code_npt_enabled(struct svm_test_data *svm, + struct pat_test_data *data) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb; + + vmcb =3D l1_common_setup(svm, data, l2_guest_code, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + l1_assert_l2_state(data, L2_VMCB12_PAT); + + data->vmcb12_gpat_after_exit =3D vmcb->save.g_pat; + GUEST_ASSERT_EQ(data->vmcb12_gpat_after_exit, L2_PAT_MODIFIED); + + data->l1_pat_after_vmexit =3D rdmsr(MSR_IA32_CR_PAT); + GUEST_ASSERT_EQ(data->l1_pat_after_vmexit, L1_PAT_VALUE); + + GUEST_DONE(); +} + +static void l1_svm_code_saverestore(struct svm_test_data *svm, + struct pat_test_data *data) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb; + + vmcb =3D l1_common_setup(svm, data, l2_guest_code_saverestoretest, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + GUEST_ASSERT(data->l2_done); + + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), L1_PAT_VALUE); + GUEST_ASSERT_EQ(vmcb->save.g_pat, L2_PAT_MODIFIED); + + GUEST_DONE(); +} + +static void l1_svm_code_multi_vmentry(struct svm_test_data *svm, + struct pat_test_data *data) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + struct vmcb *vmcb; + + vmcb =3D l1_common_setup(svm, data, l2_guest_code_multi_vmentry, + &l2_guest_stack[L2_GUEST_STACK_SIZE]); + + run_guest(vmcb, svm->vmcb_gpa); + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + + GUEST_ASSERT_EQ(data->l2_pat_after_write, L2_PAT_MODIFIED); + GUEST_ASSERT_EQ(vmcb->save.g_pat, L2_PAT_MODIFIED); + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), L1_PAT_VALUE); + + vmcb->save.rip +=3D 3; /* vmmcall */ + run_guest(vmcb, svm->vmcb_gpa); + + GUEST_ASSERT_EQ(vmcb->control.exit_code, SVM_EXIT_VMMCALL); + GUEST_ASSERT(data->l2_done); + GUEST_ASSERT_EQ(data->l2_pat_read, L2_PAT_MODIFIED); + GUEST_ASSERT_EQ(rdmsr(MSR_IA32_CR_PAT), L1_PAT_VALUE); + + GUEST_DONE(); +} + +static void run_test(void *l1_code, const char *test_name, bool npt_enable= d, + bool do_save_restore) +{ + struct pat_test_data *data_hva; + vm_vaddr_t svm_gva, data_gva; + struct kvm_x86_state *state; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + + pr_info("Testing: %s\n", test_name); + + vm =3D vm_create_with_one_vcpu(&vcpu, l1_code); + vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, + KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT); + if (npt_enabled) + vm_enable_npt(vm); + + vcpu_alloc_svm(vm, &svm_gva); + + data_gva =3D vm_vaddr_alloc_page(vm); + data_hva =3D addr_gva2hva(vm, data_gva); + memset(data_hva, 0, sizeof(*data_hva)); + + if (npt_enabled) + tdp_identity_map_default_memslots(vm); + + vcpu_args_set(vcpu, 2, svm_gva, data_gva); + + for (;;) { + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_SYNC: + if (do_save_restore) { + pr_info(" Save/restore at sync point %ld\n", + uc.args[1]); + state =3D vcpu_save_state(vcpu); + kvm_vm_release(vm); + vcpu =3D vm_recreate_with_one_vcpu(vm); + vm_enable_cap(vm, KVM_CAP_DISABLE_QUIRKS2, + KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT); + vcpu_load_state(vcpu, state); + kvm_x86_state_cleanup(state); + } + break; + case UCALL_DONE: + pr_info(" PASSED\n"); + kvm_vm_free(vm); + return; + default: + TEST_FAIL("Unknown ucall %lu", uc.cmd); + } + } +} + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_NPT)); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); + TEST_REQUIRE(kvm_check_cap(KVM_CAP_DISABLE_QUIRKS2) & + KVM_X86_QUIRK_NESTED_SVM_SHARED_PAT); + + run_test(l1_svm_code_npt_disabled, "nested NPT disabled", false, false); + + run_test(l1_svm_code_invalid_gpat, "invalid g_pat", true, false); + + run_test(l1_svm_code_npt_enabled, "nested NPT enabled", true, false); + + run_test(l1_svm_code_saverestore, "save/restore", true, true); + + run_test(l1_svm_code_multi_vmentry, "multiple entries", true, false); + + return 0; +} --=20 2.53.0.1018.g2bb0e51243-goog