From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A15B3C141F; Thu, 4 Jun 2026 20:36:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605361; cv=none; b=gi9cw0Cei7VW2m2HHY+AgGYF6b6MR1XmnGacJ9EKjGXhVO8NCNFpIqJ4bK+6qAKoJLu86vY1OfgukNcmKMD0kWnghUTOZEUz7TcsfvMVtSd25xTbI+dKR60lerLICJZUm05vjIRJp6HMctgN1Or86iW6oVDi5V456fIudGQZ/po= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605361; c=relaxed/simple; bh=02xq5Gh+6kg4ilsbxVrU9m4kwFyjWaforNS02Ur7P4c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j7HYDyq4yeTfoQfPEdvkLrzGsq6dOQutBKFj9xDTegkEeQExkiZstdgWO8MAB/fGow7WG5PsGBqgpRkpV2AG4xhT3lrkfKTlo39i4FlBlTQ3wB7h4U9I1tcMOOc5Th4G3rb1NL+4W2m+fyKxAJ/P6Qj2qy0DUhfAl2a4hLlPmqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nqhz2J1N; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nqhz2J1N" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 108C11F00899; Thu, 4 Jun 2026 20:36:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605360; bh=5vFdI1nPWjTWHGLKeQney7+T5Oug6fQYNZ9pJ08Nnm4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=nqhz2J1Nlkc+E9dt9r9gfpl5cuRE/9bPxAwuLqT8odAFq0wOFL01UeEkpOydUfySV r96obbSa/kk7Iqnjo5isi+StXSDoM/hPPjt1q42q27ZzV7fqkCj9GQQ8I9NwT0DbD0 0WMqC+Rbh9PBnf1u3wYWMN/7DSh5FZuLQoa997JLn94lmRl9qLVdEWXqxXobH8gfwE 3Y0xpiBbwjNljvT9vt0+7pNsTaQ2BnSgridsWNFkhxXboOvfRanO68tuCL0G5Ljwhx iofr6vbMI6G1daV78bTXzdlLfR5BTY4TQclrNCsxfmZPXjndf/Yd06/lkOZnB5HEhz prlMFKljF9ibQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 01/10] KVM: selftests: Move STR() and XSTR() definitions to test_util.h Date: Thu, 4 Jun 2026 20:35:37 +0000 Message-ID: <20260604203546.365658-2-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The macros are defined in two tests, and future changes will use them elsewhere. Move their definition into test_util.h to deduplicate them. No functional change intended. Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/test_util.h | 3 +++ tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c | 3 --- tools/testing/selftests/kvm/x86/smm_test.c | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kvm/include/test_util.h b/tools/testin= g/selftests/kvm/include/test_util.h index a56271c237ae9..c55148ebfe934 100644 --- a/tools/testing/selftests/kvm/include/test_util.h +++ b/tools/testing/selftests/kvm/include/test_util.h @@ -240,4 +240,7 @@ char *strdup_printf(const char *fmt, ...) __attribute__= ((format(printf, 1, 2), n =20 char *sys_get_cur_clocksource(void); =20 +#define STR(x) #x +#define XSTR(x) STR(x) + #endif /* SELFTEST_KVM_TEST_UTIL_H */ diff --git a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c b/to= ols/testing/selftests/kvm/x86/evmcs_smm_controls_test.c index 5b3aef109cfc5..0c655c48a75d6 100644 --- a/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c +++ b/tools/testing/selftests/kvm/x86/evmcs_smm_controls_test.c @@ -22,9 +22,6 @@ =20 #define SYNC_PORT 0xe =20 -#define STR(x) #x -#define XSTR(s) STR(s) - /* * SMI handler: runs in real-address mode. * Reports SMRAM_STAGE via port IO, then does RSM. diff --git a/tools/testing/selftests/kvm/x86/smm_test.c b/tools/testing/sel= ftests/kvm/x86/smm_test.c index 740051167dbd4..c260701d4691b 100644 --- a/tools/testing/selftests/kvm/x86/smm_test.c +++ b/tools/testing/selftests/kvm/x86/smm_test.c @@ -22,9 +22,6 @@ #define SMRAM_GPA 0x1000000 #define SMRAM_STAGE 0xfe =20 -#define STR(x) #x -#define XSTR(s) STR(s) - #define SYNC_PORT 0xe #define DONE 0xff =20 --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA0713C6A5F; Thu, 4 Jun 2026 20:36:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605361; cv=none; b=PLvV6YTSFe2hr760EpT6/ExyLPatuYOYa+fOD/e328+08PD0eLHf1h74dnr8XVrx4PSGZGl40enOj5JlKZ/oLOGDEJME+h5u33Z5IJjJIN046lgmbdTdgmKaKMV/7RKzzSFYSKFnm4MJkhT7AsKCSjunJMKarMH3oCNqyyCfhmw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605361; c=relaxed/simple; bh=o+gRf/jJkkQT7GrXgVPHQbiVu+EFRgY7NIiZfDaYg54=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OoMDRMlJFe1ZxHUo8BBXddnEY4xpJ0K1sGXGHQCCtflLraotLFG+SqXIO0Wm0xHBnPUvVT1M/OmiIsOtHqIImoFfh79mG7FAbN+qpHyBoQe/AB119KkBgYOpa3LzcGnqs3DaJ9/cAHzOqW391aYQRrPIu7pvMf8lloI2V9I2hiU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SRYqw7c5; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SRYqw7c5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 683FA1F0089A; Thu, 4 Jun 2026 20:36:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605360; bh=iyNtZBVOFOFiHv/bxlZAV8NqRiBzVXC6M4IsHF/XRWw=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=SRYqw7c57VATQRJQ8MPK9gQBEfEXhLqVO2uy2mfxkaGUxQRF+YJhvEMHbNsoBgUZH qKELDlXCpCacmMovDq615Kp/Y6ft6/jQetu24mA70MmOSLKqxt3p6vSE7UIKuDI6ZF ABliST0ic3QlmgwiGiZv6ljRgIG7uVhIuIvWdtw7FhtoUUM8bZhj9b90k02P2HRnIy /tgA09EYywF/c58h6furNNwlRLt/NLBt7Ky/pqgzA1qIIy+Y94fHgIZYgjWgZLsNz1 PZOZaqt6YoIwxDln3mI5AZHjSfqKV8WTIr2D4oy2JMZR/1hStWUkiSxVfH+riToxhR 4Z0hfNYg+v/Sw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed , Sashiko Subject: [PATCH v2 02/10] KVM: selftests: Fix RAX and RFLAGS VMCB offsets when running L2 Date: Thu, 4 Jun 2026 20:35:38 +0000 Message-ID: <20260604203546.365658-3-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The offsets used (0x170 and 0x1f8) are offsets within vmcb_save_area, not vmcb. The correct offsets should include the base of vmcb_save_area within vmcb (which is 0x400 -- so 0x570 and 0x5f8). Instead of just correcting the offsets, use vmcb->save.rax and vmcb->save.rflags as parameters to the asm block and avoid hardcoding offsets completely. While at it, also use guest_regs.rax directly instead of assuming it's at offset 0 of guest_regs. Note: "+m" must be used for vmcb_rax and vmcb_rflags, as caching those fields in registers would be wrong as the underlying KVM will update them in memory. The same problem was recently fixed (differently) for kvm-unit-tests [1]. [1]https://lore.kernel.org/all/20260521092311.86030-1-pbonzini@redhat.com/ Reported-by: Sashiko Closes: https://sashiko.dev/#/patchset/20260518202514.2037078-1-yosry%40ker= nel.org?part=3D1 Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/lib/x86/svm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 3b01605ab016c..f9ea1a2aeb8bc 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -162,19 +162,22 @@ void run_guest(struct vmcb *vmcb, u64 vmcb_gpa) { asm volatile ( "vmload %[vmcb_gpa]\n\t" - "mov rflags, %%r15\n\t" // rflags - "mov %%r15, 0x170(%[vmcb])\n\t" - "mov guest_regs, %%r15\n\t" // rax - "mov %%r15, 0x1f8(%[vmcb])\n\t" + "mov rflags, %%r15\n\t" + "mov %%r15, %[vmcb_rflags]\n\t" + "mov %[guest_regs_rax], %%r15\n\t" + "mov %%r15, %[vmcb_rax]\n\t" LOAD_GPR_C "vmrun %[vmcb_gpa]\n\t" SAVE_GPR_C - "mov 0x170(%[vmcb]), %%r15\n\t" // rflags + "mov %[vmcb_rflags], %%r15\n\t" "mov %%r15, rflags\n\t" - "mov 0x1f8(%[vmcb]), %%r15\n\t" // rax - "mov %%r15, guest_regs\n\t" + "mov %[vmcb_rax], %%r15\n\t" // rax + "mov %%r15, %[guest_regs_rax]\n\t" "vmsave %[vmcb_gpa]\n\t" - : : [vmcb] "r" (vmcb), [vmcb_gpa] "a" (vmcb_gpa) + : [vmcb_rflags] "+m" (vmcb->save.rflags), + [vmcb_rax] "+m" (vmcb->save.rax), + [guest_regs_rax] "+rm" (guest_regs.rax) + : [vmcb_gpa] "a" (vmcb_gpa) : "r15", "memory"); } =20 --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B5873D5642; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605362; cv=none; b=IzY5YEEkP27sNBtIFQv7zsLS6fIBRqHBoVdUBQSteBfgvjxC9kmdE0FNHX3o5mRN9md9DuEC24es7DqySmHlwtCwD/WL9Xbkg3Oiq+06AovTOkzjyjgRPG9Q/FOJSsb39Cn3Dq1ZbY+CyLB7FB6D+GyabXBOQYNAdZOdL6zNisE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605362; c=relaxed/simple; bh=Z83TagrY3VozBxtN/4asP9Llji66Ztgsekf1igu24sE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GrVIx5Mclqk1he/vjiF+cBzzxEkz0q9pROklpd4WGIRclZmHBvResfkDYKv24u4oYDiR/4XN5d7MJFWxwmLSc+dhuRsndoF4DXy8w6i44yYP+sI6DAMJoekcHfrG8rsIvf21yeNlWwscq917CyP8qCLLEc85HgXo5av/A9hTqRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NVI/a7Tq; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NVI/a7Tq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C81121F0089B; Thu, 4 Jun 2026 20:36:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605361; bh=Cr6+6IlJT99I4jbMP5FzLjUUru2KZhpu7m4ocFzuRIY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NVI/a7TqZO6caUY0U7Dk4hTzUnL8fYOEPyr1DMZ3sRmTta2yKVkliYzvCbr4p3Ako xAp4MmhVjjcwp4cgrt4Wb3IocF2uSS9N9iBt+OtaWFyGVEOfzSHqlZ5oe1f4ZYVif5 lxegluhA0Xkr3AgHx3PPZ0vkgUCZjlC8Nz9N6gCamyjL/hJnHzQNx4587n9Xw4BfwK POakuCjbNhCVflbO8HqfDgwbh9mVodbMDyb5L7k9Ij+YbmINtrQvkNvCqiq0n0QJlO 2zc82slo6x+aVPFdjcvcm6LDhulkFm2h3YrwpnoKJIQeehIigguyXCRYlEJKinvH3X A9z6PGnGTJZwQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 03/10] KVM: selftests: Use an array for guest_regs (and fix offsets) Date: Thu, 4 Jun 2026 20:35:39 +0000 Message-ID: <20260604203546.365658-4-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The assembly code defined by SAVE_GPR_C uses the wrong offsets for some registers in guest_regs. For example, the offset of RCX should 0x08 not 0x10. Also, the last offset in the struct (R15) is 0x78, not 0x80, so the code actually saves and restore beyond the end of gpr64_regs. Eliminate hardcoded offsets by using an array instead of a struct (similar to KVM's per-vCPU regs), and use the array index to generate the offset. While at it, rename SAVE_GPR_C and LOAD_GPR_C to a single macro, SVM_SWITCH_GPRS_ASM. Signed-off-by: Yosry Ahmed --- .../selftests/kvm/include/x86/processor.h | 36 +++++++-------- tools/testing/selftests/kvm/lib/x86/svm.c | 45 ++++++++++--------- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 513e4a1075fac..ff0b270bfe27f 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -396,25 +396,23 @@ static inline unsigned int x86_model(unsigned int eax) #define PTE_GET_PA(pte) ((pte) & PHYSICAL_PAGE_MASK) #define PTE_GET_PFN(pte) (PTE_GET_PA(pte) >> PAGE_SHIFT) =20 -/* General Registers in 64-Bit Mode */ -struct gpr64_regs { - u64 rax; - u64 rcx; - u64 rdx; - u64 rbx; - u64 rsp; - u64 rbp; - u64 rsi; - u64 rdi; - u64 r8; - u64 r9; - u64 r10; - u64 r11; - u64 r12; - u64 r13; - u64 r14; - u64 r15; -}; +#define GUEST_REGS_RAX 0 +#define GUEST_REGS_RCX 1 +#define GUEST_REGS_RDX 2 +#define GUEST_REGS_RBX 3 +#define GUEST_REGS_RSP 4 +#define GUEST_REGS_RBP 5 +#define GUEST_REGS_RSI 6 +#define GUEST_REGS_RDI 7 +#define GUEST_REGS_R8 8 +#define GUEST_REGS_R9 9 +#define GUEST_REGS_R10 10 +#define GUEST_REGS_R11 11 +#define GUEST_REGS_R12 12 +#define GUEST_REGS_R13 13 +#define GUEST_REGS_R14 14 +#define GUEST_REGS_R15 15 +#define NR_GUEST_REGS GUEST_REGS_R15 =20 struct desc64 { u16 limit0; diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index f9ea1a2aeb8bc..1bd111e8bed26 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -13,7 +13,7 @@ =20 #define SEV_DEV_PATH "/dev/sev" =20 -struct gpr64_regs guest_regs; +u64 guest_regs[NR_GUEST_REGS]; u64 rflags; =20 /* Allocate memory regions for nested SVM tests. @@ -123,7 +123,7 @@ void generic_svm_setup(struct svm_test_data *svm, void = *guest_rip, void *guest_r =20 vmcb->save.rip =3D (u64)guest_rip; vmcb->save.rsp =3D (u64)guest_rsp; - guest_regs.rdi =3D (u64)svm; + guest_regs[GUEST_REGS_RDI] =3D (u64)svm; =20 if (svm->ncr3_gpa) { ctrl->misc_ctl |=3D SVM_MISC_ENABLE_NP; @@ -131,27 +131,28 @@ void generic_svm_setup(struct svm_test_data *svm, voi= d *guest_rip, void *guest_r } } =20 +#define GUEST_SWITCH_GPR_ASM(reg, idx) \ + "xchg %%" #reg ", guest_regs + 8 *" XSTR(idx) "\n\t" + /* * save/restore 64-bit general registers except rax, rip, rsp * which are directly handed through the VMCB guest processor state */ -#define SAVE_GPR_C \ - "xchg %%rbx, guest_regs+0x20\n\t" \ - "xchg %%rcx, guest_regs+0x10\n\t" \ - "xchg %%rdx, guest_regs+0x18\n\t" \ - "xchg %%rbp, guest_regs+0x30\n\t" \ - "xchg %%rsi, guest_regs+0x38\n\t" \ - "xchg %%rdi, guest_regs+0x40\n\t" \ - "xchg %%r8, guest_regs+0x48\n\t" \ - "xchg %%r9, guest_regs+0x50\n\t" \ - "xchg %%r10, guest_regs+0x58\n\t" \ - "xchg %%r11, guest_regs+0x60\n\t" \ - "xchg %%r12, guest_regs+0x68\n\t" \ - "xchg %%r13, guest_regs+0x70\n\t" \ - "xchg %%r14, guest_regs+0x78\n\t" \ - "xchg %%r15, guest_regs+0x80\n\t" - -#define LOAD_GPR_C SAVE_GPR_C +#define SVM_SWITCH_GPRS_ASM \ + GUEST_SWITCH_GPR_ASM(rbx, GUEST_REGS_RBX) \ + GUEST_SWITCH_GPR_ASM(rcx, GUEST_REGS_RCX) \ + GUEST_SWITCH_GPR_ASM(rdx, GUEST_REGS_RDX) \ + GUEST_SWITCH_GPR_ASM(rbp, GUEST_REGS_RBP) \ + GUEST_SWITCH_GPR_ASM(rsi, GUEST_REGS_RSI) \ + GUEST_SWITCH_GPR_ASM(rdi, GUEST_REGS_RDI) \ + GUEST_SWITCH_GPR_ASM(r8, GUEST_REGS_R8) \ + GUEST_SWITCH_GPR_ASM(r9, GUEST_REGS_R9) \ + GUEST_SWITCH_GPR_ASM(r10, GUEST_REGS_R10) \ + GUEST_SWITCH_GPR_ASM(r11, GUEST_REGS_R11) \ + GUEST_SWITCH_GPR_ASM(r12, GUEST_REGS_R12) \ + GUEST_SWITCH_GPR_ASM(r13, GUEST_REGS_R13) \ + GUEST_SWITCH_GPR_ASM(r14, GUEST_REGS_R14) \ + GUEST_SWITCH_GPR_ASM(r15, GUEST_REGS_R15) =20 /* * selftests do not use interrupts so we dropped clgi/sti/cli/stgi @@ -166,9 +167,9 @@ void run_guest(struct vmcb *vmcb, u64 vmcb_gpa) "mov %%r15, %[vmcb_rflags]\n\t" "mov %[guest_regs_rax], %%r15\n\t" "mov %%r15, %[vmcb_rax]\n\t" - LOAD_GPR_C + SVM_SWITCH_GPRS_ASM "vmrun %[vmcb_gpa]\n\t" - SAVE_GPR_C + SVM_SWITCH_GPRS_ASM "mov %[vmcb_rflags], %%r15\n\t" "mov %%r15, rflags\n\t" "mov %[vmcb_rax], %%r15\n\t" // rax @@ -176,7 +177,7 @@ void run_guest(struct vmcb *vmcb, u64 vmcb_gpa) "vmsave %[vmcb_gpa]\n\t" : [vmcb_rflags] "+m" (vmcb->save.rflags), [vmcb_rax] "+m" (vmcb->save.rax), - [guest_regs_rax] "+rm" (guest_regs.rax) + [guest_regs_rax] "+rm" (guest_regs[GUEST_REGS_RAX]) : [vmcb_gpa] "a" (vmcb_gpa) : "r15", "memory"); } --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 84FF13DFC8F; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605362; cv=none; b=CVFxd7JmeQHlbszx+9jrYMGKQmqDrNhbqd8zy8Ycn9AqbuK6UuvvWs0ucIIzvjg5iacunhE4rvAqpKZnwJ1nBbfiumOJ8z0K2X3C+zVAy8CcknH0pq71ZzS3q+D+hfxoC+uR3R0gNwLlXrJ0XAPbMe9c/XOXS5rF7Lvb+IXGz0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605362; c=relaxed/simple; bh=5J8YWhpdP8Syhwa569HZmM4YNHLeAAV+rWpNb4p7wec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cM7uAS0LuGRlSVypVfd+WBVd3bnftSmLQMBLmyxCLv+pLN4kijLQGka91A2r/CogtufgiGIFObXs1jP/fn8FPcVR/5DCPItRl76OLR2sD5t1diE0C89ykbAqbZPjTeQ050qL7PCHZ5Y6dfqHxtAikcgh8Jdi9GCt00EPPjuF5aE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YRAtkeO4; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YRAtkeO4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2AA291F0089C; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605361; bh=AjoZr4mLwGK6n4XmzF+gC6Omz91QPnfrZ4XRKtO/Fo0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=YRAtkeO4UzDWC3TPK1xK+YgEIZAzWnwos5y1bZOyQUTCX0uD34uZgEw3gj88xjQ/q LHgBoRNimeAW++KY+YLZSkjL1aP+JFcvmD/NTk7FjZ4Pm72v0Lpgt/oOMUCLUTxw8l pNVUo6jyMXtPeUcpgrZv+NypTPGUHCIW9yKIWaz2SCGlzqqYhAVPT87sNzwxVC7qyi RYy/I6WqBwxAjx5GBJKZAFDcgC1Z2LlO9NLwEQhq7yvgOiyoTQW0oDy46+I3VoN6qu fGJnZA2Wqz08eo4VQIo6ULizwV0Ns5jpv0z7pZXMurXMEhrBJH13zJJyOLRkaXmxfu RmctrcMbwYaUQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 04/10] KVM: selftests: Move GPR load/save definitions outside of nSVM code Date: Thu, 4 Jun 2026 20:35:40 +0000 Message-ID: <20260604203546.365658-5-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for reusing the code for nVMX tests, move the guest_regs array declaration as well as GPR switching macro to processor.h. No functional change intended. Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/processor.h | 5 +++++ tools/testing/selftests/kvm/lib/x86/processor.c | 2 ++ tools/testing/selftests/kvm/lib/x86/svm.c | 4 ---- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index ff0b270bfe27f..57f81f0bcc42d 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -414,6 +414,11 @@ static inline unsigned int x86_model(unsigned int eax) #define GUEST_REGS_R15 15 #define NR_GUEST_REGS GUEST_REGS_R15 =20 +extern u64 guest_regs[NR_GUEST_REGS]; + +#define GUEST_SWITCH_GPR_ASM(reg, idx) \ + "xchg %%" #reg ", guest_regs + 8 *" XSTR(idx) "\n\t" + struct desc64 { u16 limit0; u16 base0; diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testin= g/selftests/kvm/lib/x86/processor.c index 4ca48de7a926d..44a7233d69900 100644 --- a/tools/testing/selftests/kvm/lib/x86/processor.c +++ b/tools/testing/selftests/kvm/lib/x86/processor.c @@ -29,6 +29,8 @@ bool host_cpu_is_amd_compatible; bool is_forced_emulation_enabled; u64 guest_tsc_khz; =20 +u64 guest_regs[NR_GUEST_REGS]; + const char *ex_str(int vector) { switch (vector) { diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/self= tests/kvm/lib/x86/svm.c index 1bd111e8bed26..6528a6416c178 100644 --- a/tools/testing/selftests/kvm/lib/x86/svm.c +++ b/tools/testing/selftests/kvm/lib/x86/svm.c @@ -13,7 +13,6 @@ =20 #define SEV_DEV_PATH "/dev/sev" =20 -u64 guest_regs[NR_GUEST_REGS]; u64 rflags; =20 /* Allocate memory regions for nested SVM tests. @@ -131,9 +130,6 @@ void generic_svm_setup(struct svm_test_data *svm, void = *guest_rip, void *guest_r } } =20 -#define GUEST_SWITCH_GPR_ASM(reg, idx) \ - "xchg %%" #reg ", guest_regs + 8 *" XSTR(idx) "\n\t" - /* * save/restore 64-bit general registers except rax, rip, rsp * which are directly handed through the VMCB guest processor state --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA981494A1A; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605363; cv=none; b=unDQR5QMUhM/B4UdGgYwGltJLakmRQ6MJ+gqlNgFabVtXR1lRa+9Cgcx+MfZCuAR+sfz/xoe3xs6K6FQM3Ms13x8cLFt4ZrQzkxrniAlqWEXVqAwNNZlE2vKelp6OM+9vRWkGimzwzlaVVTlvG+V0pB7wujPaoFAPQVa4Tecelk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605363; c=relaxed/simple; bh=j7IfzI3voPCQYj2N+nIvNBdNRyvLg7aGNszigvogpdU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mA5Hxp55VvSSpQ67sk4FHivQOeLXbdzhjBNp608iEl+NJykyv+PcAznCwm23AnqVKzjV/KMUd7XDAuHgvbT1p08HozB767iB8pfd8LH+Svq66/ozS+Fo1bIkgoRHIFuBuz7SCfru3O4idzzAVG1IiMu9xUgc4CgP+dJa34oRF94= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=H+fxadKU; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H+fxadKU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8148B1F00898; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605361; bh=ovrEBxl4FhwKwnx1ah7haB2DJeKCMEvjp5Fkgg7XjVA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=H+fxadKU6FYA7PhVsz9ZEGezp3EBvosGTYg7E8hmwvoYSj92a4iNO/SLDgY/TTxt5 XfeTxhGWxKZsaKOtpbWbWJWj8GF8P694h9jwsNAyN8DJGnIUSUn9CRXJL27lVokFCZ GvZ2uG1bHX4ABjGKDIkHRq9iuhsB6gxQYFKtKg0OPaoAa43D6keAt3FR/v5XCDQfT/ ebNDiZuviGIh4eDFDVT7sMyvK4KNKsR+OG9tJR3qibmUi43MVq66ugl6R9SzGXhzgs HC/BDEb+PNfe1FYF9mW+6s5QR03Ud7pWSpCr/waFVyidfsNOrMuW2JXnBIyXCtG0kF LhxOyzYsPLRTw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 05/10] KVM: selftests: Reuse GPR switching logic for nVMX Date: Thu, 4 Jun 2026 20:35:41 +0000 Message-ID: <20260604203546.365658-6-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Reuse the GPR switching logic for nVMX by defining VMX_SWITCH_GPRS_ASM, which is essentially the same as SVM_SWITCH_GPRS_ASM but also switches RAX, replacing the push/pop of a subset of the registers. The long clobber list of registers is no longer needed as registers are saved and restored appropriately (and not clobbered by L2). Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/include/x86/vmx.h | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/tools/testing/selftests/kvm/include/x86/vmx.h b/tools/testing/= selftests/kvm/include/x86/vmx.h index 90fffaf915958..64996c310fe4c 100644 --- a/tools/testing/selftests/kvm/include/x86/vmx.h +++ b/tools/testing/selftests/kvm/include/x86/vmx.h @@ -363,9 +363,23 @@ static inline u64 vmptrstz(void) return value; } =20 -/* - * No guest state (e.g. GPRs) is established by this vmlaunch. - */ +#define VMX_SWITCH_GPRS_ASM \ + GUEST_SWITCH_GPR_ASM(rax, GUEST_REGS_RAX) \ + GUEST_SWITCH_GPR_ASM(rbx, GUEST_REGS_RBX) \ + GUEST_SWITCH_GPR_ASM(rcx, GUEST_REGS_RCX) \ + GUEST_SWITCH_GPR_ASM(rdx, GUEST_REGS_RDX) \ + GUEST_SWITCH_GPR_ASM(rbp, GUEST_REGS_RBP) \ + GUEST_SWITCH_GPR_ASM(rsi, GUEST_REGS_RSI) \ + GUEST_SWITCH_GPR_ASM(rdi, GUEST_REGS_RDI) \ + GUEST_SWITCH_GPR_ASM(r8, GUEST_REGS_R8) \ + GUEST_SWITCH_GPR_ASM(r9, GUEST_REGS_R9) \ + GUEST_SWITCH_GPR_ASM(r10, GUEST_REGS_R10) \ + GUEST_SWITCH_GPR_ASM(r11, GUEST_REGS_R11) \ + GUEST_SWITCH_GPR_ASM(r12, GUEST_REGS_R12) \ + GUEST_SWITCH_GPR_ASM(r13, GUEST_REGS_R13) \ + GUEST_SWITCH_GPR_ASM(r14, GUEST_REGS_R14) \ + GUEST_SWITCH_GPR_ASM(r15, GUEST_REGS_R15) + static inline int vmlaunch(void) { int ret; @@ -373,34 +387,23 @@ static inline int vmlaunch(void) if (enable_evmcs) return evmcs_vmlaunch(); =20 - __asm__ __volatile__("push %%rbp;" - "push %%rcx;" - "push %%rdx;" - "push %%rsi;" - "push %%rdi;" - "push $0;" + __asm__ __volatile__("push $0;" "vmwrite %%rsp, %[host_rsp];" "lea 1f(%%rip), %%rax;" "vmwrite %%rax, %[host_rip];" + VMX_SWITCH_GPRS_ASM "vmlaunch;" "incq (%%rsp);" - "1: pop %%rax;" - "pop %%rdi;" - "pop %%rsi;" - "pop %%rdx;" - "pop %%rcx;" - "pop %%rbp;" + "1: ;" + VMX_SWITCH_GPRS_ASM + "pop %%rax;" : [ret]"=3D&a"(ret) : [host_rsp]"r"((u64)HOST_RSP), [host_rip]"r"((u64)HOST_RIP) - : "memory", "cc", "rbx", "r8", "r9", "r10", - "r11", "r12", "r13", "r14", "r15"); + : "memory", "cc"); return ret; } =20 -/* - * No guest state (e.g. GPRs) is established by this vmresume. - */ static inline int vmresume(void) { int ret; @@ -408,28 +411,20 @@ static inline int vmresume(void) if (enable_evmcs) return evmcs_vmresume(); =20 - __asm__ __volatile__("push %%rbp;" - "push %%rcx;" - "push %%rdx;" - "push %%rsi;" - "push %%rdi;" - "push $0;" + __asm__ __volatile__("push $0;" "vmwrite %%rsp, %[host_rsp];" "lea 1f(%%rip), %%rax;" "vmwrite %%rax, %[host_rip];" + VMX_SWITCH_GPRS_ASM "vmresume;" "incq (%%rsp);" - "1: pop %%rax;" - "pop %%rdi;" - "pop %%rsi;" - "pop %%rdx;" - "pop %%rcx;" - "pop %%rbp;" + "1: ;" + VMX_SWITCH_GPRS_ASM + "pop %%rax;" : [ret]"=3D&a"(ret) : [host_rsp]"r"((u64)HOST_RSP), [host_rip]"r"((u64)HOST_RIP) - : "memory", "cc", "rbx", "r8", "r9", "r10", - "r11", "r12", "r13", "r14", "r15"); + : "memory", "cc"); return ret; } =20 --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C3314C9008; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605363; cv=none; b=UM3xoQEXKnmJk5coXt5dzYJ6OoATquqatrioMqzuamBG5ESichnSLb0Ygr57DYEHcvp+tHOuUidfjFKfjVt7RJyFjK7OGFeZyRv+oBOlNJPgvzOVKiePeS68Rpe3lMwRZCaVpc4Pubqr+uWg+F0DEgTZm6XGCsESTSHR49gSZ8I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605363; c=relaxed/simple; bh=NC84ffeQy0iJL663aiqOy0R/eAc3gFvlRDSb+4dOhMY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ozHsukRYnJHM4NU+YB8X/L37n4OlusyJWle8ewktYaUPGrBp8PHs5tm1tAnwwNb0XqOpf37kKnnrc0JZUsPBrBH0IeZXMXtjuspp9rJdNUwO5cZWSRC9MqXh7uTVq7/9l7iBUhP6q5CU4brrJ1/smGILenHhneg7Ncx95kbwBGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oH1kkwsF; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oH1kkwsF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D7C991F00899; Thu, 4 Jun 2026 20:36:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605362; bh=OWWUy0BLOs/Gt8WhkITHDyuN301UMNeyVOt4Dhby09s=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=oH1kkwsFdwRGgpHZxjhlKiE5RRHjvvjnVe6T66j8hFVdBYBtXHw9XtiNapkpTPLP8 o03AfidrJKgfk9thQu7710O4iY9Dxnzc5ZM+oxn7cy6YLb+xjt+sTGisVFoV0+LUSC JdSfhadLUXt16Xvr9W9GXigip9+XNIT6rg/8EI93jD2qMZg9Lrhx7FmumXQ9TJT84c +l/Y6zU282CpomcVybBGji1rNFdoEwh4cT1Y3ZYVVOgo0UAbNI2rENzQO1Wd/XBhVE weqErBzebfGPUjl6bMdv6UPFs+FFXXOy+4K54qrmPmLKpjHyi5qnrgwpsGepi3IMZ2 Fu+OS2KeRDNrw== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 06/10] KVM: selftests: Drop HORRIFIC_L2_UCALL_CLOBBER_HACK Date: Thu, 4 Jun 2026 20:35:42 +0000 Message-ID: <20260604203546.365658-7-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Now that nVMX test codes preserves GPRs across nested VM-Exits (specifically RBP, RDX, and RDI among others), drop the ucall-specific hack to avoid clobbering these registers. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/lib/x86/ucall.c | 32 ++------------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/tools/testing/selftests/kvm/lib/x86/ucall.c b/tools/testing/se= lftests/kvm/lib/x86/ucall.c index e7dd5791959ba..38050c60a0670 100644 --- a/tools/testing/selftests/kvm/lib/x86/ucall.c +++ b/tools/testing/selftests/kvm/lib/x86/ucall.c @@ -10,36 +10,8 @@ =20 void ucall_arch_do_ucall(gva_t uc) { - /* - * FIXME: Revert this hack (the entire commit that added it) once nVMX - * preserves L2 GPRs across a nested VM-Exit. If a ucall from L2, e.g. - * to do a GUEST_SYNC(), lands the vCPU in L1, any and all GPRs can be - * clobbered by L1. Save and restore non-volatile GPRs (clobbering RBP - * in particular is problematic) along with RDX and RDI (which are - * inputs), and clobber volatile GPRs. *sigh* - */ -#define HORRIFIC_L2_UCALL_CLOBBER_HACK \ - "rcx", "rsi", "r8", "r9", "r10", "r11" - - asm volatile("push %%rbp\n\t" - "push %%r15\n\t" - "push %%r14\n\t" - "push %%r13\n\t" - "push %%r12\n\t" - "push %%rbx\n\t" - "push %%rdx\n\t" - "push %%rdi\n\t" - "in %[port], %%al\n\t" - "pop %%rdi\n\t" - "pop %%rdx\n\t" - "pop %%rbx\n\t" - "pop %%r12\n\t" - "pop %%r13\n\t" - "pop %%r14\n\t" - "pop %%r15\n\t" - "pop %%rbp\n\t" - : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory", - HORRIFIC_L2_UCALL_CLOBBER_HACK); + asm volatile("in %[port], %%al" + : : [port] "d" (UCALL_PIO_PORT), "D" (uc) : "rax", "memory"); } =20 void *ucall_arch_get_ucall(struct kvm_vcpu *vcpu) --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99CEC4C9572; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; cv=none; b=mAg3qlSRb1BT6nvC8QPm9Pw/5JeLQVZiPpqi5NKqp0Uu0pU375YNuAufHgh41R1Jv4rFOzUfBB3to0GMHulnx8IDOz2dkipWMcuW8xuxu01qwTo34fIMNsoIK4634SnDoFv/nUsOS3fiwXfigwaXzI1wl8MPfSoWol/EzZXbUAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; c=relaxed/simple; bh=Y4eDkGK0ehQ12zM1FBuXQANl48HN/yccSnXn6UEKv10=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YueDYH7d6vjTcIm7qGawLN09Fxy4IO8N/Bti3i085aST7vYSbS8AcOjOWUNgUU4HMdaZJXo4+1qzI0YCrM6a1DHSw7wW2hBTJzBclQyk0PvVGgr6wY9ECxjy1wPNm8ioGsxN7sGYR8ojxmkCRNWZkq5crXUq+3WKrVrVJ802adE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=L3TIXWLC; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="L3TIXWLC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A4241F00893; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605362; bh=X3Y0rZQMz1+PTOXhliSdx0TPFg2QLN/dHqojh29LrrI=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=L3TIXWLCkgs+wiiF9OGD1o7Q9pcR/C+3F5kwkEdRe1ayENZx6hQkZWDfl25WXoiWK //YxxdUBzGQ09QtZ2CzsQPEwPXGvR1C+SiiJ5HKJ4Z+pf9otngSdh7ginEWkw6auT7 6C7vsbP8ySvzlecYNhMSBcp/ttMmTe5hV4hu8/KO0SCxoiSd9Xc8zUyF2YOGbiQ+x3 1FPQLla+lG3lIYdu5j4dZUkUBHc7xg835iczkdjtwKILgLgEoINQNCJYGUjZIwoPMv TmBEbsrRxvsg5I7ugn3jaoErZj0lm2FfH2aZS5gSCzLqrFkvvSxeqa+vD7o6ZIWT68 aAUQMp2rUMTww== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 07/10] KVM: selftests: Add basic stress test for save+restore and #PF handling Date: Thu, 4 Jun 2026 20:35:43 +0000 Message-ID: <20260604203546.365658-8-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a basic stress test for handling #PFs in a guest while the host is doing save+restore cycles. The guest periodically accesses non-present memory causing a #PF, and the #PF handler walks the page tables and updates the PTE to be present, like a proper #PF handler. After every access (and #PF), the guest triggers a sync and the test performs save+restore of the VM. This is not very meaningful as save+restore are performed after the access and #PF handling complete, but following changes will change that. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/include/x86/processor.h | 14 ++ .../kvm/x86/stress_save_restore_pf_test.c | 182 ++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/stress_save_restore_pf_= test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index e0ddd3ff9472d..731ef7de1afb4 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -111,6 +111,7 @@ TEST_GEN_PROGS_x86 +=3D x86/set_sregs_test TEST_GEN_PROGS_x86 +=3D x86/smaller_maxphyaddr_emulation_test TEST_GEN_PROGS_x86 +=3D x86/smm_test TEST_GEN_PROGS_x86 +=3D x86/state_test +TEST_GEN_PROGS_x86 +=3D x86/stress_save_restore_pf_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 diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/te= sting/selftests/kvm/include/x86/processor.h index 57f81f0bcc42d..10d26e079a1a8 100644 --- a/tools/testing/selftests/kvm/include/x86/processor.h +++ b/tools/testing/selftests/kvm/include/x86/processor.h @@ -585,6 +585,15 @@ static inline void set_cr0(u64 val) __asm__ __volatile__("mov %0, %%cr0" : : "r" (val) : "memory"); } =20 +static inline u64 get_cr2(void) +{ + u64 cr2; + + __asm__ __volatile__("mov %%cr2, %[cr2]" + : /* output */ [cr2]"=3Dr"(cr2)); + return cr2; +} + static inline u64 get_cr3(void) { u64 cr3; @@ -880,6 +889,11 @@ static inline void write_sse_reg(int reg, const sse128= _t *data) } } =20 +static inline void invlpg(u64 addr) +{ + __asm__ __volatile__("invlpg (%0)" : : "r"(addr) : "memory"); +} + static inline void cpu_relax(void) { asm volatile("rep; nop" ::: "memory"); diff --git a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c = b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c new file mode 100644 index 0000000000000..622d102179e66 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include +#include +#include +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define NR_ITERATIONS 500 + +#define GOTO_PREV_LINE "\033[A\r" +#define PRINT_ITER(s, x) \ +do { \ + if (x =3D=3D 1) \ + printf(s "%d\n", x); \ + else \ + printf(GOTO_PREV_LINE s "%d\n", x); \ + fflush(stdout); \ +} while (0) + +#define PTRS_PER_PTE 512 +#define PXD_INDEX(vaddr, level) (((vaddr) >> PG_LEVEL_SHIFT(level)) & (PTR= S_PER_PTE - 1)) + +#define TEST_MEM_BASE_GVA 0xc0000000ULL +#define TEST_PGTABLE_GVA_OFFSET 0xd0000000ULL +#define NR_TEST_ADDRS PTRS_PER_PTE +#define PATTERN 0xabcdefabcdefabcdULL + +static u64 pte_present_mask; +static u64 pte_huge_mask; + +static u64 expected_vaddr; +static u64 guest_faults; + +static u64 *guest_get_pte(u64 vaddr) +{ + u64 pgtable_pa, pte; + u64 *pgtable; + int level; + bool la57; + + la57 =3D !!(get_cr4() & X86_CR4_LA57); + level =3D la57 ? PG_LEVEL_256T : PG_LEVEL_512G; + + pgtable_pa =3D get_cr3() & PHYSICAL_PAGE_MASK; + for (; level > PG_LEVEL_4K; level--) { + pgtable =3D (u64 *)(pgtable_pa + TEST_PGTABLE_GVA_OFFSET); + pte =3D pgtable[PXD_INDEX(vaddr, level)]; + GUEST_ASSERT(pte & pte_present_mask); + GUEST_ASSERT(!(pte & pte_huge_mask)); + pgtable_pa =3D PTE_GET_PA(pte); + } + + pgtable =3D (u64 *)(pgtable_pa + TEST_PGTABLE_GVA_OFFSET); + return &pgtable[PXD_INDEX(vaddr, PG_LEVEL_4K)]; +} + +static void guest_pf_handler(struct ex_regs *regs) +{ + u64 fault_addr; + u64 *ptep; + + fault_addr =3D get_cr2(); + GUEST_ASSERT_EQ(fault_addr, READ_ONCE(expected_vaddr)); + + ptep =3D guest_get_pte(fault_addr); + GUEST_ASSERT(ptep); + GUEST_ASSERT(!(*ptep & pte_present_mask)); + + *ptep |=3D pte_present_mask; + invlpg(fault_addr); + + guest_faults++; +} + +static void guest_access_memory(void *arg) +{ + u64 vaddr, val; + int i =3D 0; + + for (;; i++) { + vaddr =3D TEST_MEM_BASE_GVA + (i % NR_TEST_ADDRS) * PAGE_SIZE; + WRITE_ONCE(expected_vaddr, vaddr); + + /* Read to trigger #PF */ + val =3D READ_ONCE(*(u64 *)vaddr); + GUEST_ASSERT_EQ(val, PATTERN); + + /* Clear the present bit again so it faults next time */ + *guest_get_pte(vaddr) &=3D ~pte_present_mask; + invlpg(vaddr); + + GUEST_SYNC(guest_faults); + } +} + +int main(int argc, char *argv[]) +{ + struct kvm_x86_state *state; + int r, i, level, count =3D 0; + gpa_t gpa, pgtable_gpa; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + struct ucall uc; + u64 *pgtable; + gva_t gva; + u64 pte; + + vm =3D vm_create_with_one_vcpu(&vcpu, guest_access_memory); + vm_install_exception_handler(vm, PF_VECTOR, guest_pf_handler); + + pte_present_mask =3D PTE_PRESENT_MASK(&vm->mmu); + pte_huge_mask =3D PTE_HUGE_MASK(&vm->mmu); + sync_global_to_guest(vm, pte_present_mask); + sync_global_to_guest(vm, pte_huge_mask); + + /* Allocate a page and write the pattern to it */ + gva =3D vm_alloc_page(vm); + *(u64 *)addr_gva2hva(vm, gva) =3D PATTERN; + gpa =3D addr_gva2gpa(vm, gva); + + /* + * Map all virtual addresses to the pattern page and clear the present + * bit such that guest accesses will cause a #PF. + */ + for (i =3D 0; i < NR_TEST_ADDRS; i++) { + gva =3D TEST_MEM_BASE_GVA + i * getpagesize(); + virt_pg_map(vm, gva, gpa); + *vm_get_pte(vm, gva) &=3D ~pte_present_mask; + } + + /* + * Now create mappings for the page tables created above so that the + * guest #PF handler can walk them. All PTEs for test virtual addresses + * should lie on the same PTE page, so one page is mapped for each page + * table level. + * + * Use an offset for the GVA instead of creating identity mappings to + * avoid collision with existing mappings at low GVAs (e.g. ELF). + */ + pgtable_gpa =3D vm->mmu.pgd; + for (level =3D vm->mmu.pgtable_levels; level >=3D PG_LEVEL_4K; level--) { + virt_map(vm, pgtable_gpa + TEST_PGTABLE_GVA_OFFSET, pgtable_gpa, 1); + pgtable =3D addr_gpa2hva(vm, pgtable_gpa); + pte =3D pgtable[PXD_INDEX(TEST_MEM_BASE_GVA, level)]; + pgtable_gpa =3D PTE_GET_PA(pte); + } + + while (count++ < NR_ITERATIONS) { + r =3D __vcpu_run(vcpu); + TEST_ASSERT(!r, "vcpu_run failed"); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + get_ucall(vcpu, &uc); + if (uc.cmd =3D=3D UCALL_ABORT) { + REPORT_GUEST_ASSERT(uc); + break; + } + TEST_ASSERT_EQ(uc.cmd, UCALL_SYNC); + TEST_ASSERT_EQ(uc.args[1], count - 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); + + PRINT_ITER("Save+restore iterations: ", count); + } + + sync_global_from_guest(vm, guest_faults); + pr_info("Guest page faults: %lu\n", guest_faults); + + kvm_vm_free(vm); + return 0; +} --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6CEB4CA272; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605365; cv=none; b=kHtCoNB4xY0z8Sd7enCJ8wTc/TgQC+HTwTg+v3042Il8XHCpiChZO/fm7L6cpPtGqWLyKZF0FS66qKaidMG8XZybv5hriYj5Kq9eEkyj9bZ3zXTUOSPTNrLW9DLp9Slgs5Vrx9EH/CCh7Vd+VIRoin0YusxePQhKkY1y9aYpbKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605365; c=relaxed/simple; bh=8iBKASzbz9mlsV2tDL6ihk64B3BCpKYDiU7NsrNIa1k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Mg3YtgPC8IpT+dI0ni+Bb2OgQbOR1Uog8IAGk2whpV1dKEBnefV8s/fg1HMSXBWTrY1OnifSQV1z8v+wCyS/fmb1pxINvwbSmIgQDo2iLG3rSk7OgzuSfK/BfAEUtaiA/M3ZXGSXcO9w9hCfdJ14mJXgSYM077CuvoO5hCcqtic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DsdXjiG9; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DsdXjiG9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 90AEB1F0089B; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605362; bh=VsVTfc8q8V6S6PMSRT8ydmbG/vrsrRUOqsArdYthojc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DsdXjiG9GbOPWYH/5Mn5OIaekbHvRlV0WFKW+s3vVwJ32A5vPgBWAUkin1ek+tTLI cY/9K/DwQgwHIXqIQL2I5e0AqXNQollFgKkNgQiCknboibnKUDv4QQMXiuXkvB5Eq7 hKmHkasH8baEZ1YzqpJdbFGr9xgkb3M6vshsFrV8b2CXWAXJ8/Nfsx+s5TiARoW7OX dLio1Bsz6M5ZeXSlgUQ6v4sMeoFeAY9z15J9Vt8KDo4wAl9qS1WvpCHyLLmD11hB6L 7rjmjnJTlLu+Ea0skafFuK+/B+e/BGJEMAFnH1zV9IHx9ayVPqoaYnhFORz313CO6h CDSxDQDq+ryAA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 08/10] KVM: selftests: Trigger save+restore randomly in the #PF stress test Date: Thu, 4 Jun 2026 20:35:44 +0000 Message-ID: <20260604203546.365658-9-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Instead of an explicit GUEST_SYNC() after each access+#PF, run another thread that keeps sending SIGUSR to the vCPU thread, essentially triggering exits to userspace and save+restore on random points in guest execution. This makes the test a lot more meaningful as it opens the door to exercising race conditions between #PF handling in the guest and save+restore in the host. The signals are ignored using SIG_IGN outside of __vcpu_run() to avoid interrupting other ioctls/sysctls performed by the test. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- .../kvm/x86/stress_save_restore_pf_test.c | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c = b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c index 622d102179e66..92efb7ac9d95f 100644 --- a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c +++ b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include =20 #include "test_util.h" @@ -94,15 +96,41 @@ static void guest_access_memory(void *arg) /* Clear the present bit again so it faults next time */ *guest_get_pte(vaddr) &=3D ~pte_present_mask; invlpg(vaddr); + } +} + +static void *sigusr_thread_fn(void *arg) +{ + pthread_t vcpu_thread =3D (pthread_t)arg; =20 - GUEST_SYNC(guest_faults); + for (;;) { + pthread_testcancel(); + pthread_kill(vcpu_thread, SIGUSR1); + usleep(100); } + return NULL; +} + +static void dummy_signal_handler(int signo) {} +static struct sigaction sa; + +static void vcpu_sigusr_listen(void) +{ + sa.sa_handler =3D dummy_signal_handler; + sigaction(SIGUSR1, &sa, NULL); +} + +static void vcpu_sigusr_ignore(void) +{ + sa.sa_handler =3D SIG_IGN; + sigaction(SIGUSR1, &sa, NULL); } =20 int main(int argc, char *argv[]) { struct kvm_x86_state *state; int r, i, level, count =3D 0; + pthread_t sigusr_thread; gpa_t gpa, pgtable_gpa; struct kvm_vcpu *vcpu; struct kvm_vm *vm; @@ -151,18 +179,30 @@ int main(int argc, char *argv[]) pgtable_gpa =3D PTE_GET_PA(pte); } =20 + /* Initialize the thread sending SIGUSR and install the handler */ + vcpu_sigusr_ignore(); + r =3D pthread_create(&sigusr_thread, NULL, sigusr_thread_fn, + (void *)pthread_self()); + TEST_ASSERT(!r, "pthread_create() failed: %d", r); + while (count++ < NR_ITERATIONS) { + /* + * Only handle SIGUSR while the vCPU is running, otherwise + * ignore it to avoid interrupting other ioctls/syscalls. + */ + vcpu_sigusr_listen(); r =3D __vcpu_run(vcpu); - TEST_ASSERT(!r, "vcpu_run failed"); - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); - - get_ucall(vcpu, &uc); - if (uc.cmd =3D=3D UCALL_ABORT) { + if (r =3D=3D -1) + TEST_ASSERT_EQ(errno, EINTR); + vcpu_sigusr_ignore(); + + /* The guest only exits due to a signal or failed assertion */ + if (!r) { + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_ABORT); REPORT_GUEST_ASSERT(uc); break; } - TEST_ASSERT_EQ(uc.cmd, UCALL_SYNC); - TEST_ASSERT_EQ(uc.args[1], count - 1); =20 state =3D vcpu_save_state(vcpu); =20 @@ -175,8 +215,11 @@ int main(int argc, char *argv[]) } =20 sync_global_from_guest(vm, guest_faults); + TEST_ASSERT(guest_faults > 0, "No guest page faults triggered"); pr_info("Guest page faults: %lu\n", guest_faults); =20 + pthread_cancel(sigusr_thread); + pthread_join(sigusr_thread, NULL); kvm_vm_free(vm); return 0; } --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 39B4D4CA28E; Thu, 4 Jun 2026 20:36:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; cv=none; b=UuUk9nq3YKrFAOF2T+HOq8ddp9l5JySFYtsrNPyyXMmEuXiUO0cO/YWwshRiPyVXZHGm1okPJdlcpOtMJLW+oIw4CnQoOgeX7SqSMUZugtYZb31Rtup+96Jpu9pcgrrSvWYTxROY+LRyTOHpwBQ4tJm6Ke780aPgx4AjhCTl2Ws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; c=relaxed/simple; bh=jYDcP1j84C4u3f4AWfEcCd2MRGkrmQ+VaR17b6rbbk0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RAGj96nkSxQewtZ6PogKnc73JA6ESHlzNlnAwQ7mB7bhL+xCxaRsgRglYKtKlY1KW/JoMEUBDwrXwMRoJV/4p+pua+MzhmmH9AQNgZ7zPK3kkNvIQS7oRQ6KIwqBkCGtzVT59Ys+k8St503lCl+Ug0n/quazB9qdIBRidV9i/ps= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZHNFg7TL; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZHNFg7TL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E74801F0089C; Thu, 4 Jun 2026 20:36:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605363; bh=i/TIB41PHxWTXJyWP5r4IoLt45r+2twsxHvTX+LHVr0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZHNFg7TL+XnYcX0olqhU6rn7MBVxy0m7tm4oIfzK/uxV0hn8FUhAkMi9KmGpQg8I6 9C8gBxiYKqAbcPv4FyvqlXK2xPC65FI+7NXFBm3t45EFM3F91RNX/unsHMXtM97mfz xpVXikvzOt6f5sH2FQb9lQcrsr5+CIuriLJsWXy4GCR0xAf3lmES2iyroZdNbb2Zde r09a6W+i3A6AFYog2fQOsq9RsrwCfPEqAmOLn2oRpCA7zNOBWYXDB3gW4sNMIICLwy xcBg/mHm9byWxlnt0XplJ06DGLYONH1sE37i59pWNE5SjbaWqpXVO0/Z/vYqujCnCG fwBwXIRu0YZCA== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 09/10] KVM: selftests: Support running stress save+restore and #PF test in L2 Date: Thu, 4 Jun 2026 20:35:45 +0000 Message-ID: <20260604203546.365658-10-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the stress test to allow running the access+#PF code in L2 instead of L1 by adding proper L1 guest code to bootstrap L2. The test runs in nested mode if a '-n' flag is added. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- .../kvm/x86/stress_save_restore_pf_test.c | 75 ++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c = b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c index 92efb7ac9d95f..c285ef093400d 100644 --- a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c +++ b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c @@ -8,10 +8,13 @@ #include #include #include +#include =20 #include "test_util.h" #include "kvm_util.h" #include "processor.h" +#include "svm_util.h" +#include "vmx.h" =20 #define NR_ITERATIONS 500 =20 @@ -25,6 +28,8 @@ do { \ fflush(stdout); \ } while (0) =20 +#define L2_GUEST_STACK_SIZE 64 + #define PTRS_PER_PTE 512 #define PXD_INDEX(vaddr, level) (((vaddr) >> PG_LEVEL_SHIFT(level)) & (PTR= S_PER_PTE - 1)) =20 @@ -99,6 +104,41 @@ static void guest_access_memory(void *arg) } } =20 +static void l1_svm_code(struct svm_test_data *svm) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + + generic_svm_setup(svm, guest_access_memory, &l2_guest_stack[L2_GUEST_STAC= K_SIZE]); + + run_guest(svm->vmcb, svm->vmcb_gpa); + GUEST_ASSERT(false); +} + +static void l1_vmx_code(struct vmx_pages *vmx) +{ + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + + GUEST_ASSERT(prepare_for_vmx_operation(vmx)); + GUEST_ASSERT(load_vmcs(vmx)); + prepare_vmcs(vmx, guest_access_memory, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); + + /* Ignore any #PF */ + GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, BIT(PF_VECTOR))); + GUEST_ASSERT(!vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0)); + GUEST_ASSERT(!vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, -1)); + + GUEST_ASSERT(!vmlaunch()); + GUEST_ASSERT(false); +} + +static void l1_guest_code(void *test_data) +{ + if (this_cpu_has(X86_FEATURE_SVM)) + l1_svm_code(test_data); + else + l1_vmx_code(test_data); +} + static void *sigusr_thread_fn(void *arg) { pthread_t vcpu_thread =3D (pthread_t)arg; @@ -126,6 +166,25 @@ static void vcpu_sigusr_ignore(void) sigaction(SIGUSR1, &sa, NULL); } =20 +static bool parse_args_nested(int argc, char *argv[]) +{ + bool nested =3D false; + int opt; + + while ((opt =3D getopt(argc, argv, "n")) !=3D -1) { + switch (opt) { + case 'n': + nested =3D true; + break; + default: + printf("Usage: %s [-n]\n", argv[0]); + exit(1); + } + } + + return nested; +} + int main(int argc, char *argv[]) { struct kvm_x86_state *state; @@ -136,12 +195,24 @@ int main(int argc, char *argv[]) struct kvm_vm *vm; struct ucall uc; u64 *pgtable; + bool nested; gva_t gva; u64 pte; =20 - vm =3D vm_create_with_one_vcpu(&vcpu, guest_access_memory); + nested =3D parse_args_nested(argc, argv); + + vm =3D vm_create_with_one_vcpu(&vcpu, nested ? l1_guest_code : guest_acce= ss_memory); vm_install_exception_handler(vm, PF_VECTOR, guest_pf_handler); =20 + if (nested) { + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM) || kvm_cpu_has(X86_FEATURE_VMX= )); + if (kvm_cpu_has(X86_FEATURE_SVM)) + vcpu_alloc_svm(vm, &gva); + else + vcpu_alloc_vmx(vm, &gva); + vcpu_args_set(vcpu, 1, gva); + } + pte_present_mask =3D PTE_PRESENT_MASK(&vm->mmu); pte_huge_mask =3D PTE_HUGE_MASK(&vm->mmu); sync_global_to_guest(vm, pte_present_mask); @@ -216,7 +287,7 @@ int main(int argc, char *argv[]) =20 sync_global_from_guest(vm, guest_faults); TEST_ASSERT(guest_faults > 0, "No guest page faults triggered"); - pr_info("Guest page faults: %lu\n", guest_faults); + pr_info("Guest page faults%s: %lu\n", nested ? " (in L2)" : "", guest_fau= lts); =20 pthread_cancel(sigusr_thread); pthread_join(sigusr_thread, NULL); --=20 2.54.0.1032.g2f8565e1d1-goog From nobody Mon Jun 8 07:22:06 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 935D74D2EC5; Thu, 4 Jun 2026 20:36:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; cv=none; b=D/dQfP3eggnhtGUsMjZD0prIJftq/OmJCoqVBcg+2v5+C3qnlNxVP7ZcBBW/dVJnm+SUE9gpdrgyYOKpgudiOESl94vnsW1jTCVPbbfHGa5T7M0p1p2Ny00wzUNC3LI4hMGZNai/hQGrtWLmwcoUxZn/1NXuVp7yRE3CvKt/4wE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780605364; c=relaxed/simple; bh=+e2vy5zU3nu1IPMrqBwOvvVwQTO1UvoxDGn9xFGsOMI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YFH8OMxAKi9DEhalXYj+JvsPGXvEuzvykLEY3WUJlK4mC2NvcKyFecMRlEq0IttTDDCRrzMwnF9nYKF31GKPiNbKjP/ot2/3U2Lgday3TENw1xBusY/nnXXU4OazUXCL2Ue+HjNt7MrQtFlh3sX20SqXJymTE0tjURxgwlP0MOg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HencdQ5K; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HencdQ5K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4998F1F00898; Thu, 4 Jun 2026 20:36:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1780605363; bh=bhRojyqIvVAuAQn/SyJnyO3rkyzuri5p/LOK2Hls3xk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=HencdQ5Kw0p9Ff2NnHBsWP8Acr6eL0tv5M/aH9wgEKfzYvJNVVBWhz6kWJ8yqJLTT 0qAZsNvHKYTdPvzVv0JGhTmaDRhHoTM7Qb2mKDqUgfQHljBgqDsaMtJZlOxStymUY0 sKHdp5e/6gLSXyhGJRTAGrVqxPo2eHYRCV/lYNm7OjqbQVADZ6+GAN2aNoc9LosY9D XNErpvmjiRBXqOoGiY77ISstkB6UY2vco71MI/pvQybsGia9L2Ph8Cm2AG6XaYShUa 26f2FHgXaxvdZyvAtEMifrwKWTnOElci0x7rMkhZzvxjgQoUSQo3rax2SdXh1NLnHs pbKzXvIH1a43Q== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v2 10/10] KVM: selftests: Trigger L2->L1 exits stress save+restore and #PF test Date: Thu, 4 Jun 2026 20:35:46 +0000 Message-ID: <20260604203546.365658-11-yosry@kernel.org> X-Mailer: git-send-email 2.54.0.1032.g2f8565e1d1-goog In-Reply-To: <20260604203546.365658-1-yosry@kernel.org> References: <20260604203546.365658-1-yosry@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the testing coverage in L2 by injecting a #UD into the vCPU every other iteration during restore, and intercepting #UD from L1, essentially forcing an L2 -> L1 VM-Exit directly after save+restore. With this change, the test reliably reproduces the CR2 bug fixed by commit 5c247d08bc81 ("KVM: nSVM: Use vcpu->arch.cr2 when updating vmcb12 on nested #VMEXIT") -- at least on Milan, Genoa, and Turin CPUs. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Yosry Ahmed --- .../kvm/x86/stress_save_restore_pf_test.c | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c = b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c index c285ef093400d..6aae34cf8f13f 100644 --- a/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c +++ b/tools/testing/selftests/kvm/x86/stress_save_restore_pf_test.c @@ -110,8 +110,12 @@ static void l1_svm_code(struct svm_test_data *svm) =20 generic_svm_setup(svm, guest_access_memory, &l2_guest_stack[L2_GUEST_STAC= K_SIZE]); =20 - run_guest(svm->vmcb, svm->vmcb_gpa); - GUEST_ASSERT(false); + svm->vmcb->control.intercept_exceptions |=3D BIT(UD_VECTOR); + + while (1) { + run_guest(svm->vmcb, svm->vmcb_gpa); + GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, (SVM_EXIT_EXCP_BASE + UD_V= ECTOR)); + } } =20 static void l1_vmx_code(struct vmx_pages *vmx) @@ -122,13 +126,17 @@ static void l1_vmx_code(struct vmx_pages *vmx) GUEST_ASSERT(load_vmcs(vmx)); prepare_vmcs(vmx, guest_access_memory, &l2_guest_stack[L2_GUEST_STACK_SIZ= E]); =20 - /* Ignore any #PF */ - GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, BIT(PF_VECTOR))); + /* Intercept UD, ignore any #PF */ + GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, BIT(UD_VECTOR) | BIT(PF_VECTOR))); GUEST_ASSERT(!vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0)); GUEST_ASSERT(!vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, -1)); =20 GUEST_ASSERT(!vmlaunch()); - GUEST_ASSERT(false); + while (1) { + GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_EXCEPTION_NMI); + GUEST_ASSERT_EQ(vmreadz(VM_EXIT_INTR_INFO) & 0xff, UD_VECTOR); + GUEST_ASSERT(!vmresume()); + } } =20 static void l1_guest_code(void *test_data) @@ -166,6 +174,24 @@ static void vcpu_sigusr_ignore(void) sigaction(SIGUSR1, &sa, NULL); } =20 +static bool vcpu_state_is_guest_mode(struct kvm_x86_state *state) +{ + return !!(state->nested.flags & KVM_STATE_NESTED_GUEST_MODE); +} + +static void vcpu_state_inject_ud(struct kvm_x86_state *state) +{ + if (state->events.exception.pending || state->events.exception.injected) + return; + + state->events.flags |=3D KVM_VCPUEVENT_VALID_PAYLOAD; + state->events.exception.pending =3D true; + state->events.exception.injected =3D false; + state->events.exception.nr =3D UD_VECTOR; + state->events.exception.has_error_code =3D false; + state->events.exception_has_payload =3D false; +} + static bool parse_args_nested(int argc, char *argv[]) { bool nested =3D false; @@ -199,10 +225,13 @@ int main(int argc, char *argv[]) gva_t gva; u64 pte; =20 + TEST_REQUIRE(kvm_has_cap(KVM_CAP_EXCEPTION_PAYLOAD)); + nested =3D parse_args_nested(argc, argv); =20 vm =3D vm_create_with_one_vcpu(&vcpu, nested ? l1_guest_code : guest_acce= ss_memory); vm_install_exception_handler(vm, PF_VECTOR, guest_pf_handler); + vm_enable_cap(vm, KVM_CAP_EXCEPTION_PAYLOAD, -2ul); =20 if (nested) { TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM) || kvm_cpu_has(X86_FEATURE_VMX= )); @@ -277,8 +306,16 @@ int main(int argc, char *argv[]) =20 state =3D vcpu_save_state(vcpu); =20 + /* + * If the vCPU is in guest mode, inject a #UD to trigger an + * L2->L1 VM-Exit every other iteration. + */ + if (nested && vcpu_state_is_guest_mode(state) && count % 2 =3D=3D 0) + vcpu_state_inject_ud(state); + kvm_vm_release(vm); vcpu =3D vm_recreate_with_one_vcpu(vm); + vm_enable_cap(vm, KVM_CAP_EXCEPTION_PAYLOAD, -2ul); vcpu_load_state(vcpu, state); kvm_x86_state_cleanup(state); =20 --=20 2.54.0.1032.g2f8565e1d1-goog