From 1910bf1fe895f3669177fc29329de44417b64add Mon Sep 17 00:00:00 2001 From: Wojciech Ozga Date: Fri, 7 Jun 2024 04:30:15 -0500 Subject: [PATCH] Enable CoVE guests to run in an environment that does not have AIA. Detect AIA presence by discovering that the TEE security monitor (TSM) implements the SBI COVI extension. If AIA is not present, inject external interrupts using the HVIP register when resuming execution of a virtual processor via the COVH tvm_vcpu_run() call. Signed-off-by: Wojciech Ozga --- arch/riscv/include/asm/kvm_cove.h | 4 ++++ arch/riscv/kvm/aia.c | 1 + arch/riscv/kvm/cove.c | 8 ++++++-- arch/riscv/kvm/main.c | 9 ++++----- arch/riscv/kvm/vcpu.c | 11 +++++++---- 5 files changed, 22 insertions(+), 11 deletions(-) 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 ||