All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, Sean Christopherson <seanjc@google.com>,
	 Mathias Krause <minipli@grsecurity.net>,
	Andrew Jones <andrew.jones@linux.dev>
Subject: [kvm-unit-tests PATCH v3 04/20] x86: Dedup guest/host context switch of registers across SVM and VMX
Date: Thu, 14 May 2026 14:04:44 -0700	[thread overview]
Message-ID: <20260514210500.1626871-5-seanjc@google.com> (raw)
In-Reply-To: <20260514210500.1626871-1-seanjc@google.com>

Deduplicate the context switching of registers across VM-Enter<=>VM-Exit
between SVM and VMX.  The required functionality and implementations are
practically identical, literally the only difference is that SVM doesn't
need (or want) to manually swap RAX as SVM automatically swaps RAX at
VMRUN and #VMEXIT.

Opportunistically rename the structure to "guest_regs" to clarify its
purpose, and to avoid conflicts, e.g. with realmode's "struct regs".

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 lib/x86/virt.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 x86/svm.c      |  4 ++--
 x86/svm.h      | 47 ++++-----------------------------------------
 x86/vmx.c      |  8 ++++----
 x86/vmx.h      | 42 +---------------------------------------
 5 files changed, 63 insertions(+), 90 deletions(-)
 create mode 100644 lib/x86/virt.h

diff --git a/lib/x86/virt.h b/lib/x86/virt.h
new file mode 100644
index 00000000..ccc90c25
--- /dev/null
+++ b/lib/x86/virt.h
@@ -0,0 +1,52 @@
+#ifndef _x86_VIRT_H_
+#define _x86_VIRT_H_
+
+#include "libcflat.h"
+
+struct guest_regs {
+	u64 rax;
+	u64 rcx;
+	u64 rdx;
+	u64 rbx;
+	/*
+	 * Use RSP's index to hold CR3, as RSP isn't manually context switched
+	 * by software in any relevant flows.
+	 */
+	u64 cr2;
+	u64 rbp;
+	u64 rsi;
+	u64 rdi;
+	u64 r8;
+	u64 r9;
+	u64 r10;
+	u64 r11;
+	u64 r12;
+	u64 r13;
+	u64 r14;
+	u64 r15;
+	u64 rflags;
+};
+
+extern struct guest_regs regs;
+
+#define __SWAP_GPRS			\
+	"xchg %%rcx, regs+0x8\n\t"	\
+	"xchg %%rdx, regs+0x10\n\t"	\
+	"xchg %%rbx, regs+0x18\n\t"	\
+	"xchg %%rbp, regs+0x28\n\t"	\
+	"xchg %%rsi, regs+0x30\n\t"	\
+	"xchg %%rdi, regs+0x38\n\t"	\
+	"xchg %%r8, regs+0x40\n\t"	\
+	"xchg %%r9, regs+0x48\n\t"	\
+	"xchg %%r10, regs+0x50\n\t"	\
+	"xchg %%r11, regs+0x58\n\t"	\
+	"xchg %%r12, regs+0x60\n\t"	\
+	"xchg %%r13, regs+0x68\n\t"	\
+	"xchg %%r14, regs+0x70\n\t"	\
+	"xchg %%r15, regs+0x78\n\t"
+
+#define SWAP_GPRS			\
+	"xchg %%rax, regs+0x0\n\t"	\
+	__SWAP_GPRS
+
+#endif /* _x86_VIRT_H_ */
\ No newline at end of file
diff --git a/x86/svm.c b/x86/svm.c
index 941e0784..893b3f49 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -223,9 +223,9 @@ void vmcb_ident(struct vmcb *vmcb)
 	}
 }
 
-struct regs regs;
+struct guest_regs regs;
 
-struct regs get_regs(void)
+struct guest_regs get_regs(void)
 {
 	return regs;
 }
diff --git a/x86/svm.h b/x86/svm.h
index d9f7c731..a9e15f67 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -2,6 +2,7 @@
 #define X86_SVM_H
 
 #include "libcflat.h"
