Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com, seanjc@google.com, chang.seok.bae@intel.com
Subject: [PATCH kvm-unit-tests] x86: xsave: Add test case for emulation of APX instructions
Date: Mon, 20 Apr 2026 21:23:55 +0000	[thread overview]
Message-ID: <20260420212355.507827-1-chang.seok.bae@intel.com> (raw)
In-Reply-To: <072ad56c-24d5-425a-9faf-c1a3ba732005@redhat.com>

Add a test to validate emulation support for extended GPRs (EGPRs). APX
extends the x86 general-purpose register set with R16-R31.

The test follows the pattern established by existing AVX tests: it
performs register-to-memory and register-to-register moves across various
combinations, and cross-checks emulated execution against native results.

For convenience, make available only when built with a compiler that
supports APX. Otherwise, raw bytecode is ugly and inefficient, and
even macrofied bytecode looks to be an overkill.

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
Note:
As suggested by Paolo [1], I also think this piece of testing can go to
the KVM test tree. Additional (new) cases like testing KVM ABI and EGPR
state management will be included to the KVM series (from next revision).

[1]: https://lore.kernel.org/lkml/072ad56c-24d5-425a-9faf-c1a3ba732005@redhat.com/
---
 lib/linux/compiler.h |  5 +++
 lib/x86/processor.h  |  1 +
 x86/xsave.c          | 86 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+)

diff --git a/lib/linux/compiler.h b/lib/linux/compiler.h
index 8e62aae02b5e..e9df821d50fd 100644
--- a/lib/linux/compiler.h
+++ b/lib/linux/compiler.h
@@ -13,6 +13,11 @@
 		     + __GNUC_PATCHLEVEL__)
 
 #ifdef __clang__
+
+#define CLANG_VERSION (__clang_major__ * 10000	\
+		       + __clang_minor__ * 100	\
+		       + __clang_patchlevel__)
+
 #if __has_builtin(__builtin_add_overflow) && \
     __has_builtin(__builtin_sub_overflow) && \
     __has_builtin(__builtin_mul_overflow)
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 42dd2d2a4787..85e96741a6bf 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -198,6 +198,7 @@ static inline u64 get_non_canonical(u64 addr, u64 mask)
 #define XFEATURE_MASK_LBR		BIT_ULL(15)
 #define XFEATURE_MASK_XTILE_CFG		BIT_ULL(17)
 #define XFEATURE_MASK_XTILE_DATA	BIT_ULL(18)
+#define XFEATURE_MASK_APX		BIT_ULL(19)
 
 #define XFEATURE_MASK_FP_SSE		(XFEATURE_MASK_FP | XFEATURE_MASK_SSE)
 
diff --git a/x86/xsave.c b/x86/xsave.c
index 254f9fde6976..a1e57dea18db 100644
--- a/x86/xsave.c
+++ b/x86/xsave.c
@@ -1,6 +1,11 @@
 #include "libcflat.h"
 #include "desc.h"
 #include "processor.h"
+#include "linux/compiler.h"
+
+#if GCC_VERSION >= 140000 || CLANG_VERSION >= 180000
+#define TEST_EGPRS
+#endif
 
 char __attribute__((aligned(32))) v32_1[32];
 char __attribute__((aligned(32))) v32_2[32];
