xref: /linux/tools/testing/selftests/kvm/loongarch/fpu_test.c (revision 7bb6284aa7b3c369b41e7f33fcbe193161f008e7)
1*c5959723SBibo Mao // SPDX-License-Identifier: GPL-2.0
2*c5959723SBibo Mao 
3*c5959723SBibo Mao #include <stdio.h>
4*c5959723SBibo Mao #include <string.h>
5*c5959723SBibo Mao #include "kvm_util.h"
6*c5959723SBibo Mao #include "processor.h"
7*c5959723SBibo Mao #include "loongarch/processor.h"
8*c5959723SBibo Mao 
9*c5959723SBibo Mao struct kvm_fpureg __aligned(64) vector = {{1, 2, 3, 4 }};
10*c5959723SBibo Mao 
11*c5959723SBibo Mao static void guest_code(void)
12*c5959723SBibo Mao {
13*c5959723SBibo Mao 	unsigned long val;
14*c5959723SBibo Mao 	struct kvm_fpureg *fp = &vector;
15*c5959723SBibo Mao 
16*c5959723SBibo Mao 	val = csr_read(LOONGARCH_CSR_EUEN);
17*c5959723SBibo Mao 	val |= CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN;
18*c5959723SBibo Mao 	csr_write(val, LOONGARCH_CSR_EUEN);
19*c5959723SBibo Mao 
20*c5959723SBibo Mao 	__asm__ __volatile__("fld.d $f0, %0, 0\n" : : "r"(fp) : "$f0");
21*c5959723SBibo Mao 	GUEST_SYNC(0);
22*c5959723SBibo Mao 
23*c5959723SBibo Mao 	__asm__ __volatile__("vld $vr0, %0, 0\n" : : "r"(fp) : "$vr0");
24*c5959723SBibo Mao 	GUEST_SYNC(1);
25*c5959723SBibo Mao 
26*c5959723SBibo Mao 	__asm__ __volatile__("xvld $xr0, %0, 0\n" : : "r"(fp) : "$xr0");
27*c5959723SBibo Mao 	GUEST_SYNC(2);
28*c5959723SBibo Mao 
29*c5959723SBibo Mao 	__asm__ __volatile__("fst.d $f0, %0, 0\n" : : "r"(fp) : "memory");
30*c5959723SBibo Mao 	GUEST_SYNC(3);
31*c5959723SBibo Mao 
32*c5959723SBibo Mao 	__asm__ __volatile__("vst $vr0, %0, 0\n" : : "r"(fp) : "memory");
33*c5959723SBibo Mao 	GUEST_SYNC(4);
34*c5959723SBibo Mao 
35*c5959723SBibo Mao 	__asm__ __volatile__("xvst $xr0, %0, 0\n" : : "r"(fp) : "memory");
36*c5959723SBibo Mao 	GUEST_SYNC(5);
37*c5959723SBibo Mao 
38*c5959723SBibo Mao 	GUEST_DONE();
39*c5959723SBibo Mao }
40*c5959723SBibo Mao 
41*c5959723SBibo Mao static void run_vcpu(struct kvm_vcpu *vcpu)
42*c5959723SBibo Mao {
43*c5959723SBibo Mao 	int cont = 1;
44*c5959723SBibo Mao 	struct ucall uc;
45*c5959723SBibo Mao 
46*c5959723SBibo Mao 	while (cont) {
47*c5959723SBibo Mao 		vcpu_run(vcpu);
48*c5959723SBibo Mao 
49*c5959723SBibo Mao 		switch (get_ucall(vcpu, &uc)) {
50*c5959723SBibo Mao 		case UCALL_PRINTF:
51*c5959723SBibo Mao 			printf("%s", (const char *)uc.buffer);
52*c5959723SBibo Mao 			break;
53*c5959723SBibo Mao 		case UCALL_DONE:
54*c5959723SBibo Mao 			printf("FPU test PASSED\n");
55*c5959723SBibo Mao 			fallthrough;
56*c5959723SBibo Mao 		case UCALL_SYNC:
57*c5959723SBibo Mao 			cont = 0;
58*c5959723SBibo Mao 			break;
59*c5959723SBibo Mao 		case UCALL_ABORT:
60*c5959723SBibo Mao 			REPORT_GUEST_ASSERT(uc);
61*c5959723SBibo Mao 		default:
62*c5959723SBibo Mao 			TEST_ASSERT(false, "Unexpected exit: %s",
63*c5959723SBibo Mao 				exit_reason_str(vcpu->run->exit_reason));
64*c5959723SBibo Mao 		}
65*c5959723SBibo Mao 	}
66*c5959723SBibo Mao }
67*c5959723SBibo Mao 
68*c5959723SBibo Mao int main(void)
69*c5959723SBibo Mao {
70*c5959723SBibo Mao 	int ret;
71*c5959723SBibo Mao 	struct kvm_vm *vm;
72*c5959723SBibo Mao 	struct kvm_vcpu *vcpu;
73*c5959723SBibo Mao 	struct kvm_fpu fpu;
74*c5959723SBibo Mao 	struct kvm_fpureg *fp = &vector;
75*c5959723SBibo Mao 
76*c5959723SBibo Mao 	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
77*c5959723SBibo Mao 
78*c5959723SBibo Mao 	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LSX);
79*c5959723SBibo Mao 	__TEST_REQUIRE(!ret, "LSX not available, skipping test\n");
80*c5959723SBibo Mao 
81*c5959723SBibo Mao 	ret = __kvm_has_device_attr(vm->fd, KVM_LOONGARCH_VM_FEAT_CTRL, KVM_LOONGARCH_VM_FEAT_LASX);
82*c5959723SBibo Mao 	__TEST_REQUIRE(!ret, "LASX not available, skipping test\n");
83*c5959723SBibo Mao 
84*c5959723SBibo Mao 	run_vcpu(vcpu);
85*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
86*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 8), "Wanted 0x%llx from f0, got 0x%llx",
87*c5959723SBibo Mao 			fp->val64[0], fpu.fpr[0].val64[0]);
88*c5959723SBibo Mao 
89*c5959723SBibo Mao 	run_vcpu(vcpu);
90*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
91*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 16), "Wanted 0x%llx %llx from vr0, got 0x%llx %llx",
92*c5959723SBibo Mao 			fp->val64[0], fp->val64[1],
93*c5959723SBibo Mao 			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1]);
94*c5959723SBibo Mao 
95*c5959723SBibo Mao 	run_vcpu(vcpu);
96*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
97*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 32),
98*c5959723SBibo Mao 			"Wanted 0x%llx %llx %llx %llx from xr0, got 0x%llx %llx %llx %llx",
99*c5959723SBibo Mao 			fp->val64[0], fp->val64[1], fp->val64[2], fp->val64[3],
100*c5959723SBibo Mao 			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1], fpu.fpr[0].val64[2], fpu.fpr[0].val64[3]);
101*c5959723SBibo Mao 
102*c5959723SBibo Mao 	fpu.fpr[0].val64[0] += random();
103*c5959723SBibo Mao 	vcpu_fpu_set(vcpu, &fpu);
104*c5959723SBibo Mao 	run_vcpu(vcpu);
105*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
106*c5959723SBibo Mao 	sync_global_from_guest(vm, *fp);
107*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 8), "Wanted 0x%llx from f0, got 0x%llx",
108*c5959723SBibo Mao 			fp->val64[0], fpu.fpr[0].val64[0]);
109*c5959723SBibo Mao 
110*c5959723SBibo Mao 	fpu.fpr[0].val64[0] += random();
111*c5959723SBibo Mao 	fpu.fpr[0].val64[1] += random();
112*c5959723SBibo Mao 	vcpu_fpu_set(vcpu, &fpu);
113*c5959723SBibo Mao 	run_vcpu(vcpu);
114*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
115*c5959723SBibo Mao 	sync_global_from_guest(vm, *fp);
116*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 16), "Wanted 0x%llx %llx from vr0, got 0x%llx %llx",
117*c5959723SBibo Mao 			fp->val64[0], fp->val64[1],
118*c5959723SBibo Mao 			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1]);
119*c5959723SBibo Mao 
120*c5959723SBibo Mao 	fpu.fpr[0].val64[0] += random();
121*c5959723SBibo Mao 	fpu.fpr[0].val64[1] += random();
122*c5959723SBibo Mao 	fpu.fpr[0].val64[2] += random();
123*c5959723SBibo Mao 	fpu.fpr[0].val64[3] += random();
124*c5959723SBibo Mao 	vcpu_fpu_set(vcpu, &fpu);
125*c5959723SBibo Mao 	run_vcpu(vcpu);
126*c5959723SBibo Mao 	vcpu_fpu_get(vcpu, &fpu);
127*c5959723SBibo Mao 	sync_global_from_guest(vm, *fp);
128*c5959723SBibo Mao 	TEST_ASSERT(!memcmp(fpu.fpr, fp, 32),
129*c5959723SBibo Mao 			"Wanted 0x%llx %llx %llx %llx from xr0, got 0x%llx %llx %llx %llx",
130*c5959723SBibo Mao 			fp->val64[0], fp->val64[1], fp->val64[2], fp->val64[3],
131*c5959723SBibo Mao 			fpu.fpr[0].val64[0], fpu.fpr[0].val64[1], fpu.fpr[0].val64[2], fpu.fpr[0].val64[3]);
132*c5959723SBibo Mao 
133*c5959723SBibo Mao 	run_vcpu(vcpu);
134*c5959723SBibo Mao 	kvm_vm_free(vm);
135*c5959723SBibo Mao 
136*c5959723SBibo Mao 	return 0;
137*c5959723SBibo Mao }
138