+#include "virt.h"
 
 enum {
 	INTERCEPT_INTR,
@@ -390,26 +391,6 @@ struct svm_test {
 	bool on_vcpu_done;
 };
 
-struct regs {
-	u64 rax;
-	u64 rcx;
-	u64 rdx;
-	u64 rbx;
-	u64 cr2;
-	u64 rbp;
-	u64 rsi;
-	u64 rdi;
-	u64 r8;
-	u64 r9;
-	u64 r10;
-	u64 r11;
-	u64 r12;
-	u64 r13;
-	u64 r14;
-	u64 r15;
-	u64 rflags;
-};
-
 typedef void (*test_guest_func)(struct svm_test *);
 
 int run_svm_tests(int ac, char **av, struct svm_test *svm_tests);
@@ -435,7 +416,7 @@ int get_test_stage(struct svm_test *test);
 void set_test_stage(struct svm_test *test, int s);
 void inc_test_stage(struct svm_test *test);
 void vmcb_ident(struct vmcb *vmcb);
-struct regs get_regs(void);
+struct guest_regs get_regs(void);
 void vmmcall(void);
 void svm_setup_vmrun(u64 rip);
 u64 __svm_vmrun(u64 rip);
@@ -454,36 +435,16 @@ static inline void clgi(void)
     asm volatile ("clgi");
 }
 
-
-
-#define SAVE_GPR_C                              \
-        "xchg %%rcx, regs+0x8\n\t"              \
-        "xchg %%rdx, regs+0x10\n\t"             \
-        "xchg %%rbx, regs+0x18\n\t"             \
-        "xchg %%rbp, regs+0x28\n\t"             \
-        "xchg %%rsi, regs+0x30\n\t"             \
-        "xchg %%rdi, regs+0x38\n\t"             \
-        "xchg %%r8, regs+0x40\n\t"              \
-        "xchg %%r9, regs+0x48\n\t"              \
-        "xchg %%r10, regs+0x50\n\t"             \
-        "xchg %%r11, regs+0x58\n\t"             \
-        "xchg %%r12, regs+0x60\n\t"             \
-        "xchg %%r13, regs+0x68\n\t"             \
-        "xchg %%r14, regs+0x70\n\t"             \
-        "xchg %%r15, regs+0x78\n\t"
-
-#define LOAD_GPR_C      SAVE_GPR_C
-
 #define ASM_PRE_VMRUN_CMD                       \
                 "vmload %%rax\n\t"              \
                 "mov regs+0x80, %%r15\n\t"      \
                 "mov %%r15, 0x170(%%rax)\n\t"   \
                 "mov regs, %%r15\n\t"           \
                 "mov %%r15, 0x1f8(%%rax)\n\t"   \
-                LOAD_GPR_C                      \
+                __SWAP_GPRS                     \
 
 #define ASM_POST_VMRUN_CMD                      \
-                SAVE_GPR_C                      \
+                __SWAP_GPRS                     \
                 "mov 0x170(%%rax), %%r15\n\t"   \
                 "mov %%r15, regs+0x80\n\t"      \
                 "mov 0x1f8(%%rax), %%r15\n\t"   \
diff --git a/x86/vmx.c b/x86/vmx.c
index 44ee3697..603730c2 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -44,7 +44,7 @@ struct vmcs *vmcs_root;
 u32 vpid_cnt;
 u64 guest_stack_top;
 u32 ctrl_pin, ctrl_enter, ctrl_exit, ctrl_cpu[2];
-struct regs regs;
+struct guest_regs regs;
 
 struct vmx_test *current;
 
