Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[sfrench/cifs-2.6.git] / arch / riscv / kvm / vcpu.c
index 7b355900f2354a9c7e185db8c1df86b55b12018d..d12ef99901fc50334df504c04d9492304f513411 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/cacheflush.h>
 #include <asm/hwcap.h>
 #include <asm/sbi.h>
+#include <asm/vector.h>
+#include <asm/kvm_vcpu_vector.h>
 
 const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
        KVM_GENERIC_VCPU_STATS(),
@@ -57,6 +59,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
        [KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h,
        [KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i,
        [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
+       [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
 
        KVM_ISA_EXT_ARR(SSAIA),
        KVM_ISA_EXT_ARR(SSTC),
@@ -86,6 +89,8 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
        switch (ext) {
        case KVM_RISCV_ISA_EXT_H:
                return false;
+       case KVM_RISCV_ISA_EXT_V:
+               return riscv_v_vstate_ctrl_user_allowed();
        default:
                break;
        }
@@ -140,6 +145,8 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
 
        kvm_riscv_vcpu_fp_reset(vcpu);
 
+       kvm_riscv_vcpu_vector_reset(vcpu);
+
        kvm_riscv_vcpu_timer_reset(vcpu);
 
        kvm_riscv_vcpu_aia_reset(vcpu);
@@ -200,6 +207,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
        cntx->hstatus |= HSTATUS_SPVP;
        cntx->hstatus |= HSTATUS_SPV;
 
+       if (kvm_riscv_vcpu_alloc_vector_context(vcpu, cntx))
+               return -ENOMEM;
+
        /* By default, make CY, TM, and IR counters accessible in VU mode */
        reset_csr->scounteren = 0x7;
 
@@ -243,6 +253,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
        /* Free unused pages pre-allocated for G-stage page table mappings */
        kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
+
+       /* Free vector context space for host and guest kernel */
+       kvm_riscv_vcpu_free_vector_context(vcpu);
 }
 
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
@@ -683,6 +696,9 @@ static int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu,
                return kvm_riscv_vcpu_set_reg_isa_ext(vcpu, reg);
        case KVM_REG_RISCV_SBI_EXT:
                return kvm_riscv_vcpu_set_reg_sbi_ext(vcpu, reg);
+       case KVM_REG_RISCV_VECTOR:
+               return kvm_riscv_vcpu_set_reg_vector(vcpu, reg,
+                                                KVM_REG_RISCV_VECTOR);
        default:
                break;
        }
@@ -712,6 +728,9 @@ static int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
                return kvm_riscv_vcpu_get_reg_isa_ext(vcpu, reg);
        case KVM_REG_RISCV_SBI_EXT:
                return kvm_riscv_vcpu_get_reg_sbi_ext(vcpu, reg);
+       case KVM_REG_RISCV_VECTOR:
+               return kvm_riscv_vcpu_get_reg_vector(vcpu, reg,
+                                                KVM_REG_RISCV_VECTOR);
        default:
                break;
        }
@@ -1006,6 +1025,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        kvm_riscv_vcpu_host_fp_save(&vcpu->arch.host_context);
        kvm_riscv_vcpu_guest_fp_restore(&vcpu->arch.guest_context,
                                        vcpu->arch.isa);
+       kvm_riscv_vcpu_host_vector_save(&vcpu->arch.host_context);
+       kvm_riscv_vcpu_guest_vector_restore(&vcpu->arch.guest_context,
+                                           vcpu->arch.isa);
 
        kvm_riscv_vcpu_aia_load(vcpu, cpu);
 
@@ -1025,6 +1047,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        kvm_riscv_vcpu_host_fp_restore(&vcpu->arch.host_context);
 
        kvm_riscv_vcpu_timer_save(vcpu);
+       kvm_riscv_vcpu_guest_vector_save(&vcpu->arch.guest_context,
+                                        vcpu->arch.isa);
+       kvm_riscv_vcpu_host_vector_restore(&vcpu->arch.host_context);
 
        csr->vsstatus = csr_read(CSR_VSSTATUS);
        csr->vsie = csr_read(CSR_VSIE);