diff --git a/arch/riscv/include/asm/kvm_cove.h b/arch/riscv/include/asm/kvm_cove.h index afaea7c621bb..ba4e282c0e81 100644 --- a/arch/riscv/include/asm/kvm_cove.h +++ b/arch/riscv/include/asm/kvm_cove.h @@ -19,6 +19,10 @@ #include #include +DECLARE_STATIC_KEY_FALSE(kvm_riscv_covi_available); +#define kvm_riscv_covi_available() \ + static_branch_unlikely(&kvm_riscv_covi_available) + #define KVM_COVE_PAGE_SIZE_4K (1UL << 12) #define KVM_COVE_PAGE_SIZE_2MB (1UL << 21) #define KVM_COVE_PAGE_SIZE_1GB (1UL << 30) diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c index 88b91b5d5837..3259d53197ac 100644 --- a/arch/riscv/kvm/aia.c +++ b/arch/riscv/kvm/aia.c @@ -30,6 +30,7 @@ static int hgei_parent_irq; unsigned int kvm_riscv_aia_nr_hgei; unsigned int kvm_riscv_aia_max_ids; DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available); +DEFINE_STATIC_KEY_FALSE(kvm_riscv_covi_available); static int aia_find_hgei(struct kvm_vcpu *owner) { diff --git a/arch/riscv/kvm/cove.c b/arch/riscv/kvm/cove.c index ba596b7f2240..c4a3fe3b6bd7 100644 --- a/arch/riscv/kvm/cove.c +++ b/arch/riscv/kvm/cove.c @@ -589,9 +589,9 @@ void noinstr kvm_riscv_cove_vcpu_switchto(struct kvm_vcpu *vcpu, struct kvm_cpu_ /* * Bind the vsfile here instead during the new vsfile allocation because - * COVH bind call requires the TVM to be in finalized state. + * COVI bind call requires the TVM to be in finalized state. */ - if (tvcpuc->imsic.bind_required) { + if (likely(kvm_riscv_covi_available()) && tvcpuc->imsic.bind_required) { tvcpuc->imsic.bind_required = false; rc = kvm_riscv_cove_vcpu_imsic_bind(vcpu, BIT(tvcpuc->imsic.vsfile_hgei)); if (rc) { @@ -988,6 +988,10 @@ int kvm_riscv_cove_init(void) if (sbi_probe_extension(SBI_EXT_COVH) <= 0 || !kvm_riscv_nacl_available()) return -EOPNOTSUPP; + if (sbi_probe_extension(SBI_EXT_COVI) > 0) { + static_branch_enable(&kvm_riscv_covi_available); + } + rc = sbi_covh_tsm_get_info(&tinfo); if (rc < 0) return -EINVAL; diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c index a05941420307..6d5cfa52e413 100644 --- a/arch/riscv/kvm/main.c +++ b/arch/riscv/kvm/main.c @@ -31,12 +31,11 @@ int kvm_arch_hardware_enable(void) return rc; /* - * We just need to invoke aia enable for CoVE if host is in VS mode - * However, if the host is running in HS mode, we need to initialize - * other CSRs as well for legacy VMs. - * TODO: Handle host in HS mode use case. + * We just need to invoke aia enable for CoVE if host is in VS mode and TSM + * supports AIA (COVI extension). However, if the host is running in HS mode, + * we need to initialize other CSRs as well for legacy VMs. */ - if (unlikely(kvm_riscv_cove_enabled())) + if (unlikely(kvm_riscv_cove_enabled()) && likely(kvm_riscv_covi_available())) goto enable_aia; hedeleg = 0; diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index 49f2dba38447..4d8a01385ed4 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -730,8 +730,8 @@ long kvm_arch_vcpu_async_ioctl(struct file *filp, if (ioctl == KVM_INTERRUPT) { struct kvm_interrupt irq; - /* We do not support user space emulated IRQCHIP for TVMs yet */ - if (is_cove_vcpu(vcpu)) + /* We do not support user space emulated IRQCHIP for TVMs that utilize AIA yet */ + if (is_cove_vcpu(vcpu) && kvm_riscv_aia_initialized(vcpu->kvm)) return -ENXIO; if (copy_from_user(&irq, argp, sizeof(irq))) @@ -1325,8 +1325,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) */ kvm_riscv_vcpu_flush_interrupts(vcpu); - /* Update HVIP CSR for current CPU only for non TVMs */ - if (!is_cove_vcpu(vcpu)) + /* + * Do not update HVIP CSR for TVMs with AIA because AIA + * provides alternative method to inject interrupts. + */ + if (!is_cove_vcpu(vcpu) || !kvm_riscv_covi_available()) kvm_riscv_update_hvip(vcpu); if (ret <= 0 ||