@@ -1732,7 +1732,7 @@ static noinline void vmx_enter_guest(struct vmentry_result *result)
 	asm volatile (
 		"mov %[HOST_RSP], %%rdi\n\t"
 		"vmwrite %%rsp, %%rdi\n\t"
-		LOAD_GPR_C
+		SWAP_GPRS
 		"cmpb $0, %[launched]\n\t"
 		"jne 1f\n\t"
 		"vmlaunch\n\t"
@@ -1740,14 +1740,14 @@ static noinline void vmx_enter_guest(struct vmentry_result *result)
 		"1: "
 		"vmresume\n\t"
 		"2: "
-		SAVE_GPR_C
+		SWAP_GPRS
 		"pushf\n\t"
 		"pop %%rdi\n\t"
 		"mov %%rdi, %[vm_fail_flags]\n\t"
 		"movl $1, %[vm_fail]\n\t"
 		"jmp 3f\n\t"
 		"vmx_return:\n\t"
-		SAVE_GPR_C
+		SWAP_GPRS
 		"3: \n\t"
 		: [vm_fail]"+m"(result->vm_fail),
 		  [vm_fail_flags]"=m"(result->flags)
diff --git a/x86/vmx.h b/x86/vmx.h
index 425b1c43..56f37633 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -5,6 +5,7 @@
 #include "processor.h"
 #include "bitops.h"
 #include "util.h"
+#include "virt.h"
 #include "asm/page.h"
 #include "asm/io.h"
 
@@ -58,26 +59,6 @@ struct invvpid_operand {
 	u64 gla;
 };
 
-struct regs {
-	u64 rax;
-	u64 rcx;
-	u64 rdx;
-	u64 rbx;
-	u64 cr2;
-	u64 rbp;
-	u64 rsi;
-	u64 rdi;
-	u64 r8;
-	u64 r9;
-	u64 r10;
-	u64 r11;
-	u64 r12;
-	u64 r13;
-	u64 r14;
-	u64 r15;
-	u64 rflags;
-};
-
 union exit_reason {
 	struct {
 		u32	basic			: 16;
@@ -587,25 +568,6 @@ enum vm_entry_failure_code {
 	ENTRY_FAIL_VMCS_LINK_PTR	= 4,
 };
 
-#define SAVE_GPR_C				\
-	"xchg %%rax, regs\n\t"			\
-	"xchg %%rcx, regs+0x8\n\t"		\
-	"xchg %%rdx, regs+0x10\n\t"		\
-	"xchg %%rbx, regs+0x18\n\t"		\
-	"xchg %%rbp, regs+0x28\n\t"		\
-	"xchg %%rsi, regs+0x30\n\t"		\
-	"xchg %%rdi, regs+0x38\n\t"		\
-	"xchg %%r8, regs+0x40\n\t"		\
-	"xchg %%r9, regs+0x48\n\t"		\
-	"xchg %%r10, regs+0x50\n\t"		\
-	"xchg %%r11, regs+0x58\n\t"		\
-	"xchg %%r12, regs+0x60\n\t"		\
-	"xchg %%r13, regs+0x68\n\t"		\
-	"xchg %%r14, regs+0x70\n\t"		\
-	"xchg %%r15, regs+0x78\n\t"
-
-#define LOAD_GPR_C	SAVE_GPR_C
-
 #define VMX_IO_SIZE_MASK	0x7
 #define _VMX_IO_BYTE		0
 #define _VMX_IO_WORD		1
@@ -739,8 +701,6 @@ enum vm_entry_failure_code {
 #define VMCS_FIELD_RESERVED_SHIFT	(15)
 #define VMCS_FIELD_BIT_SIZE		(BITS_PER_LONG)
 
-extern struct regs regs;
-
 extern union vmx_basic_msr basic_msr;
 extern union vmx_ctrl_msr ctrl_pin_rev;
 extern union vmx_ctrl_msr ctrl_cpu_rev[2];
-- 
2.54.0.563.g4f69b47b94-goog


  parent reply	other threads:[~2026-05-14 21:05 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-14 21:04 [kvm-unit-tests PATCH v3 00/20] x86: Better backtraces for leaf functions Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 01/20] x86/vmx: Drop unused SYSENTER "support" in nested VMX infrastructure Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 02/20] x86/vmx: Drop unused guest_regs " Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 03/20] x86/svm: Sort (and swap) GPRs by their index, not alphabetically Sean Christopherson
2026-05-14 21:04 ` Sean Christopherson [this message]
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 05/20] x86/virt: Use macro shenanigans to get reg offsets when swapping guest/host regs Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 06/20] x86/virt: Track "guest regs" using per-CPU variable Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 07/20] x86/svm: Don't VMLOAD/VMSAVE "guest" state around VMRUN Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 08/20] x86/vmx: Use separate VMCSes for BSP vs. AP in INIT test Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 09/20] x86/vmx: Swap GPRs after checking "launched" status Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 10/20] x86/vmx: Track VMCS "launched" state per-CPU Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 11/20] x86/vmx: Track "is this CPU in guest mode" per-CPU Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 12/20] x86/vmx: Communicate hypercalls via RAX, not a global field Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 13/20] x86/vmx: Initialize test stage in SIPI test *before* launching AP thread Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 14/20] x86/kvmclock: Replace spaces with tabs Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 15/20] x86/kvmclock: Skip kvmclock test when not running on KVM with CLOCKSOURCE2 Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 16/20] x86/vmx: Tag "struct vmx_msr_entry" as needing to be 16-byte aligned Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 17/20] x86/smp: Align the stack to a 16-byte boundary when invoking SMP function calls Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 18/20] x86/vmx: Write to KVM's WALL_CLOCK MSR via VM-Entry load list sync in SIPI test Sean Christopherson
2026-05-14 21:04 ` [kvm-unit-tests PATCH v3 19/20] x86: Better backtraces for leaf functions Sean Christopherson
2026-05-14 21:05 ` [kvm-unit-tests PATCH v3 20/20] x86: Prevent realmode test code instrumentation with nop-mcount Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260514210500.1626871-5-seanjc@google.com \
    --to=seanjc@google.com \
    --cc=andrew.jones@linux.dev \
    --cc=kvm@vger.kernel.org \
    --cc=minipli@grsecurity.net \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.