@@ -43,6 +48,78 @@ do {									\
 		__TEST_VMOVDQA(ymm##r1, ymm##r2, KVM_FEP);		\
 } while (0)
 
+#ifdef TEST_EGPRS
+
+char __attribute__((aligned(8)))  r8_1[8];
+char __attribute__((aligned(8)))  r8_2[8];
+char __attribute__((aligned(8)))  r8_3[8];
+
+static void initialize_gpr_buffers(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(r8_1); i++)
+		r8_1[i] = (char)rdtsc();
+
+	memset(r8_2, 0, sizeof(r8_2));
+	memset(r8_3, 0, sizeof(r8_3));
+}
+
+#define __TEST_MOV_GPRS(reg1, reg2, FEP)				\
+do {									\
+	asm volatile(FEP "mov r8_1(%%rip), %%" #reg1 "\n"		\
+		     FEP "mov %%" #reg1 ", %%" #reg2 "\n"		\
+		     FEP "mov %%" #reg2 ", r8_2(%%rip)\n"		\
+		     "mov %%" #reg2 ", r8_3(%%rip)\n"			\
+		     ::: "memory", #reg1, #reg2);			\
+									\
+	report(!memcmp(r8_1, r8_2, sizeof(r8_1)),			\
+	       "%s MOV using " #reg1 " and " #reg2,			\
+	       strlen(FEP) ? "Emulated" : "Native");			\
+	report(!memcmp(r8_1, r8_3, sizeof(r8_1)),			\
+	       "%s MOV using " #reg1 " and " #reg2,			\
+	       strlen(FEP) ? "Emulated+Native" : "Native");		\
+} while (0)
+
+#define TEST_MOV_GPRS(r1, r2)						\
+do {									\
+	initialize_gpr_buffers();					\
+									\
+	__TEST_MOV_GPRS(r##r1, r##r2, "");				\
+									\
+	if (is_fep_available)						\
+		__TEST_MOV_GPRS(r##r1, r##r2, KVM_FEP);			\
+} while (0)
+
+static __attribute__((target("apxf"))) void test_mov_egprs(void)
+{
+	TEST_MOV_GPRS(16, 31);
+	TEST_MOV_GPRS(17, 30);
+	TEST_MOV_GPRS(18, 29);
+	TEST_MOV_GPRS(19, 28);
+	TEST_MOV_GPRS(20, 27);
+	TEST_MOV_GPRS(21, 26);
+	TEST_MOV_GPRS(22, 25);
+	TEST_MOV_GPRS(23, 24);
+	TEST_MOV_GPRS(24, 23);
+	TEST_MOV_GPRS(25, 22);
+	TEST_MOV_GPRS(26, 21);
+	TEST_MOV_GPRS(27, 20);
+	TEST_MOV_GPRS(28, 19);
+	TEST_MOV_GPRS(29, 18);
+	TEST_MOV_GPRS(30, 17);
+	TEST_MOV_GPRS(31, 16);
+}
+
+#else
+
+static test_mov_egprs(void)
+{
+	report_skip("Skip EGPR MOV tests: compiler does not support APX");
+}
+
+#endif /* TEST_EGPRS */
+
 static void test_write_xcr0(u64 val)
 {
 	u64 xcr0_alias = rdtsc() << 32, cur;
@@ -93,6 +170,12 @@ static __attribute__((target("avx"))) void test_avx_vmovdqa(void)
 	TEST_VMOVDQA(15, 1);
 }
 
+static void test_apx(void)
+{
+	test_write_xcr0(XFEATURE_MASK_FP_SSE | XFEATURE_MASK_APX);
+	test_mov_egprs();
+}
+
 static void test_unsupported_xcrs(void)
 {
 	u64 ign;
@@ -151,6 +234,9 @@ static void test_xsave(void)
 	if (supported_xcr0 & XFEATURE_MASK_YMM)
 		test_avx_vmovdqa();
 
+	if (supported_xcr0 & XFEATURE_MASK_APX)
+		test_apx();
+
 	report(write_xcr0_safe(0) == GP_VECTOR,
 	       "Write XCR0 = 0 - expect #GP");
 
-- 
2.51.0


      reply	other threads:[~2026-04-20 21:48 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-12 23:53 [PATCH v2 00/16] KVM: x86: Enable APX for guests Chang S. Bae
2026-01-12 23:53 ` [PATCH v2 01/16] KVM: x86: Rename register accessors to be GPR-specific Chang S. Bae
2026-03-05  1:35   ` Sean Christopherson
2026-03-07  1:32     ` Chang S. Bae
2026-03-09 23:28       ` Chang S. Bae
2026-03-10  1:23       ` Sean Christopherson
2026-03-10 22:05         ` Chang S. Bae
2026-03-10 23:12           ` Sean Christopherson
2026-01-12 23:53 ` [PATCH v2 02/16] KVM: x86: Refactor GPR accessors to differentiate register access types Chang S. Bae
2026-03-05  1:49   ` Sean Christopherson
2026-03-07  1:32     ` Chang S. Bae
2026-01-12 23:53 ` [PATCH v2 03/16] KVM: x86: Implement accessors for extended GPRs Chang S. Bae
2026-03-05  1:41   ` Sean Christopherson
2026-03-07  1:32     ` Chang S. Bae
2026-01-12 23:53 ` [PATCH v2 04/16] KVM: VMX: Introduce unified instruction info structure Chang S. Bae
2026-03-05  4:21   ` Sean Christopherson
2026-03-07  1:33     ` Chang S. Bae
2026-03-13  1:05       ` Sean Christopherson
2026-01-12 23:53 ` [PATCH v2 05/16] KVM: VMX: Refactor instruction information retrieval Chang S. Bae
2026-01-12 23:53 ` [PATCH v2 06/16] KVM: VMX: Refactor GPR index retrieval from exit qualification Chang S. Bae
2026-03-05  4:13   ` Sean Christopherson
2026-01-12 23:53 ` [PATCH v2 07/16] KVM: VMX: Support extended register index in exit handling Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 08/16] KVM: nVMX: Propagate the extended instruction info field Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 09/16] KVM: emulate: Support EGPR accessing and tracking Chang S. Bae
2026-03-05  4:22   ` Sean Christopherson
2026-01-12 23:54 ` [PATCH v2 10/16] KVM: emulate: Handle EGPR index and REX2-incompatible opcodes Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 11/16] KVM: emulate: Support REX2-prefixed opcode decode Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 12/16] KVM: emulate: Reject EVEX-prefixed instructions Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 13/16] KVM: x86: Guard valid XCR0.APX settings Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 14/16] KVM: x86: Expose APX foundational feature bit to guests Chang S. Bae
2026-01-19  5:55   ` Xiaoyao Li
2026-01-20 18:07     ` Edgecombe, Rick P
2026-01-20 20:50       ` Chang S. Bae
2026-01-21 19:59         ` Edgecombe, Rick P
2026-01-12 23:54 ` [PATCH v2 15/16] KVM: x86: Expose APX sub-features " Chang S. Bae
2026-01-12 23:54 ` [PATCH v2 16/16] KVM: x86: selftests: Add APX state handling and XCR0 sanity checks Chang S. Bae
2026-03-05  4:28   ` Sean Christopherson
2026-03-07  1:33     ` Chang S. Bae
2026-03-11 18:42       ` Paolo Bonzini
2026-04-20 21:23         ` Chang S. Bae [this message]

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=20260420212355.507827-1-chang.seok.bae@intel.com \
    --to=chang.seok.bae@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox