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