From: Fangyu Yu In MRIF mode, the Advanced Interrupt Architecture Specification defines the operation to store the incoming MSIs into the MRIF and to generate the notice MSI,the software shold check the MRIF in the notice MSI irq handler. And without MRIF support,we redirect the guest interrupt back to the original host interrupt, the software update and check MRIF in host irq handler. Signed-off-by: Fangyu Yu --- arch/riscv/kvm/aia_imsic.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/arch/riscv/kvm/aia_imsic.c b/arch/riscv/kvm/aia_imsic.c index 58807e68a3dd..f0d1acde0dd4 100644 --- a/arch/riscv/kvm/aia_imsic.c +++ b/arch/riscv/kvm/aia_imsic.c @@ -867,11 +867,16 @@ int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq, ret = irq_set_vcpu_affinity(host_irq, &vcpu_info); if (ret) { + if (ret == -ENODEV) { + imsic->mrif_support = false; + ret = 0; + } read_unlock_irqrestore(&imsic->vsfile_lock, flags); goto out; } - irq_data_get_irq_chip(irqdata)->irq_write_msi_msg(irqdata, msg); + if (imsic->mrif_support) + irq_data_get_irq_chip(irqdata)->irq_write_msi_msg(irqdata, msg); read_unlock_irqrestore(&imsic->vsfile_lock, flags); } @@ -921,6 +926,10 @@ static int kvm_riscv_vcpu_irq_update(struct kvm_vcpu *vcpu) ret = irq_set_vcpu_affinity(host_irq, &vcpu_info); if (ret) { + if (ret == -ENODEV) { + imsic->mrif_support = false; + ret = 0; + } spin_unlock_irq(&kvm->irqfds.lock); return ret; } @@ -1182,8 +1191,24 @@ int kvm_riscv_vcpu_aia_imsic_inject(struct kvm_vcpu *vcpu, if (imsic->vsfile_cpu >= 0) { writel(iid, imsic->vsfile_va + IMSIC_MMIO_SETIPNUM_LE); } else { + if (imsic->mrif_support) { + struct msi_msg *msg; + unsigned long idx; + + /* In MRIF mode, the noticed MSI irq handler will call here to + * determine whether the MRIF has been updated.Since the IOMMU + * hardware has updated the MRIF,the software does not need to + * update the MRIF file again. + */ + xa_for_each(&imsic->hostirq_array, idx, msg) { + if (msg->data == iid) + goto skip_update_swfile; + } + } eix = &imsic->swfile->eix[iid / BITS_PER_TYPE(u64)]; set_bit(iid & (BITS_PER_TYPE(u64) - 1), eix->eip); + +skip_update_swfile: imsic_swfile_extirq_update(vcpu); } @@ -1260,7 +1285,7 @@ int kvm_riscv_vcpu_aia_imsic_init(struct kvm_vcpu *vcpu) raw_spin_lock_init(&imsic->swfile_extirq_lock); xa_init(&imsic->hostirq_array); - imsic->mrif_support = false; + imsic->mrif_support = true; /* Setup IO device */ kvm_iodevice_init(&imsic->iodev, &imsic_iodoev_ops); -- 2.49.0