From nobody Thu Apr 2 19:00:06 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 BF7E6318BBB for ; Thu, 12 Feb 2026 15:59:14 +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=1770911957; cv=none; b=gMyUZNXOJqBM7eij0ckx5//2FztNhFi6IDS91LLV0IDJywZQHWA+UZrocn/c8I3xuDxVpUpIVjKa65FC/0zcWF0YFG4LO3djbFif6vo3Zo4L9lAussHTWFbVEP73klfVr5pXtB3gF93XDlk48Avm8JoxdIeNSt5IHzjI0rvko0E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911957; c=relaxed/simple; bh=mbEr3hzyszjJo46OU/qkjXN9L7/rAyLb4rEYR0jpuE8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=PDe3ZOZ3qavP3orsUcI9tsg2wMfHscHcuwWwqfHb5yutJlgrL7wkMfIlr4few7Bhmfku00kcuosl5e1NmMe1N4kHrneBCDxfMPNv3TBuchkPE7DBxrW/wkIBiauBqi19becXh7DT8NUGsYOmWlxoCAEgiBm0KLz7OusjnlbQ1BE= 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=gaLaqEal; 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="gaLaqEal" Received: by mail-pg1-f201.google.com with SMTP id 41be03b00d2f7-c6e18f1cb86so3864136a12.0 for ; Thu, 12 Feb 2026 07:59:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911954; x=1771516754; 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=J6K8kyx9CcUqpPEEuGOr7xIDm2PG4sM2n5DYfDKzhGk=; b=gaLaqEalXK25FPBVCJfjG1nVXZh0QROSDjhxJ/M22T8D4S9eQw2gyRcnv5dWJ7Z7KD ez/cl60A9fXcypTgecR2Znf+guBnb+Ar+l+rboZ8GYn+mmL6wpRHRyM7/osi4Y4yOblF 4QbVbbYW0VEIGs+hhV1rQXPjPD+8B+90FFAE8Zl+CTt7Xnurcq451tFoonrLXxW9nYf9 RKfNbedQMa9bgq7LSqko/v2wys0MyQylnP1wYYVp+AI19FSJYgBa13gpJr8PxjQ0/ZCj vqeHO784iZ0b+mVWbJ0Yu7hKmvMpGiJko2jPG8X4J8R/Tkd+8xcG8jocyyRL/Lq+DFIs ENKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911954; x=1771516754; 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=J6K8kyx9CcUqpPEEuGOr7xIDm2PG4sM2n5DYfDKzhGk=; b=ZO4g+1bt0CZnYxhO3sIgBFUNC++MgZXTL4gh3JEeEMHtjymtQCnhrbQRAjjPF7A1U0 y4i8f1YY7GhoV5fgIf5O6M7oclzCRqltJ8X6mKoj9jXiAuotSr4on4+b0DwwfC4cFJj8 DlY+nvicEnMErG/ID+6znQUrmZZ1U0BjEOkNCwjeWlt27ehsaHIXej7m632ieUImhIrK C1FxxuRBHaUs3qbzwfNZxoyYAycRAaVZlz08X1yftpZoy1TBwErdNE5zpfsWh8h6N2vF hWM8dW+jUKImwWcR+en+0mH44/wQ4soqFG1GZvCJVf8L0xNT+l7EJqpO97N5jpnrUB3u bbZQ== X-Forwarded-Encrypted: i=1; AJvYcCXiYdnbv3lvHbGRmc/aD9HAW8v2J0JfCP1rFrOJRjhpqKNJi/I885/V09c16GCxWR/YdfJTSGQ5T0ikzGo=@vger.kernel.org X-Gm-Message-State: AOJu0YzSO+8miekeKdSX4aplyMQ9gff8aK0GuZJkcveCDS5e3qPiSmwQ wDSW5iS0qA9oTzUqt3pbR0IvC1PNIFWF4zFfz8OZo90hLdNcYoV8R8xCyZKWAnvGgylgoq+AzpN 7SKO+C4UVVtZCNQ== X-Received: from pgc7.prod.google.com ([2002:a05:6a02:2f87:b0:c6e:21b7:bfd0]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:3d8d:b0:35f:cfb:1ee3 with SMTP id adf61e73a8af0-394484b2496mr3361847637.25.1770911954124; Thu, 12 Feb 2026 07:59:14 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:49 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-2-jmattson@google.com> Subject: [PATCH v4 1/8] KVM: x86: nSVM: Clear VMCB_NPT clean bit when updating hPAT from guest mode From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 | 9 +++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index d80b1bde6630..b72a1f3c4144 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -707,7 +707,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 void nested_vmcb02_prepare_save(struct vcpu_svm *svm) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 364915f42e13..529cbac57814 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2924,10 +2924,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 0bb93879abfe..9850ed01e16e 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -434,14 +434,15 @@ static inline void vmcb_mark_dirty(struct vmcb *vmcb,= int bit) vmcb->control.clean &=3D ~(1 << bit); } =20 -static inline bool vmcb_is_dirty(struct vmcb *vmcb, int bit) +static inline bool vmcb12_is_dirty(struct vmcb_ctrl_area_cached *control, = int bit) { - return !test_bit(bit, (unsigned long *)&vmcb->control.clean); + return !test_bit(bit, (unsigned long *)&control->clean); } =20 -static inline bool vmcb12_is_dirty(struct vmcb_ctrl_area_cached *control, = int bit) +static inline void vmcb_set_gpat(struct vmcb *vmcb, u64 data) { - return !test_bit(bit, (unsigned long *)&control->clean); + vmcb->save.g_pat =3D data; + vmcb_mark_dirty(vmcb, VMCB_NPT); } =20 static __always_inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) --=20 2.53.0.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 41F7A334374 for ; Thu, 12 Feb 2026 15:59:16 +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=1770911957; cv=none; b=sc3LksAA6IG+mPlZVydiiFAQFO5nLRr0w8Ex7a3Hs5zPBxJE6s28c0xlqVjKxboCgsTSUrhRsO2kRe4EMYvmOqLbMveQLlt7T1w5DIBWDMJ+vX6zoOJ/uv/wYCkBrIRdAWaaUCmEDdTHkC11I0r/xHMOk7np8VXlArYRPKu3M5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911957; c=relaxed/simple; bh=0pkG637PPrMnHAp36dNXBDpeM+jikBZBFutLvS3Rhns=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Rk5lyp5tHDNKDbegBIaFGtAyXIJjiFog1nUI7Zan+6slDrpkWXF7l86648Ul3S/1UhD7x/kSU5DIiEOqiVDMQe+rFM7LfhavxW/VnpbXoAM4VBCX0LGnCk4HFkjqOHPONyYAPmTOoQRS4sDPE+QDLdO7kSGFB1wfHvcrhd1Sq5I= 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=fl/VG49g; 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="fl/VG49g" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2a377e15716so175212515ad.3 for ; Thu, 12 Feb 2026 07:59:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911956; x=1771516756; 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=Zf8WWkIBl7yhW0Oc6MyZTF76PTkFmwYWfgFxHjbq7+4=; b=fl/VG49gVN/F8pdVQNA06z9p8j+5wbrNAWug/wXdtGfScySTyqVCcSrRO4fzTt70B1 n9fnId1lscpIn+0LlqtumdZ6gyslwpfX1x9wXMeeVpBe80yA90PEsMaRp1X5O3UdhPMj wiP4cK+3A0Q3M5seoGXc2BGCMbwEY+EUdRjYXflIAZdVayzrMAl1fLX9mdWd6d2wTDr/ 8QecPr14ztkTUu3REcITEQjP2EeOEB89XFPYRenDLgi70YM9tjFQtSBfdeHRtAuJ+nuH hXQNEvE7CZryMBTOz3/H6+Xcl6QsccW839SUEJ+OuQxhMpC9nS0xh+48yJHMB9zsERS4 x81Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911956; x=1771516756; 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=Zf8WWkIBl7yhW0Oc6MyZTF76PTkFmwYWfgFxHjbq7+4=; b=h6K+Fa4YF1PPG7HGuRi/GN2sL9mh7D281VeGT0z2Rn1Ve7OFwSSjGfnhUsnW5BB0H4 mjEEhGnhxiTRuw62AzSWDwftKsi8yYhul5g9gWPyHgqooaDwT4SO/QLGRj03EEKspIym 52xwyoeOC+l2U/fCpJvgdu95IjPmTiyKR6J4Yf5IE8NZSRnJ28n+wgRFaHuFndOfM4/x oSP44CJOMq3Lrvhx6GCyU9g70vYI3occxjvoyBKp4aFOWaPNyJDh7Luxku1klsYdfWLA LhZNomp6g281THyyxlCFFMQBPGxV2zt41MptVKCFYV2TNlX3YGx6y6+Sa1L5cyC0oFZ1 Q4jQ== X-Forwarded-Encrypted: i=1; AJvYcCVlARx9vEPQFv31DsqxLgENxTtTgGEmebxiSwCZCFvAehWnz366Nf2nmJi2jSbSO9VVX5aEzzRdo7U+ZlQ=@vger.kernel.org X-Gm-Message-State: AOJu0Ywf27LJQqwS/eJLFSIIWr6y9jPRBKCp2zd3zUdrH/c+rSZsAeGK YuEb8vqsnIwlG93afp+mtK91shH5K6V1Z95KwNE0AnOihY9SPm/pfxmwW4e5edz88b4XCNRZ8Zi jOUzUNiCUc7iL6w== X-Received: from plbkh12.prod.google.com ([2002:a17:903:64c:b0:2aa:d3c5:610d]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:98b:b0:295:62d:5004 with SMTP id d9443c01a7336-2ab399dd629mr35532595ad.26.1770911955652; Thu, 12 Feb 2026 07:59:15 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:50 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-3-jmattson@google.com> Subject: [PATCH v4 2/8] KVM: x86: nSVM: Cache and validate vmcb12 g_pat From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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" Cache g_pat from vmcb12 in vmcb_save_area_cached to avoid TOCTTOU issues, and add a validity check so that when nested paging is enabled for vmcb12, an invalid g_pat at emulated VMRUN causes an immediate VMEXIT with exit code VMEXIT_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 Reviewed-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 17 +++++++++++++---- arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index b72a1f3c4144..91b35adb83f8 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -426,7 +426,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; @@ -462,6 +463,9 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vcp= u, if (CC(!kvm_valid_efer(vcpu, save->efer))) return false; =20 + if (check_gpat && CC(!kvm_pat_valid(save->g_pat))) + return false; + return true; } =20 @@ -573,6 +577,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); } @@ -1036,7 +1041,8 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 v= mcb12_gpa, bool from_vmrun) =20 enter_guest_mode(vcpu); =20 - if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + if (!nested_vmcb_check_save(vcpu, &svm->nested.save, + nested_npt_enabled(svm)) || !nested_vmcb_check_controls(vcpu, &svm->nested.ctl, svm->vmcb01.ptr->save.cr0)) return -EINVAL; @@ -2006,13 +2012,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 9850ed01e16e..a49c48459e0b 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.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 93ABE318BA2 for ; Thu, 12 Feb 2026 15:59:17 +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=1770911958; cv=none; b=dcNyzuYO+d9mgrR2y1dVxadpSPm6/zwG9AwFtCNSiswQgebhvSHXdS2qvPKy2uNqzyF7ObQWMJFzR2mEEmD6C01sLtMlWuQxPfmM1cr7zr8OCNm5DQbAx3ryZQQ8fdldb9gIzFFaULVuA+swMFYBafRl+xw+3Ml3hP9F1jP52zQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911958; c=relaxed/simple; bh=s4DygJeXL0KLLS5zyD1EU8BmPQvpE/qt7AMgOQ0hWEQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LpBs45eR3NJDByka6i3/hLxG+ADec1y0LJ9yechH3Yk9HlgO4K7DINfMip8vmqTcINOcaEYME3BAjytbwtK814b2YgHqk9hq8RluC18HtUCrrP4H5raY00Vadg25kuFaSTQIt1ceStudLHgXxQrVsAzwebsOPGRm/Gg8k9e205I= 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=taYhWl0V; 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="taYhWl0V" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2aad5fc5b2fso35291065ad.1 for ; Thu, 12 Feb 2026 07:59:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911957; x=1771516757; 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=NXWGIZTswQvFKRAzrwUvmCg40y2DnJJnM3/XWRTJ8no=; b=taYhWl0VakB0+GWUKmGV5DQjC/DmSRoYMX3fcdswEOWsXo85OAOOeEuzw9x1nx7lhV z6QUtL2RtrTl5n1TbCjWO9juQn9hiLOLlUh7fE0eos6LYAxCkXy7dEBmjGG2o2kMADQi iTaJxSI3GxCSyvSt+gWRR79luHr1yPitmZwidq+2KmF97naRUEFMVJMYsmQHk09QL+kY dV2Eya9KLQiT7Et+pLS5R2L3tUZjdbJetRv3QKzhx+wwLXBRq2qPySCmFK+fNXv1jlzy yA1eYGC45t8YkIHRjN1DOklxmQ/zbQHCWLDoWBQ4v27dAdcr88uBXI57N5ls1c00xZjG IIEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911957; x=1771516757; 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=NXWGIZTswQvFKRAzrwUvmCg40y2DnJJnM3/XWRTJ8no=; b=WKvT1Jf40rjgMbCPGB/y+Wjj8cMFKF8II3VVZl9V0Nr4jSVRwXv5I5fsmF3PnJFeup cPDqrROZ968CVkBMkLtYqf4NpX+kJysGXNq3rHkHDqEMuCBHYhbgH4eASlzVC2G17ELM 948JSu0ocw/JS+M3A3MURcuy0j5OHhfxpopsgt6eghjWCqOKUySjUV03AT1wJNMDQk3W 7LJwqUQYn5RI7ifibnnq7q+HWr0M6sN+PEz20x+EZUujofc26o+QajClNb4/O/hGen8o nf0dpqUcKk2fNjFvxdFdXD6Zv0Daq4LItEh6u0dPTX0EJwn30c46NsMf9dfsPy2rhCqn WC4g== X-Forwarded-Encrypted: i=1; AJvYcCWvh2gMAy1mAcm56JFwAiL082LLbbLfLuYmHL1EU+asyuSv+8Ozh8TkhP1O/J31z91DpcKjdE5HsnXvaOU=@vger.kernel.org X-Gm-Message-State: AOJu0Yxxv1ukRP7vSl2OTxEp6BipuBImmaVGNWfbPaTojRHMYxZZjlJ2 /OW6zoWOooQ5vDW8/CJlqXgQ4vb1VGV1tgLIvk2Pg3s2uMwBjoDR4vDtKIPdc/PqvqrNuNH0xp4 lIJh9JhSuVXungg== X-Received: from plbje12.prod.google.com ([2002:a17:903:264c:b0:2ab:f1d:4446]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:d2d1:b0:2a9:602c:159 with SMTP id d9443c01a7336-2ab3b1a00c3mr29570985ad.19.1770911956923; Thu, 12 Feb 2026 07:59:16 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:51 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-4-jmattson@google.com> Subject: [PATCH v4 3/8] KVM: x86: nSVM: Set vmcb02.g_pat correctly for nested NPT From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 nested NPT is enabled in vmcb12, copy the (cached and validated) vmcb12 g_pat field to the guest PAT register. Under KVM, the guest PAT register lives in svm->nested.save.g_pat. 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 Reviewed-by: Yosry Ahmed --- 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 91b35adb83f8..dc8275837120 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -724,9 +724,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; @@ -757,6 +754,13 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm= *svm) vmcb_mark_dirty(vmcb02, VMCB_CET); } =20 + if (nested_npt_enabled(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.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 2026 Received: from mail-pg1-f202.google.com (mail-pg1-f202.google.com [209.85.215.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 72A1435CBD8 for ; Thu, 12 Feb 2026 15:59:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911960; cv=none; b=uWty+AqbNqEll4GBwEJARmJdYS3J0bCzFN4GHVfwfzLeWv3irIsnI3wV5r/EN2mvXdzHnmLfpdA99S3gRsFzErEdPxDLvUogJX27gFOa73zuoOgElWSUSC92Deu59A7txaaDZ1u+NV1UwOZdP8NPENFwM1okALZgXPrjWUExPCY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911960; c=relaxed/simple; bh=4LHE5WLYNB6gyN85lIMig0mQ2kzlCE0cLPzqj3TDstc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YMJCwwOH5tw4C2fgqOCcUPMfVpkuXUWZy1irDrTX3ctp6n3BkXVUw+erHPM39mylzE6bHOc0zLqjSZbS+duN0R3CFIuyQj1LShLyUrjpvGs0q2QnfgBDnMhxlRa5r+qZwug6ZH6tSEdMbxy/abYjSjPWtC+sx7FLHXn6CoBj2PA= 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=fcdheKUJ; arc=none smtp.client-ip=209.85.215.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="fcdheKUJ" Received: by mail-pg1-f202.google.com with SMTP id 41be03b00d2f7-b630b4d8d52so4493234a12.3 for ; Thu, 12 Feb 2026 07:59:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911959; x=1771516759; 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=xlVjUD6X+DWJ5GX5AGAVyWl05TJtGeS8hkpBTgsS/Ys=; b=fcdheKUJhL9Lap3mGGAKBOr+zq2hA39ls5F0YVRWa0MXSrdnvEI15eiQCi1r2Rnltt X3XpzCdhNIxyYR4WpECd+AlYjqInVexoaJcH8KqFGWC+pAC4KMNdbCySB97iNwuCnIjf 6a6mMBzdKBsJyscUWEhaJGrOT5EZsqkxuyVTGKsqvxeVgJ+tYb7AsCYymNSxKPMgNLrO 2nzod//MxHomQnBTxphDr9v3uY5MA7tWVluTCuQGCh22k9/YuDwnVFceN4XRuWdJQJV3 EeNAX0jcQaUYHNM6zxYe8E3nc5ie9Q6AogrgF4KDzOo6G4BlI2TPH6A02N1ylzm4Wfdl 1gTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911959; x=1771516759; 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=xlVjUD6X+DWJ5GX5AGAVyWl05TJtGeS8hkpBTgsS/Ys=; b=HwoHJOIw9zgWsJ2AJe7BH20ukJ6auKk12oW3P61tOJgaFXPBBaTSGx19mCg/5UQcph Ub30AUYF+JaqPBDchl/+xZwjfEOrOA6+8mWCx8PAo5oQT2B5sDdhvGnAEAuwPwkAzGP6 8CUwjf3w0mY4HVtIj+4XLUelmmWV7qhLS3zRh96ej4BsHgKYYIXP3HMKmGsbpfPhueLD Z45ZpDMrn+MKaaCtH5DbXzV3FfE4824TOvuqzqjjs+s0n/rW0KqAF4aqvcRHaOitWxba oWI3HpDOp+AZrTu8m6BhhBgn47LCtfVAyZ1Q1+hy4wIBapd0VY2Q1OOOs0a87UBTGAKJ lRbA== X-Forwarded-Encrypted: i=1; AJvYcCWgY8hgjRxTlJWUblwqzyGemzjvCEhYCoM4kc7CEjpw/9cWZ2EbVfi+dYvoGzgOOpk+/OUYKSFuvHlxbO0=@vger.kernel.org X-Gm-Message-State: AOJu0YxXC4srTM9U+NgXje6q+KfvNKCy7bqj2b5/Du806mEEQeC7E+UC Pq+BglCojRkJJoIPdKcTcG/hrx+hvv1jjH/1LNafb/LTySUG0B5scHlax+10vmJ1i296/iENI5i w8PK17y/RehCg2Q== X-Received: from pgab127.prod.google.com ([2002:a63:3485:0:b0:c6e:2e0d:72cc]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a20:7284:b0:392:e5eb:f0f with SMTP id adf61e73a8af0-3944897a82fmr3339452637.68.1770911958649; Thu, 12 Feb 2026 07:59:18 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:52 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-5-jmattson@google.com> Subject: [PATCH v4 4/8] KVM: x86: nSVM: Redirect IA32_PAT accesses to either hPAT or gPAT From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 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 svm->nested.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. Add WARN_ON_ONCE to both svm_get_msr() and svm_set_msr() to flag any host-initiated accesses originating from KVM itself rather than userspace. Fixes: 15038e147247 ("KVM: SVM: obey guest PAT") Signed-off-by: Jim Mattson --- arch/x86/kvm/svm/nested.c | 9 --------- arch/x86/kvm/svm/svm.c | 37 ++++++++++++++++++++++++++++++------- arch/x86/kvm/svm/svm.h | 17 ++++++++++++++++- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index dc8275837120..69b577a4915c 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -706,15 +706,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 void nested_vmcb02_prepare_save(struct vcpu_svm *svm) { struct vmcb_ctrl_area_cached *control =3D &svm->nested.ctl; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 529cbac57814..205bf07896ad 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2837,6 +2837,21 @@ 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: + /* + * 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 for backward and forward KVM_GET_MSRS compatibility + * with older kernels. + */ + WARN_ON_ONCE(msr_info->host_initiated && vcpu->wants_to_run); + if (!msr_info->host_initiated && is_guest_mode(vcpu) && + nested_npt_enabled(svm)) + msr_info->data =3D svm->nested.save.g_pat; + else + msr_info->data =3D vcpu->arch.pat; + break; default: return kvm_get_msr_common(vcpu, msr_info); } @@ -2920,13 +2935,21 @@ 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; - - vmcb_set_gpat(svm->vmcb01.ptr, data); - if (is_guest_mode(vcpu)) - nested_vmcb02_compute_g_pat(svm); + if (!kvm_pat_valid(data)) + return 1; + /* + * 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 for backward and forward KVM_SET_MSRS compatibility + * with older kernels. + */ + WARN_ON_ONCE(msr->host_initiated && vcpu->wants_to_run); + if (!msr->host_initiated && is_guest_mode(vcpu) && + nested_npt_enabled(svm)) + svm_set_gpat(svm, data); + else + svm_set_hpat(svm, 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 a49c48459e0b..88549705133f 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -607,6 +607,22 @@ static inline bool nested_npt_enabled(struct vcpu_svm = *svm) return svm->nested.ctl.misc_ctl & SVM_MISC_ENABLE_NP; } =20 +static inline void svm_set_gpat(struct vcpu_svm *svm, u64 data) +{ + svm->nested.save.g_pat =3D data; + vmcb_set_gpat(svm->nested.vmcb02.ptr, data); +} + +static inline void svm_set_hpat(struct vcpu_svm *svm, u64 data) +{ + svm->vcpu.arch.pat =3D data; + if (npt_enabled) { + vmcb_set_gpat(svm->vmcb01.ptr, data); + if (is_guest_mode(&svm->vcpu) && !nested_npt_enabled(svm)) + vmcb_set_gpat(svm->nested.vmcb02.ptr, data); + } +} + static inline bool nested_vnmi_enabled(struct vcpu_svm *svm) { return guest_cpu_cap_has(&svm->vcpu, X86_FEATURE_VNMI) && @@ -840,7 +856,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; --=20 2.53.0.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 ECE8F352FA4 for ; Thu, 12 Feb 2026 15:59:20 +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=1770911962; cv=none; b=F923aX+7eCw91ZLL6aUrLoAjqwnAFhj5bJejJoFdbDW4Vx7cbNWXGF9m8dawUjJrM7xUQu+pZukfTLnefxHGsjtw0O6tun5tOvN+6D+p54urkOaY8c36GZfWtYm3aH+OWNY2OXvSt7c/l+1B8yYK4Cd0InG1GuBxrJaebPQwSOA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911962; c=relaxed/simple; bh=++djy9qE0Jp6xQfXeogvywVaePhWe023CD1zQ9+shs0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=eImhJm1tvHCHpomlzHPVhjHcj4jSzAOLsDGstD6X3KiCHt3/E2diZlBvJeAQchQxwqxE78SPuq8l2DbEcmPk2o+Dy5jwEtdv7A6SZ5+DbSIxyzvivPvYlUk/6Locb5yDlHZP3bHbGiJlPnjeYPpd1ddgPFLvIGE7LG0pOl+UhQ0= 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=AVdHkij9; 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="AVdHkij9" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2a7d7b87977so38053035ad.0 for ; Thu, 12 Feb 2026 07:59:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911960; x=1771516760; 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=2K3QbxzwUqR/5mBjTZowvxoPbPjbPH0qQe3lheBbwSQ=; b=AVdHkij9pCKnFB9bD7XnQI0kNTUFT0ksN5cPC3jqige7G8d9DOKdY8eIu7g5NoWjKI RoOPqXE7B+cRKp02J2cmlROmYCn7/zK/P4sd61PclhPxOm4ED6Zcy3pOi5p8b6LlY7V2 gYiwUIqd4//gHihuovbu8lT8PGV3xotfIv5Cql9BndZ7aBS8RzeuGVLsR2m467ZaiC6n 9qLdHuDmzQL72Pg+/y0ef6bMS7QvDIDteIxhk5d/sojvJuHqy31EqG8Ha58YggK+ek4b +mB+ZV3R8zHb05QZeHfummTdDkCXsbhwKEokW23z1tKdEXy5pmqWZ8Veaf5BV6JYbIVb Rdmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911960; x=1771516760; 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=2K3QbxzwUqR/5mBjTZowvxoPbPjbPH0qQe3lheBbwSQ=; b=AFN1KwJINInyZJ0QzB6K/NX1AFKcbW6CoccIPN7wpbFTK2zEw/Nd4EaC6Qz6aZFxTd GM8GZ+mDiNs9YGxA4d2BmgwOx8bAo4kFdqyC5FFOFuLbzbwdbp7cx+fffEO3XEJ7ElSU iXYksEuxPYVaJVEjUEaVg07wO6270xdGcUyKq3NHYZPZPECrI5IKgKWstE2Omdv6C3Tq ip7JxDe0mfYh7XrN+7Ao/g3Xq+wgz6f8VsssBVTlL0WEnGxswaXtYcOBVfmL+PEXYHy2 p3wcQcDGdngmPYfXI6oYN5dvVLb/o1NtJkgDvgr3s0S6GeX8D2/cfhiqmoNd4MP2He3N +JrQ== X-Forwarded-Encrypted: i=1; AJvYcCVZ/kxiJiKhAlkEpUG4OyC8aabsE+luereG/8fI/yTh5avkil6tPp1k5NobzcsLyDm54FKaqmuzutOzrMs=@vger.kernel.org X-Gm-Message-State: AOJu0YyolORGcr0Rs3saT3o1wyLZJj0A3lLWJGT15T3vlfaY5kNG3Fki KcbbwEt/xRYT2ydltcUzzuIz9xheSjon+9qKLQb486W2y+gdyrM0QyYiznLHoeIb59fqKmorppU FUdLKk5n3+HZZzQ== X-Received: from plbla13.prod.google.com ([2002:a17:902:fa0d:b0:2a9:622c:47d6]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:9cf:b0:2a7:d5c0:c659 with SMTP id d9443c01a7336-2ab3b1581a3mr26923795ad.5.1770911960328; Thu, 12 Feb 2026 07:59:20 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:53 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-6-jmattson@google.com> Subject: [PATCH v4 5/8] KVM: x86: nSVM: Save gPAT to vmcb12.g_pat on VMEXIT From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 nested NPT is 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 Reviewed-by: Yosry Ahmed --- 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 69b577a4915c..26f758e294ab 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1312,6 +1312,9 @@ void nested_svm_vmexit(struct vcpu_svm *svm) vmcb12->save.dr6 =3D svm->vcpu.arch.dr6; vmcb12->save.cpl =3D vmcb02->save.cpl; =20 + if (nested_npt_enabled(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.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 7070235D608 for ; Thu, 12 Feb 2026 15:59:22 +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=1770911965; cv=none; b=dG/7NXPLYfjy861uULIWEakUJLswWLYDdZvO1Pr8dQyf792Z9MuPE91CbRT9ENsX0xpkrtGwBKzrDLV8XT8ovVxzqMqIrZs77jSLBbkaKL9NrEt0hhlsXFabFAsDFCTigoZemvcDrJLgnotZ6MpsTzUgJ5gTZW+aDGmJ3Kzjwzc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911965; c=relaxed/simple; bh=IPS4V3Xedp44qKMO94o2K4sQEaOjEKl0DVkxqcvXKYk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=I/ARsOu5+dG2yjh0lMu5jeyKuHtuyUGDkUJCimebzDip7OL6aB7WRdzUF65rcO6fAt7FGffudHzbKRRBIelhSd9jfhtm15WodYf88SrrFPSZ6s2CW1beibQMKG2kYRXRh1/+5UimvFvrXCJVDz0xd/KaDOv3F1ysjUVGLmxBEWk= 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=Rk7lUsRQ; 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="Rk7lUsRQ" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2aaeafeadbcso52000755ad.1 for ; Thu, 12 Feb 2026 07:59:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911962; x=1771516762; 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=VRlL7csLSSKDZLO+EBN/PvZlh3NDnCHP9xjp5VbQz/o=; b=Rk7lUsRQlQl//uUdrDEVniH1nIzVU71SbuF+C8bAsWBkXeZFHVAX7JExUi0Go0cngD STiD1RqFWvHhB3uW6DMPeLEa3GFWcpRjtGJ2HlG4IiRuC1/GRZBsV4HrloJEyjGQ/L7/ lE59ROP/3XTiptLaYbHd170cag7CJF1BEcZLJ5Rf35xaH5Fh1zj1D7SjtN2wlqfvucbN EWoYX5SCveD2+y8GVjxPpCIhE05BmJ/e5x97b9TlH5kduPequDPaQ7DQdQevqcKNmVW2 Qgh0qMq8DKDnM6SV3m4R90dh5Muo1E2pAwPxKASbZQ7F3OXnJqsHohFarpYR+B0DYp/9 Gw3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911962; x=1771516762; 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=VRlL7csLSSKDZLO+EBN/PvZlh3NDnCHP9xjp5VbQz/o=; b=uqJAABVNeT2rqDi6YK5s7iV+ncIA3CXF5G4fkcBMUvE7KyfB1JoP9t6nXwbF7zDptm 5YC4QLuazoS45lVOc76fyyysBqWPkuitLdxT0RVn/EyHwvyywVhkJ6BJUCL11+Dx2ya4 U4jFfb+jB/QXZEY9a2mBNJBB6vqDgrjER3IopDvqngnNdVTWm93Fcel/RAT3jDUHxvlf rh1rF+9XMhMs7cm9mbluLjb1A4lR//aNbd2feJAXeZ+HWC/GJMIGlwln6QnLG2CDihxn HZ8L2dN2Vk2/FujMNEb50eo2HOKESNr2XqiDkb9UxpS6MYbZhgA2wJdryTpzBa8QEu1g WnOA== X-Forwarded-Encrypted: i=1; AJvYcCX0Xu8SZA36sjD7M+jkCO4FpVZNpFaKES5NNp++DkbGtugaOT4Flr+xVma5/o4S1Pyu7dAYquKpHD55FeI=@vger.kernel.org X-Gm-Message-State: AOJu0YzL4vgU8B2T5cTvNBCsfGt+EeYmcD7i7XCNeOfY+d+WVMs2trTp r91sLjMfGX80R44wFJVBpcEUdqKs2FtAkjrSNS/pp9M3g2mlEB1NqIziGWcnvU7Ea/1wDTJ6HqQ 3AmY7H0Vt0elCEQ== X-Received: from pjbgv21.prod.google.com ([2002:a17:90b:11d5:b0:354:c1db:b113]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2e0d:b0:34a:b8e0:dd64 with SMTP id 98e67ed59e1d1-3568f2be796mr3007216a91.1.1770911961810; Thu, 12 Feb 2026 07:59:21 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:54 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-7-jmattson@google.com> Subject: [PATCH v4 6/8] KVM: x86: nSVM: Save/restore gPAT with KVM_{GET,SET}_NESTED_STATE From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 'flags' field to the SVM nested state header, and use bit 0 of the flags to indicate that gPAT is stored in the nested state. If in guest mode with NPT enabled, store the current vmcb->save.g_pat value into the header of the nested state, and set the flag. Note that struct kvm_svm_nested_state_hdr is included in a union padded to 120 bytes, so there is room to add the flags field and 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 Reviewed-by: Yosry Ahmed --- arch/x86/include/uapi/asm/kvm.h | 5 +++++ arch/x86/kvm/svm/nested.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 846a63215ce1..664d04d1db3f 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -495,6 +495,8 @@ struct kvm_sync_regs { =20 #define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001 =20 +#define KVM_STATE_SVM_VALID_GPAT 0x00000001 + /* vendor-independent attributes for system fd (group 0) */ #define KVM_X86_GRP_SYSTEM 0 # define KVM_X86_XCOMP_GUEST_SUPP 0 @@ -531,6 +533,9 @@ struct kvm_svm_nested_state_data { =20 struct kvm_svm_nested_state_hdr { __u64 vmcb_pa; + __u32 flags; + __u32 reserved; + __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 26f758e294ab..f73f3e586012 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1893,6 +1893,10 @@ static int svm_get_nested_state(struct kvm_vcpu *vcp= u, /* 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; + if (nested_npt_enabled(svm)) { + kvm_state.hdr.svm.flags |=3D KVM_STATE_SVM_VALID_GPAT; + kvm_state.hdr.svm.gpat =3D svm->nested.save.g_pat; + } kvm_state.size +=3D KVM_STATE_NESTED_SVM_VMCB_SIZE; kvm_state.flags |=3D KVM_STATE_NESTED_GUEST_MODE; =20 @@ -2022,6 +2026,14 @@ 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, if provided. 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. + */ + if ((kvm_state->hdr.svm.flags & KVM_STATE_SVM_VALID_GPAT) && + !kvm_pat_valid(kvm_state->hdr.svm.gpat)) + goto out_free; =20 /* * All checks done, we can enter guest mode. Userspace provides @@ -2061,6 +2073,10 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, if (ret) goto out_free; =20 + if (nested_npt_enabled(svm) && + (kvm_state->hdr.svm.flags & KVM_STATE_SVM_VALID_GPAT)) + svm_set_gpat(svm, kvm_state->hdr.svm.gpat); + svm_switch_vmcb(svm, &svm->nested.vmcb02); nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); =20 --=20 2.53.0.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 C024A35DD0B for ; Thu, 12 Feb 2026 15:59:23 +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=1770911965; cv=none; b=TJcetjsV17H6gqH8yRg9MRDMZ/CmSTNzKZjqn0XgcSGpTdBVChun42859g1ZHk7NORib9WsyskNpTjZUgQpsEefQChGPBCtPWIMvMXU+oiHiW3AQ3o95FzTwilI8kHsskvt2AjQSQRoYOxvKN58CRftCTGmwsOnl2T78U0jcqv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911965; c=relaxed/simple; bh=k4PiYHsSuuJFMDCPsbANk87y2wEFqDT2QuLQAFxQBqU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ldhGEFvGLa/VGsq5mmBZ/HHkL7ADJH5JAZ5v2T1KCa/SD1BgfAnbETEbDeAZprtBD3nTFvhGsJP4iJ9ebcQj+t32n/+uWUWqQj0lDWT7RIjYDxGbNgSCOU9ZbVWSHEPLSFtFZS4UxH1kIgH3VGh67w1q5z9GroVL9OGV+3RroH4= 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=zif59+xB; 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="zif59+xB" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-2a76f2d7744so34990765ad.3 for ; Thu, 12 Feb 2026 07:59:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911963; x=1771516763; 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=PVdp9sqT0g4R8OZdrPzG/zG6Qh9LMmNSXbaooXKmXCg=; b=zif59+xBcl7e0OBAqId74xmvjRidQUf3nY5NJYVNYZjDJqvDBHJ9G5EVcy/sUbh/Pr z39dkDkgf1yrBENuQtrEJzEA11tM27F0dHSA1yan4nXMhlF+RZEAc4GgUnS2PbHg3xLp IkLNIs9P50QgP0PzAbr2yF5R48H3ebaRb1/NCbi9O/zJODISKQF77ZAajDoXDyb/WqyM lKbrbMqPAHLZVOnzatRe5wchYaHTISKVFIlKxIAraaja6xUD0Lxz+2OGV1zFFd0V6v4L MTdFicP8Mc/aKk8IfIvEIkLL1sSM89FLSfuAyykQWaJTcigC2hWotzHEgy3oOhQO8uud PtwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911963; x=1771516763; 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=PVdp9sqT0g4R8OZdrPzG/zG6Qh9LMmNSXbaooXKmXCg=; b=pl/IQJCn23MDgk9fwznj6SmTy8brnrlt30kUe2RlPWQ4UqFOowmwu99DvuFXoYWZ4P qB8uks08nVGa14lKIQnhHUaP/rEZwMdRYZITkbvz++Hda3omiTk2mz5IFrgljALZ+JBe 1B4dXSZBWUwFw/223+g4qmNHPbRY9fGuihOgus7xT7bvsz6fuCvuSw4Uaoiexwqri9Z9 ci6veELFSUn5/Fstq15cxc0l9nANzf0NDatIEJIcAml/lutHRhDsHPb6P7+/MGVV6oxR OU0UGseEdcLgicCAYM3RH7qw8lpbMQQOb2lrKroyF0ZAYFOc7VDLZicK/qnsqHNUxFEu C/4g== X-Forwarded-Encrypted: i=1; AJvYcCXpqUTlFvG7HAlubBuep7WeSDd8UFJvuu9i8oVzgcFMn0+RPClRWGNbnPO+syaXLYR1HyyvsdpTZRkbSNM=@vger.kernel.org X-Gm-Message-State: AOJu0YzEajXic6knnBiSBuZLwBRv0OoMTb178U0KUxYgx64Xlo5EcH1u iGI77qUT1ow4QNVTxnOdbMpfCmVFY9BAyfPDTsWK0wXYcNFyBaIjqnpewuLiJgy+qNEOzTmW8M0 ay9S9rSa8zcdU9g== X-Received: from plbkk4.prod.google.com ([2002:a17:903:704:b0:2a9:6206:d68]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:ec83:b0:2a7:3dbe:353d with SMTP id d9443c01a7336-2ab3b28af34mr31946425ad.53.1770911963215; Thu, 12 Feb 2026 07:59:23 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:55 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-8-jmattson@google.com> Subject: [PATCH v4 7/8] KVM: x86: nSVM: Handle restore of legacy nested state From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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 nested NPT is enabled and KVM_SET_NESTED_STATE is used to restore an old checkpoint (without a valid gPAT), the current IA32_PAT value must be used as L2's gPAT. Unfortunately, checkpoint restore is non-atomic, and the order in which state components are restored is not specified. Hence, the current IA32_PAT value may be restored by KVM_SET_MSRS after KVM_SET_NESTED_STATE. To further complicate matters, there may be a KVM_GET_NESTED_STATE before the next KVM_RUN. Introduce a new boolean, svm->nested.legacy_gpat_semantics. When set, hPAT updates are also applied to gPAT, preserving the old behavior (i.e. L2 shares L1's PAT). Set this boolean when restoring legacy state (i.e. nested NPT is enabled, but no GPAT is provided) in KVM_SET_NESTED_STATE. Clear this boolean in svm_vcpu_pre_run(), to ensure that hPAT and gPAT are decoupled before the vCPU resumes execution. Signed-off-by: Jim Mattson Reviewed-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 11 ++++++++--- arch/x86/kvm/svm/svm.c | 2 ++ arch/x86/kvm/svm/svm.h | 11 +++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f73f3e586012..d854d29b0bd8 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -2073,9 +2073,14 @@ static int svm_set_nested_state(struct kvm_vcpu *vcp= u, if (ret) goto out_free; =20 - if (nested_npt_enabled(svm) && - (kvm_state->hdr.svm.flags & KVM_STATE_SVM_VALID_GPAT)) - svm_set_gpat(svm, kvm_state->hdr.svm.gpat); + if (nested_npt_enabled(svm)) { + if (kvm_state->hdr.svm.flags & KVM_STATE_SVM_VALID_GPAT) { + svm_set_gpat(svm, kvm_state->hdr.svm.gpat); + } else { + svm_set_gpat(svm, vcpu->arch.pat); + svm->nested.legacy_gpat_semantics =3D true; + } + } =20 svm_switch_vmcb(svm, &svm->nested.vmcb02); nested_vmcb02_prepare_control(svm, svm->vmcb->save.rip, svm->vmcb->save.c= s.base); diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 205bf07896ad..d951d25f1f91 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4245,6 +4245,8 @@ static int svm_vcpu_pre_run(struct kvm_vcpu *vcpu) if (to_kvm_sev_info(vcpu->kvm)->need_init) return -EINVAL; =20 + to_svm(vcpu)->nested.legacy_gpat_semantics =3D false; + return 1; } =20 diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 88549705133f..0bb9fdcb489d 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -238,6 +238,15 @@ struct svm_nested_state { * on its side. */ bool force_msr_bitmap_recalc; + + /* + * Indicates that a legacy nested state (without a valid gPAT) was + * recently restored. Until the next KVM_RUN, updates to hPAT are + * also applied to gPAT, preserving legacy behavior (i.e. L2 shares + * L1's PAT). Because checkpoint restore is non-atomic, this + * complication is necessary for backward compatibility. + */ + bool legacy_gpat_semantics; }; =20 struct vcpu_sev_es_state { @@ -621,6 +630,8 @@ static inline void svm_set_hpat(struct vcpu_svm *svm, u= 64 data) if (is_guest_mode(&svm->vcpu) && !nested_npt_enabled(svm)) vmcb_set_gpat(svm->nested.vmcb02.ptr, data); } + if (svm->nested.legacy_gpat_semantics) + svm_set_gpat(svm, data); } =20 static inline bool nested_vnmi_enabled(struct vcpu_svm *svm) --=20 2.53.0.239.g8d8fc8a987-goog From nobody Thu Apr 2 19:00:06 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 33F5135E520 for ; Thu, 12 Feb 2026 15:59:25 +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=1770911968; cv=none; b=inebNpWU/W3obRDdRvh3wQm14inG6v/BMJPHKvEjpMe+jobSt9ljf6VTMrtRvFu20wPeXb5pH2cVy/3NR/m/lwCoDn7zgsu8QxWXT24/SAJWprj5qSfRZ27wf6dCCvUkrHqBj84H64Bfwp3CUm+I8/woznR7WWPixAzpAqhlhhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770911968; c=relaxed/simple; bh=8+Zi2wIRqjuMkzWhWVrhTevqZDBmEn7YJS8dxkMRtyQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=USD1PGJDIYQEvjee7696do8vVAeI/HNcV5lJUir+t4SqY3PBCsUcCU5wuS9yCEeXO8osgjcW6OGrRj2dkOWyRWyX3xSILeWmmbzTELS4+YULzwvc4igKMuwHIZ7UzrJ6zPTVQHXtTtmdOeJ5Jl+6rxL7GVwCfpuC8UvQAJ0h8Rg= 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=z/nxesuX; 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="z/nxesuX" Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2a8fc061ce1so209119015ad.0 for ; Thu, 12 Feb 2026 07:59:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1770911965; x=1771516765; 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=AUl3gjz1kKfg9Z4YCOJbzABwXZkXgt7AzcqRZ75wmRs=; b=z/nxesuXV+SlJbagjGlkIrXOPS7Ggr8QzY3JRyiFwnzz85EQveY2H59cZzXhM878j4 gLQlMzul+MNnFVKfWK4vKGWyl/KBQaaW1UAkCz1DETC2X5eY83BMSTz/N6qqEvIzTwi6 tEgIe+eoVpC41G84tcHzsOa2YEn0W9ltZjQDEFiTG49DU28xVwRmRVB8xWcKAdnwp0o/ 1G9+XIuSSt0yggEeEG9ragn0Dlo13yL2zmx2/Th8Nnmwo/hHx81F/y7lTvKI/j1AaQiZ cHmZPTrzGMEIXs85htMxHPPYwSHWk4WaXhCujtQs2ZToaTWnt5MfPIw5oEkg8MkzFoZM yglw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770911965; x=1771516765; 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=AUl3gjz1kKfg9Z4YCOJbzABwXZkXgt7AzcqRZ75wmRs=; b=Ez23iYceGX0FS7ATEHHcT6G/NHa8j2Uhg0AxyKDW69KOD3uurqJRNy0E8QRmyYCk3E Mkoatk2Ke/kG28i+AbMA1t2kiM1kFLYphJQSeoevx/pCV7claYsEu7AcgLCwp+CRHV5k 0amZVhFqUqmdyUAM1AERmacTTVrMi5+n5oJ+SaVfquD6Kox31Y3yRcUql3vMsBcHPb4J fyNsYviy2bErnKGHxSSWv2HKqSHQ/WWKGAQkC6u12h02lpWmlZeW7xQxnUGDtDwD1Y3L TnospVQZoDwUhzP3aVcfOrUx1nZ3mXz0HxZEeEeR3rUr7JEvyBvzizEQmVmtPLYex1Y5 l/2Q== X-Forwarded-Encrypted: i=1; AJvYcCVvwqsnFfKBuYeJ4YpF9RSM2w+aQ/eNRq3eifIQIH8AS+/rD7E2kAPAs/1G4GSym4AxqENkJIitCmHpQi0=@vger.kernel.org X-Gm-Message-State: AOJu0YyT5IrHlIejk9rXt7jpose43udxxhrQLYRAiu3TVKGfQhGMRsTW pD3u2gm/IJH0MZZEKruySl4d5eFcydpAAfMc9xzW2uebsd/FPDEMwLbI9Xr/dBvB4G9cY9NhG7G P/f+7lzJ66KVJPw== X-Received: from pleu16.prod.google.com ([2002:a17:903:41d0:b0:29f:2fcb:60c8]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2f0b:b0:2aa:d600:d03e with SMTP id d9443c01a7336-2ab398817f3mr36450955ad.18.1770911964630; Thu, 12 Feb 2026 07:59:24 -0800 (PST) Date: Thu, 12 Feb 2026 07:58:56 -0800 In-Reply-To: <20260212155905.3448571-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: <20260212155905.3448571-1-jmattson@google.com> X-Mailer: git-send-email 2.53.0.239.g8d8fc8a987-goog Message-ID: <20260212155905.3448571-9-jmattson@google.com> Subject: [PATCH v4 8/8] KVM: selftests: nSVM: Add svm_nested_pat test From: Jim Mattson To: Sean Christopherson , Paolo Bonzini , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , kvm@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" 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/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/x86/svm_nested_pat_test.c | 298 ++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/svm_nested_pat_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 7810f9db5f77..5554e40f73f8 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -110,6 +110,7 @@ TEST_GEN_PROGS_x86 +=3D x86/state_test TEST_GEN_PROGS_x86 +=3D x86/vmx_preemption_timer_test 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_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..08c1428969b0 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/svm_nested_pat_test.c @@ -0,0 +1,298 @@ +// 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); + 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); + 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)); + + 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.239.g8d8fc8a987-goog