Kernel KVM virtualization development
 help / color / mirror / Atom feed
* [PATCH v3 0/2] KVM: LoongArch: selftests: Add FPU test case
@ 2026-06-16  2:26 Bibo Mao
  2026-06-16  2:26 ` [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method Bibo Mao
  2026-06-16  2:26 ` [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
  0 siblings, 2 replies; 5+ messages in thread
From: Bibo Mao @ 2026-06-16  2:26 UTC (permalink / raw)
  To: Huacai Chen; +Cc: kvm, loongarch, linux-kernel, linux-kselftest

Here add FPU test case and verify FPU register get and set APIs, the
FPU width supports 64/128/256 bits. It is important for VM migration.
---
v2 ... v3:
  1. Remove __vm_has_feature() and use __kvm_has_device_attr() directly
     when checking LSX/LASX feature in patch 2.

v1 ... v2:
  1. Replace hardcode value with CSR_EUEN_XXX when enable FPU access.
  2. Add attribute __aligned(64) with kvm_fpureg variable with better FPU
     save and restore.
  3. Add clobber $f0 register with inline assemble language with
     fld.d/vld/xvld instruction.
  4. Add fallthrough between UCALL_DONE and UCALL_SYNC switch case
     sentences.
  5. Remove sync_global_from_guest() between vcpu_fpu_get() ioctl test
     case, since the buffer is not modified with such instructions
     fld.d/vld/xvld.
  6. Modify FPU register with random value rather than plus 0x10, and
     random() is replaced with value 0x10.
---
Bibo Mao (2):
  KVM: LoongArch: selftests: Enable LASX feature by auto detect method
  KVM: LoongArch: selftests: Add FPU test case

 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../kvm/include/loongarch/processor.h         |  18 +++
 .../selftests/kvm/lib/loongarch/processor.c   |  12 +-
 .../selftests/kvm/loongarch/fpu_test.c        | 138 ++++++++++++++++++
 4 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/kvm/loongarch/fpu_test.c


base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
-- 
2.39.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method
  2026-06-16  2:26 [PATCH v3 0/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
@ 2026-06-16  2:26 ` Bibo Mao
  2026-06-16  2:39   ` sashiko-bot
  2026-06-16  2:26 ` [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
  1 sibling, 1 reply; 5+ messages in thread
From: Bibo Mao @ 2026-06-16  2:26 UTC (permalink / raw)
  To: Huacai Chen; +Cc: kvm, loongarch, linux-kernel, linux-kselftest

Add LSX and LASX features when VM is created. These features are detected
firstly, enable it if it is available on host machine.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 .../selftests/kvm/include/loongarch/processor.h      | 10 ++++++++++
 .../testing/selftests/kvm/lib/loongarch/processor.c  | 12 +++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
index 93dc1fbd2e79..2324e311180f 100644
--- a/tools/testing/selftests/kvm/include/loongarch/processor.h
+++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
@@ -131,6 +131,16 @@
 #define  CSR_TLBREHI_PS_SHIFT		0
 #define  CSR_TLBREHI_PS			(0x3fUL << CSR_TLBREHI_PS_SHIFT)
 
+#define LOONGARCH_CPUCFG2		0x2
+#define  CPUCFG2_FP			BIT(0)
+#define  CPUCFG2_FPSP			BIT(1)
+#define  CPUCFG2_FPDP			BIT(2)
+#define  CPUCFG2_FPVERS			GENMASK(5, 3)
+#define  CPUCFG2_LSX			BIT(6)
+#define  CPUCFG2_LASX			BIT(7)
+#define  CPUCFG2_LLFTP			BIT(14)
+#define  CPUCFG2_LLFTPREV		GENMASK(17, 15)
+
 #define read_cpucfg(reg)			\
 ({						\
 	register unsigned long __v;		\
diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
index 64d91fb76522..e7fb54d746f4 100644
--- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
+++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
@@ -278,7 +278,7 @@ static void loongarch_set_csr(struct kvm_vcpu *vcpu, u64 id, u64 val)
 
 void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	int width;
+	int width, ret;
 	unsigned int cfg;
 	unsigned long val;
 	struct kvm_vm *vm = vcpu->vm;
@@ -292,6 +292,16 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
 		TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
 	}
 
+	/* Enable LSX/LASX feature by detecting host capability */
+	cfg = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | CPUCFG2_LLFTP;
+	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LSX);
+	if (!ret)
+		cfg |= CPUCFG2_LSX;
+
+	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
+	if (!ret)
+		cfg |= CPUCFG2_LASX;
+	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG2, cfg);
 	cfg = read_cpucfg(LOONGARCH_CPUCFG6);
 	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG6, cfg);
 
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case
  2026-06-16  2:26 [PATCH v3 0/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
  2026-06-16  2:26 ` [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method Bibo Mao
@ 2026-06-16  2:26 ` Bibo Mao
  2026-06-16  2:34   ` sashiko-bot
  1 sibling, 1 reply; 5+ messages in thread
From: Bibo Mao @ 2026-06-16  2:26 UTC (permalink / raw)
  To: Huacai Chen; +Cc: kvm, loongarch, linux-kernel, linux-kselftest

Add FPU test case and verify FPU register get and set APIs, the
FPU width supports 64/128/256 bits.

Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
 tools/testing/selftests/kvm/Makefile.kvm      |   1 +
 .../kvm/include/loongarch/processor.h         |   8 +
 .../selftests/kvm/loongarch/fpu_test.c        | 138 ++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/loongarch/fpu_test.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 9118a5a51b89..7d11592b3759 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -224,6 +224,7 @@ TEST_GEN_PROGS_riscv += rseq_test
 TEST_GEN_PROGS_riscv += steal_time
 
 TEST_GEN_PROGS_loongarch = loongarch/pmu_test
+TEST_GEN_PROGS_loongarch += loongarch/fpu_test
 TEST_GEN_PROGS_loongarch += arch_timer
 TEST_GEN_PROGS_loongarch += coalesced_io_test
 TEST_GEN_PROGS_loongarch += demand_paging_test
diff --git a/tools/testing/selftests/kvm/include/loongarch/processor.h b/tools/testing/selftests/kvm/include/loongarch/processor.h
index 2324e311180f..981ae7078354 100644
--- a/tools/testing/selftests/kvm/include/loongarch/processor.h
+++ b/tools/testing/selftests/kvm/include/loongarch/processor.h
@@ -82,6 +82,14 @@
 #define  PLV_MASK			0x3
 #define LOONGARCH_CSR_PRMD		0x1
 #define LOONGARCH_CSR_EUEN		0x2
+#define  CSR_EUEN_LBTEN_SHIFT		3
+#define  CSR_EUEN_LBTEN			BIT_ULL(CSR_EUEN_LBTEN_SHIFT)
+#define  CSR_EUEN_LASXEN_SHIFT		2
+#define  CSR_EUEN_LASXEN		BIT_ULL(CSR_EUEN_LASXEN_SHIFT)
+#define  CSR_EUEN_LSXEN_SHIFT		1
+#define  CSR_EUEN_LSXEN			BIT_ULL(CSR_EUEN_LSXEN_SHIFT)
+#define  CSR_EUEN_FPEN_SHIFT		0
+#define  CSR_EUEN_FPEN			BIT_ULL(CSR_EUEN_FPEN_SHIFT)
 #define LOONGARCH_CSR_ECFG		0x4
 #define  ECFGB_PMU			10
 #define  ECFGF_PMU			(BIT_ULL(ECFGB_PMU))
diff --git a/tools/testing/selftests/kvm/loongarch/fpu_test.c b/tools/testing/selftests/kvm/loongarch/fpu_test.c
new file mode 100644
index 000000000000..fe58ed4f93c0
--- /dev/null
+++ b/tools/testing/selftests/kvm/loongarch/fpu_test.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <stdio.h>
+#include <string.h>
+#include "kvm_util.h"
+#include "processor.h"
+#include "loongarch/processor.h"
+
+struct kvm_fpureg __aligned(64) vector = {{1, 2, 3, 4 }};
+
+static void guest_code(void)
+{
+	unsigned long val;
+	struct kvm_fpureg *fp = &vector;
+
+	val = csr_read(LOONGARCH_CSR_EUEN);
+	val |= CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN;
+	csr_write(val, LOONGARCH_CSR_EUEN);
+
+	__asm__ __volatile__("fld.d $f0, %0, 0\n" : : "r"(fp) : "$f0");
+	GUEST_SYNC(0);
+
+	__asm__ __volatile__("vld $vr0, %0, 0\n" : : "r"(fp) : "$vr0");
+	GUEST_SYNC(1);
+
+	__asm__ __volatile__("xvld $xr0, %0, 0\n" : : "r"(fp) : "$xr0");
+	GUEST_SYNC(2);
+
+	__asm__ __volatile__("fst.d $f0, %0, 0\n" : : "r"(fp) : "memory");
+	GUEST_SYNC(3);
+
+	__asm__ __volatile__("vst $vr0, %0, 0\n" : : "r"(fp) : "memory");
+	GUEST_SYNC(4);
+
+	__asm__ __volatile__("xvst $xr0, %0, 0\n" : : "r"(fp) : "memory");
+	GUEST_SYNC(5);
+
+	GUEST_DONE();
+}
+
+static void run_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct ucall uc;
+	int cont;
+
+	cont = 1;
+	while (cont) {
+		vcpu_run(vcpu);
+
+		switch (get_ucall(vcpu, &uc)) {
+		case UCALL_PRINTF:
+			printf("%s", (const char *)uc.buffer);
+			break;
+		case UCALL_DONE:
+			printf("FPU test PASSED\n");
+			fallthrough;
+		case UCALL_SYNC:
+			cont = 0;
+			break;
+		case UCALL_ABORT:
+			REPORT_GUEST_ASSERT(uc);
+		default:
+			TEST_ASSERT(false, "Unexpected exit: %s",
+				exit_reason_str(vcpu->run->exit_reason));
+		}
+	}
+}
+
+int main(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+	struct kvm_fpu fpu;
+	struct kvm_fpureg *fp = &vector;
+	int ret;
+
+	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LSX);
+	__TEST_REQUIRE(!ret, "LSX not available, skipping test\n");
+
+	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
+	__TEST_REQUIRE(!ret, "LASX not available, skipping test\n");
+
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 8), "Wanted 0x%llx from f0, got 0x%llx",
+			fp->val64[0], fpu.fpr[0].val64[0]);
+
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 16), "Wanted 0x%llx %llx from vr0, got 0x%llx %llx",
+			fp->val64[0], fp->val64[1],
+			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1]);
+
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 32),
+			"Wanted 0x%llx %llx %llx %llx from xr0, got 0x%llx %llx %llx %llx",
+			fp->val64[0], fp->val64[1], fp->val64[2], fp->val64[3],
+			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1],
+			fpu.fpr[0].val64[2], fpu.fpr[0].val64[3]);
+
+	fpu.fpr[0].val64[0] += random();
+	vcpu_fpu_set(vcpu, &fpu);
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	sync_global_from_guest(vm, *fp);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 8), "Wanted 0x%llx from f0, got 0x%llx",
+			fp->val64[0], fpu.fpr[0].val64[0]);
+
+	fpu.fpr[0].val64[0] += random();
+	fpu.fpr[0].val64[1] += random();
+	vcpu_fpu_set(vcpu, &fpu);
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	sync_global_from_guest(vm, *fp);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 16), "Wanted 0x%llx %llx from vr0, got 0x%llx %llx",
+			fp->val64[0], fp->val64[1],
+			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1]);
+
+	fpu.fpr[0].val64[0] += random();
+	fpu.fpr[0].val64[1] += random();
+	fpu.fpr[0].val64[2] += random();
+	fpu.fpr[0].val64[3] += random();
+	vcpu_fpu_set(vcpu, &fpu);
+	run_vcpu(vcpu);
+	vcpu_fpu_get(vcpu, &fpu);
+	sync_global_from_guest(vm, *fp);
+	TEST_ASSERT(!memcmp(fpu.fpr, fp, 32),
+			"Wanted 0x%llx %llx %llx %llx from xr0, got 0x%llx %llx %llx %llx",
+			fp->val64[0], fp->val64[1], fp->val64[2], fp->val64[3],
+			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1],
+			fpu.fpr[0].val64[2], fpu.fpr[0].val64[3]);
+
+	run_vcpu(vcpu);
+	kvm_vm_free(vm);
+	return 0;
+}
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case
  2026-06-16  2:26 ` [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
@ 2026-06-16  2:34   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-16  2:34 UTC (permalink / raw)
  To: Bibo Mao; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] FPU selftest fails to verify that `vcpu_fpu_set` actually modifies the vCPU FPU state.
--

commit 2bf4caa3158a9fa987285bf7aea2092fe7c8a3f7
Author: Bibo Mao <maobibo@loongson.cn>

KVM: LoongArch: selftests: Add FPU test case

This commit adds an FPU test case to verify FPU register get and set APIs
for LoongArch. It supports testing 64, 128, and 256-bit FPU widths.

> diff --git a/tools/testing/selftests/kvm/loongarch/fpu_test.c b/tools/testing/selftests/kvm/loongarch/fpu_test.c
> new file mode 100644
> index 0000000000000..fe58ed4f93c0b
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/loongarch/fpu_test.c

[ ... ]

> +int main(void)
> +{

[ ... ]

> +	fpu.fpr[0].val64[0] += random();
> +	vcpu_fpu_set(vcpu, &fpu);
> +	run_vcpu(vcpu);
> +	vcpu_fpu_get(vcpu, &fpu);
> +	sync_global_from_guest(vm, *fp);
> +	TEST_ASSERT(!memcmp(fpu.fpr, fp, 8), "Wanted 0x%llx from f0, got 0x%llx",
> +			fp->val64[0], fpu.fpr[0].val64[0]);

[Severity: Medium]
Does this sequence actually verify the set operation? 

The test adds random() to the fpu structure and calls vcpu_fpu_set(). However,
it then updates both the fpu structure via vcpu_fpu_get() and the fp structure
via sync_global_from_guest() before comparing them against each other.

If vcpu_fpu_set() silently fails or does nothing, won't both structures just
read back the previous, unmodified state and cause the memcmp() to pass anyway?
It looks like this pattern repeats for the 128-bit and 256-bit checks below as
well.

> +
> +	fpu.fpr[0].val64[0] += random();
> +	fpu.fpr[0].val64[1] += random();
> +	vcpu_fpu_set(vcpu, &fpu);
> +	run_vcpu(vcpu);
> +	vcpu_fpu_get(vcpu, &fpu);
> +	sync_global_from_guest(vm, *fp);
> +	TEST_ASSERT(!memcmp(fpu.fpr, fp, 16), "Wanted 0x%llx %llx from vr0, got 0x%llx %llx",
> +			fp->val64[0], fp->val64[1],
> +			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1]);

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616022615.2141072-1-maobibo@loongson.cn?part=2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method
  2026-06-16  2:26 ` [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method Bibo Mao
@ 2026-06-16  2:39   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-16  2:39 UTC (permalink / raw)
  To: Bibo Mao; +Cc: kvm

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Hardcoding the base CPUCFG2 value silently clears FPU version, LLFTP revision, and other default KVM features.
--

commit 7ccc915fb84c033373faa2df43f4b5551f11c4d3
Author: Bibo Mao <maobibo@loongson.cn>

KVM: LoongArch: selftests: Enable LASX feature by auto detect method

This commit enables LSX and LASX features for LoongArch KVM selftests when
the host machine supports them.

> diff --git a/tools/testing/selftests/kvm/lib/loongarch/processor.c b/tools/testing/selftests/kvm/lib/loongarch/processor.c
> index 64d91fb76522d..e7fb54d746f45 100644
> --- a/tools/testing/selftests/kvm/lib/loongarch/processor.c
> +++ b/tools/testing/selftests/kvm/lib/loongarch/processor.c
[ ... ]
> @@ -292,6 +292,16 @@ void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
>  		TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
>  	}
>  
> +	/* Enable LSX/LASX feature by detecting host capability */
> +	cfg = CPUCFG2_FP | CPUCFG2_FPSP | CPUCFG2_FPDP | CPUCFG2_LLFTP;
> +	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LSX);
> +	if (!ret)
> +		cfg |= CPUCFG2_LSX;
> +
> +	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
> +	if (!ret)
> +		cfg |= CPUCFG2_LASX;
> +	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG2, cfg);

[Severity: Medium]
Does hardcoding the base CPUCFG2 value here inadvertently clear other default
KVM features?

Since KVM populates CPUCFG2 with defaults like CPUCFG2_FPVERS (FPU version)
and CPUCFG2_LLFTPREV (LLFTP revision) during vCPU creation, overwriting the
entire register with this bitmask might cause issues for tests or guests
relying on these standard properties.

Would it be better to read the existing KVM-provided value via vcpu_get_reg(),
bitwise-OR the detected LSX and LASX bits, and then write it back?

>  	cfg = read_cpucfg(LOONGARCH_CPUCFG6);
>  	loongarch_set_cpucfg(vcpu, LOONGARCH_CPUCFG6, cfg);
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260616022615.2141072-1-maobibo@loongson.cn?part=1

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-16  2:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-16  2:26 [PATCH v3 0/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
2026-06-16  2:26 ` [PATCH v3 1/2] KVM: LoongArch: selftests: Enable LASX feature by auto detect method Bibo Mao
2026-06-16  2:39   ` sashiko-bot
2026-06-16  2:26 ` [PATCH v3 2/2] KVM: LoongArch: selftests: Add FPU test case Bibo Mao
2026-06-16  2:34   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox