From 2faec60a4858bd7fe1bc1419963c6bf030e85706 Mon Sep 17 00:00:00 2001 From: Bibo Mao Date: Fri, 6 Feb 2026 09:28:00 +0800 Subject: [PATCH] LoongArch: KVM: Set default return value in KVM IO bus ops When in-kernel irqchip is enabled, its register area is registered in the KVM IO bus list with API kvm_io_bus_register_dev(). In MMIO/IOCSR register access emulation, kvm_io_bus_read()/kvm_io_bus_write() is called firstly. If it returns 0, it means that the in-kernel irqchip handles the emulation already, else it returns to user-mode VMM and lets VMM emulate the register access. Once in-kernel irqchip is enabled, it should return 0 if the address is within range of the registered KVM IO bus. It should not return to user-mode VMM since VMM does not know how to handle it, and irqchip is handled in kernel already. Here set default return value with 0 in KVM IO bus operations. Signed-off-by: Bibo Mao Signed-off-by: Huacai Chen --- arch/loongarch/kvm/intc/eiointc.c | 43 ++++++++++++------------------- arch/loongarch/kvm/intc/ipi.c | 26 ++++++------------- arch/loongarch/kvm/intc/pch_pic.c | 31 ++++++++++------------ 3 files changed, 39 insertions(+), 61 deletions(-) diff --git a/arch/loongarch/kvm/intc/eiointc.c b/arch/loongarch/kvm/intc/eiointc.c index dfaf6ccfdd8b3..e498a3f1e1367 100644 --- a/arch/loongarch/kvm/intc/eiointc.c +++ b/arch/loongarch/kvm/intc/eiointc.c @@ -119,7 +119,7 @@ void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level) static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s, gpa_t addr, unsigned long *val) { - int index, ret = 0; + int index; u64 data = 0; gpa_t offset; @@ -150,40 +150,36 @@ static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eioint data = s->coremap[index]; break; default: - ret = -EINVAL; break; } *val = data; - return ret; + return 0; } static int kvm_eiointc_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, gpa_t addr, int len, void *val) { - int ret = -EINVAL; unsigned long flags, data, offset; struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { kvm_err("%s: eiointc irqchip not valid!\n", __func__); - return -EINVAL; + return 0; } if (addr & (len - 1)) { kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); - return -EINVAL; + return 0; } offset = addr & 0x7; addr -= offset; vcpu->stat.eiointc_read_exits++; spin_lock_irqsave(&eiointc->lock, flags); - ret = loongarch_eiointc_read(vcpu, eiointc, addr, &data); + loongarch_eiointc_read(vcpu, eiointc, addr, &data); spin_unlock_irqrestore(&eiointc->lock, flags); - if (ret) - return ret; data = data >> (offset * 8); switch (len) { @@ -208,7 +204,7 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu, struct loongarch_eiointc *s, gpa_t addr, u64 value, u64 field_mask) { - int index, irq, ret = 0; + int index, irq; u8 cpu; u64 data, old, mask; gpa_t offset; @@ -287,29 +283,27 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu, eiointc_update_sw_coremap(s, index * 8, data, sizeof(data), true); break; default: - ret = -EINVAL; break; } - return ret; + return 0; } static int kvm_eiointc_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, gpa_t addr, int len, const void *val) { - int ret = -EINVAL; unsigned long flags, value; struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { kvm_err("%s: eiointc irqchip not valid!\n", __func__); - return -EINVAL; + return 0; } if (addr & (len - 1)) { kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); - return -EINVAL; + return 0; } vcpu->stat.eiointc_write_exits++; @@ -317,24 +311,24 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu, switch (len) { case 1: value = *(unsigned char *)val; - ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF); + loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF); break; case 2: value = *(unsigned short *)val; - ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX); + loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX); break; case 4: value = *(unsigned int *)val; - ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX); + loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX); break; default: value = *(unsigned long *)val; - ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX); + loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX); break; } spin_unlock_irqrestore(&eiointc->lock, flags); - return ret; + return 0; } static const struct kvm_io_device_ops kvm_eiointc_ops = { @@ -352,7 +346,7 @@ static int kvm_eiointc_virt_read(struct kvm_vcpu *vcpu, if (!eiointc) { kvm_err("%s: eiointc irqchip not valid!\n", __func__); - return -EINVAL; + return 0; } addr -= EIOINTC_VIRT_BASE; @@ -376,28 +370,25 @@ static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, gpa_t addr, int len, const void *val) { - int ret = 0; unsigned long flags; u32 value = *(u32 *)val; struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc; if (!eiointc) { kvm_err("%s: eiointc irqchip not valid!\n", __func__); - return -EINVAL; + return 0; } addr -= EIOINTC_VIRT_BASE; spin_lock_irqsave(&eiointc->lock, flags); switch (addr) { case EIOINTC_VIRT_FEATURES: - ret = -EPERM; break; case EIOINTC_VIRT_CONFIG: /* * eiointc features can only be set at disabled status */ if ((eiointc->status & BIT(EIOINTC_ENABLE)) && value) { - ret = -EPERM; break; } eiointc->status = value & eiointc->features; @@ -407,7 +398,7 @@ static int kvm_eiointc_virt_write(struct kvm_vcpu *vcpu, } spin_unlock_irqrestore(&eiointc->lock, flags); - return ret; + return 0; } static const struct kvm_io_device_ops kvm_eiointc_virt_ops = { diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 1058c13dba7f4..6a044a74c0955 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -111,7 +111,7 @@ static int mail_send(struct kvm *kvm, uint64_t data) vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu); if (unlikely(vcpu == NULL)) { kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); - return -EINVAL; + return 0; } mailbox = ((data & 0xffffffff) >> 2) & 0x7; offset = IOCSR_IPI_BUF_20 + mailbox * 4; @@ -145,7 +145,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) srcu_read_unlock(&vcpu->kvm->srcu, idx); if (unlikely(ret)) { kvm_err("%s: : read data from addr %llx failed\n", __func__, addr); - return ret; + return 0; } /* Construct the mask by scanning the bit 27-30 */ for (i = 0; i < 4; i++) { @@ -162,7 +162,7 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) if (unlikely(ret)) kvm_err("%s: : write data to addr %llx failed\n", __func__, addr); - return ret; + return 0; } static int any_send(struct kvm *kvm, uint64_t data) @@ -174,7 +174,7 @@ static int any_send(struct kvm *kvm, uint64_t data) vcpu = kvm_get_vcpu_by_cpuid(kvm, cpu); if (unlikely(vcpu == NULL)) { kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); - return -EINVAL; + return 0; } offset = data & 0xffff; @@ -183,7 +183,6 @@ static int any_send(struct kvm *kvm, uint64_t data) static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *val) { - int ret = 0; uint32_t offset; uint64_t res = 0; @@ -202,33 +201,27 @@ static int loongarch_ipi_readl(struct kvm_vcpu *vcpu, gpa_t addr, int len, void spin_unlock(&vcpu->arch.ipi_state.lock); break; case IOCSR_IPI_SET: - res = 0; - break; case IOCSR_IPI_CLEAR: - res = 0; break; case IOCSR_IPI_BUF_20 ... IOCSR_IPI_BUF_38 + 7: if (offset + len > IOCSR_IPI_BUF_38 + 8) { kvm_err("%s: invalid offset or len: offset = %d, len = %d\n", __func__, offset, len); - ret = -EINVAL; break; } res = read_mailbox(vcpu, offset, len); break; default: kvm_err("%s: unknown addr: %llx\n", __func__, addr); - ret = -EINVAL; break; } *(uint64_t *)val = res; - return ret; + return 0; } static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, const void *val) { - int ret = 0; uint64_t data; uint32_t offset; @@ -239,7 +232,6 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons switch (offset) { case IOCSR_IPI_STATUS: - ret = -EINVAL; break; case IOCSR_IPI_EN: spin_lock(&vcpu->arch.ipi_state.lock); @@ -257,7 +249,6 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons if (offset + len > IOCSR_IPI_BUF_38 + 8) { kvm_err("%s: invalid offset or len: offset = %d, len = %d\n", __func__, offset, len); - ret = -EINVAL; break; } write_mailbox(vcpu, offset, data, len); @@ -266,18 +257,17 @@ static int loongarch_ipi_writel(struct kvm_vcpu *vcpu, gpa_t addr, int len, cons ipi_send(vcpu->kvm, data); break; case IOCSR_MAIL_SEND: - ret = mail_send(vcpu->kvm, data); + mail_send(vcpu->kvm, data); break; case IOCSR_ANY_SEND: - ret = any_send(vcpu->kvm, data); + any_send(vcpu->kvm, data); break; default: kvm_err("%s: unknown addr: %llx\n", __func__, addr); - ret = -EINVAL; break; } - return ret; + return 0; } static int kvm_ipi_read(struct kvm_vcpu *vcpu, diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c index 4addb34bf432b..a175f52fcf7f1 100644 --- a/arch/loongarch/kvm/intc/pch_pic.c +++ b/arch/loongarch/kvm/intc/pch_pic.c @@ -74,7 +74,7 @@ void pch_msi_set_irq(struct kvm *kvm, int irq, int level) static int loongarch_pch_pic_read(struct loongarch_pch_pic *s, gpa_t addr, int len, void *val) { - int ret = 0, offset; + int offset; u64 data = 0; void *ptemp; @@ -121,34 +121,32 @@ static int loongarch_pch_pic_read(struct loongarch_pch_pic *s, gpa_t addr, int l data = s->isr; break; default: - ret = -EINVAL; + break; } spin_unlock(&s->lock); - if (ret == 0) { - offset = (addr - s->pch_pic_base) & 7; - data = data >> (offset * 8); - memcpy(val, &data, len); - } + offset = (addr - s->pch_pic_base) & 7; + data = data >> (offset * 8); + memcpy(val, &data, len); - return ret; + return 0; } static int kvm_pch_pic_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, gpa_t addr, int len, void *val) { - int ret; + int ret = 0; struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic; if (!s) { kvm_err("%s: pch pic irqchip not valid!\n", __func__); - return -EINVAL; + return ret; } if (addr & (len - 1)) { kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); - return -EINVAL; + return ret; } /* statistics of pch pic reading */ @@ -161,7 +159,7 @@ static int kvm_pch_pic_read(struct kvm_vcpu *vcpu, static int loongarch_pch_pic_write(struct loongarch_pch_pic *s, gpa_t addr, int len, const void *val) { - int ret = 0, offset; + int offset; u64 old, data, mask; void *ptemp; @@ -226,29 +224,28 @@ static int loongarch_pch_pic_write(struct loongarch_pch_pic *s, gpa_t addr, case PCH_PIC_ROUTE_ENTRY_START ... PCH_PIC_ROUTE_ENTRY_END: break; default: - ret = -EINVAL; break; } spin_unlock(&s->lock); - return ret; + return 0; } static int kvm_pch_pic_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, gpa_t addr, int len, const void *val) { - int ret; + int ret = 0; struct loongarch_pch_pic *s = vcpu->kvm->arch.pch_pic; if (!s) { kvm_err("%s: pch pic irqchip not valid!\n", __func__); - return -EINVAL; + return ret; } if (addr & (len - 1)) { kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); - return -EINVAL; + return ret; } /* statistics of pch pic writing */ -- 2.47.3