From nobody Mon Feb 9 19:52:57 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1586762950; cv=none; d=zohomail.com; s=zohoarc; b=Mzj4oYcjgn3N3KSwLp56cj96nQcGM9rPgdJQ0nQLSdNF24zEYwOpXPSxQpPvQ7nEwWV+qKp0JsPlo1TnTJ1774dexHYuqZ86//tuKhZVlZL2lPCcIIX9K0RGAZcnkh5L4eSiofrsqumlhqt2npSLZbCqn8hEajP2zfsMlYfoYh4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1586762950; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=E5XZsIYrkFoN+5jD0I/wrFbIiXPkxWIW2fV5KwTgBEQ=; b=fDnyxsfkpSzdTx9LNeRed7T8i+ODlAU8OJK898u3n4KP6fZItgTRzXJk/2Fy1cTBfkxF9yAAST37o0wFqqmWNxRzgWhRBotTsowhBVlVX1aZkva/1bbT6ypLezvYCS4XGrq/yF7AphZU0/p2O2HrTiHnOE0J6dv1FasZD0gQn7Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1586762950445444.7128615062012; Mon, 13 Apr 2020 00:29:10 -0700 (PDT) Received: from localhost ([::1]:41230 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jNtWn-0005Y4-3e for importer@patchew.org; Mon, 13 Apr 2020 03:29:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37778) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jNtVR-0003rG-IJ for qemu-devel@nongnu.org; Mon, 13 Apr 2020 03:27:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jNtVP-0000yq-Jv for qemu-devel@nongnu.org; Mon, 13 Apr 2020 03:27:45 -0400 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]:32801) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1jNtVP-0000yS-6K for qemu-devel@nongnu.org; Mon, 13 Apr 2020 03:27:43 -0400 Received: by mail-pf1-x444.google.com with SMTP id c138so4174312pfc.0 for ; Mon, 13 Apr 2020 00:27:43 -0700 (PDT) Received: from software.domain.org (28.144.92.34.bc.googleusercontent.com. [34.92.144.28]) by smtp.gmail.com with ESMTPSA id u8sm7241341pgl.19.2020.04.13.00.27.39 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 13 Apr 2020 00:27:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=E5XZsIYrkFoN+5jD0I/wrFbIiXPkxWIW2fV5KwTgBEQ=; b=U+9g9P4Vw69qaDQk3gys+jQLuU/kCp9CvuU+g3pGc6BKknmKHDJlxVPExvg3zBv4kD lF6tUZYcIYyR6DhGqHo/XF+ASNt9ZnmkERoe3Y45rLMaWjMfh6SWtlBqX1x05NyWLRaS /ZxSGletmTcXrnBUObh+xfVJI1XH6GugJnx9HtFAfCK/nu9JZgd220pi0pAkA1/IXHD0 bEuPYNzFJktX/fFdkaiBYlke0PGujrhfIfjMLzlfMd056gSDZ7Y7CGycGjyBBHsG6BL5 zkEfelWSnOJ800NfTODxsu7UJj5sp1ewMm4cvNvC6IHq4hMG7HkEAPcuUjyNyQDBErRk 57Hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=E5XZsIYrkFoN+5jD0I/wrFbIiXPkxWIW2fV5KwTgBEQ=; b=EewbYh2KWzhMZErpfrBIQLZ4d/dfQqTrhsnEGEYlf3Vhpuz7y6RxaVXyN4rDX1zTHv D8JW+yC6yZwFPC6uvMIyuElllph12AByo+OOz7DGuCbsr8XfVV7QWTakLQUOdoCZaU85 ouU4mhcZixxtNfb3g7w0f4Py4orp5FO7N9UPjYkl8HLzeWa2bkTG8rHwuVULOX558zpD l1eiwiY8lbeaoGC3RltG7kM8bqoDtRFK1Kh9hxIEwmf+xgnsUYx6+iRn4CT/6iYOQ5Yj kGoAUf7TyeDrs57M2NjlMOeFmJIJn+pJwuRGCrnRu5oBHkzbgzkYeBeWOabtkeZh9UAi 9a7w== X-Gm-Message-State: AGi0PuZBhZryXLnf9nLMQ6KUPPLdHIND49dPk+dciA/fnMjza2U3AAy4 fJQroOqr/jQLr/bIO9rq1IM= X-Google-Smtp-Source: APiQypJOPUPgo1mrI2VzVpnQy4tPiVfjCCn1bn/fu8hLYrHYsLB8kwYoXC4VuJRWgZ3eO9qL2aDOrA== X-Received: by 2002:a63:5f01:: with SMTP id t1mr15385599pgb.186.1586762862161; Mon, 13 Apr 2020 00:27:42 -0700 (PDT) From: Huacai Chen To: Paolo Bonzini , Thomas Bogendoerfer Subject: [PATCH 11/15] KVM: MIPS: Add Loongson-3 Virtual IPI interrupt support Date: Mon, 13 Apr 2020 15:30:20 +0800 Message-Id: <1586763024-12197-12-git-send-email-chenhc@lemote.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1586763024-12197-1-git-send-email-chenhc@lemote.com> References: <1586763024-12197-1-git-send-email-chenhc@lemote.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::444 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kvm@vger.kernel.org, Huacai Chen , qemu-devel@nongnu.org, Jiaxun Yang , linux-mips@vger.kernel.org, Fuxin Zhang , Huacai Chen Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch add Loongson-3 Virtual IPI interrupt support in the kernel, because emulate it in QEMU is too expensive for performance. Signed-off-by: Huacai Chen Co-developed-by: Jiaxun Yang --- arch/mips/include/asm/kvm_host.h | 32 ++++++ arch/mips/kvm/Makefile | 3 + arch/mips/kvm/emulate.c | 21 +++- arch/mips/kvm/loongson_ipi.c | 215 +++++++++++++++++++++++++++++++++++= ++++ arch/mips/kvm/mips.c | 6 ++ 5 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 arch/mips/kvm/loongson_ipi.c diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_h= ost.h index 2258a2e..4022712 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -23,6 +23,8 @@ #include #include =20 +#include + /* MIPS KVM register ids */ #define MIPS_CP0_32(_R, _S) \ (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U32 | (8 * (_R) + (_S))) @@ -181,11 +183,39 @@ struct kvm_vcpu_stat { struct kvm_arch_memory_slot { }; =20 +#ifdef CONFIG_CPU_LOONGSON64 +typedef struct ipi_state { + uint32_t status; + uint32_t en; + uint32_t set; + uint32_t clear; + uint64_t buf[4]; +} ipi_state; + +struct loongson_kvm_ipi; + +typedef struct ipi_io_device { + int node_id; + struct loongson_kvm_ipi *ipi; + struct kvm_io_device device; +} ipi_io_device; + +struct loongson_kvm_ipi { + spinlock_t lock; + struct kvm *kvm; + ipi_state ipistate[16]; + ipi_io_device dev_ipi[4]; +}; +#endif + struct kvm_arch { /* Guest physical mm */ struct mm_struct gpa_mm; /* Mask of CPUs needing GPA ASID flush */ cpumask_t asid_flush_mask; +#ifdef CONFIG_CPU_LOONGSON64 + struct loongson_kvm_ipi ipi; +#endif }; =20 #define N_MIPS_COPROC_REGS 32 @@ -1133,6 +1163,8 @@ extern int kvm_mips_trans_mtc0(union mips_instruction= inst, u32 *opc, /* Misc */ extern void kvm_mips_dump_stats(struct kvm_vcpu *vcpu); extern unsigned long kvm_mips_get_ramsize(struct kvm *kvm); +extern int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, + struct kvm_mips_interrupt *irq); =20 static inline void kvm_arch_hardware_unsetup(void) {} static inline void kvm_arch_sync_events(struct kvm *kvm) {} diff --git a/arch/mips/kvm/Makefile b/arch/mips/kvm/Makefile index 0a3cef6..506c4ac 100644 --- a/arch/mips/kvm/Makefile +++ b/arch/mips/kvm/Makefile @@ -13,6 +13,9 @@ kvm-objs :=3D $(common-objs-y) mips.o emulate.o entry.o \ fpu.o kvm-objs +=3D hypcall.o kvm-objs +=3D mmu.o +ifdef CONFIG_CPU_LOONGSON64 +kvm-objs +=3D loongson_ipi.o +endif =20 ifdef CONFIG_KVM_MIPS_VZ kvm-objs +=3D vz.o diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 754094b..aa2db51 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -1600,6 +1600,7 @@ enum emulation_result kvm_mips_emulate_store(union mi= ps_instruction inst, struct kvm_run *run, struct kvm_vcpu *vcpu) { + int r; enum emulation_result er; u32 rt; void *data =3D run->mmio.data; @@ -1666,9 +1667,17 @@ enum emulation_result kvm_mips_emulate_store(union m= ips_instruction inst, goto out_fail; } =20 - run->mmio.is_write =3D 1; vcpu->mmio_needed =3D 1; + run->mmio.is_write =3D 1; vcpu->mmio_is_write =3D 1; + + r =3D kvm_io_bus_write(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr, run->mmio= .len, data); + + if (!r) { + vcpu->mmio_needed =3D 0; + return EMULATE_DONE; + } + return EMULATE_DO_MMIO; =20 out_fail: @@ -1681,6 +1690,7 @@ enum emulation_result kvm_mips_emulate_load(union mip= s_instruction inst, u32 cause, struct kvm_run *run, struct kvm_vcpu *vcpu) { + int r; enum emulation_result er; unsigned long curr_pc; u32 op, rt; @@ -1745,6 +1755,15 @@ enum emulation_result kvm_mips_emulate_load(union mi= ps_instruction inst, =20 run->mmio.is_write =3D 0; vcpu->mmio_is_write =3D 0; + + r =3D kvm_io_bus_read(vcpu, KVM_MMIO_BUS, run->mmio.phys_addr, run->mmio.= len, run->mmio.data); + + if (!r) { + kvm_mips_complete_mmio_load(vcpu, run); + vcpu->mmio_needed =3D 0; + return EMULATE_DONE; + } + return EMULATE_DO_MMIO; } =20 diff --git a/arch/mips/kvm/loongson_ipi.c b/arch/mips/kvm/loongson_ipi.c new file mode 100644 index 00000000..3e22532 --- /dev/null +++ b/arch/mips/kvm/loongson_ipi.c @@ -0,0 +1,215 @@ +/* + * This file is subject to the terms and conditions of the GNU General Pub= lic + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Loongson-3 Virtual IPI interrupt support. + * + * Copyright (C) 2019 Loongson Technologies, Inc. All rights reserved. + * + * Authors: Chen Zhu + * Authors: Huacai Chen + */ + +#include + +#define IPI_BASE 0x3ff01000ULL + +#define CORE0_STATUS_OFF 0x000 +#define CORE0_EN_OFF 0x004 +#define CORE0_SET_OFF 0x008 +#define CORE0_CLEAR_OFF 0x00c +#define CORE0_BUF_20 0x020 +#define CORE0_BUF_28 0x028 +#define CORE0_BUF_30 0x030 +#define CORE0_BUF_38 0x038 + +#define CORE1_STATUS_OFF 0x100 +#define CORE1_EN_OFF 0x104 +#define CORE1_SET_OFF 0x108 +#define CORE1_CLEAR_OFF 0x10c +#define CORE1_BUF_20 0x120 +#define CORE1_BUF_28 0x128 +#define CORE1_BUF_30 0x130 +#define CORE1_BUF_38 0x138 + +#define CORE2_STATUS_OFF 0x200 +#define CORE2_EN_OFF 0x204 +#define CORE2_SET_OFF 0x208 +#define CORE2_CLEAR_OFF 0x20c +#define CORE2_BUF_20 0x220 +#define CORE2_BUF_28 0x228 +#define CORE2_BUF_30 0x230 +#define CORE2_BUF_38 0x238 + +#define CORE3_STATUS_OFF 0x300 +#define CORE3_EN_OFF 0x304 +#define CORE3_SET_OFF 0x308 +#define CORE3_CLEAR_OFF 0x30c +#define CORE3_BUF_20 0x320 +#define CORE3_BUF_28 0x328 +#define CORE3_BUF_30 0x330 +#define CORE3_BUF_38 0x338 + +static int loongson_vipi_read(struct loongson_kvm_ipi *ipi, gpa_t addr, in= t len, void *val) +{ + uint32_t core =3D (addr >> 8) & 3; + uint32_t node =3D (addr >> 44) & 3; + uint32_t id =3D core + node * 4; + uint64_t offset =3D addr & 0xff; + void *pbuf; + ipi_state *s =3D &(ipi->ipistate[id]); + + BUG_ON(offset & (len - 1)); + + switch (offset) { + case CORE0_STATUS_OFF: + *(uint64_t *)val =3D s->status; + break; + + case CORE0_EN_OFF: + *(uint64_t *)val =3D s->en; + break; + + case CORE0_SET_OFF: + *(uint64_t *)val =3D 0; + break; + + case CORE0_CLEAR_OFF: + *(uint64_t *)val =3D 0; + break; + + case CORE0_BUF_20 ... CORE0_BUF_38: + pbuf =3D (void *)s->buf + (offset - 0x20); + if (len =3D=3D 8) + *(uint64_t *)val =3D *(uint64_t *)pbuf; + else /* Assume len =3D=3D 4 */ + *(uint32_t *)val =3D *(uint32_t *)pbuf; + break; + + default: + printk("loongson_vipi_read() with unknown addr %llx \n", addr); + break; + } + + return 0; +} + +static int loongson_vipi_write(struct loongson_kvm_ipi *ipi, gpa_t addr, i= nt len, const void *val) +{ + uint32_t core =3D (addr >> 8) & 3; + uint32_t node =3D (addr >> 44) & 3; + uint32_t id =3D core + node * 4; + uint64_t data, offset =3D addr & 0xff; + void *pbuf; + struct kvm *kvm =3D ipi->kvm; + struct kvm_mips_interrupt irq; + ipi_state *s =3D &(ipi->ipistate[id]); + + data =3D *(uint64_t *)val; + BUG_ON(offset & (len - 1)); + + switch (offset) { + case CORE0_STATUS_OFF: + break; + + case CORE0_EN_OFF: + s->en =3D data; + break; + + case CORE0_SET_OFF: + s->status |=3D data; + irq.cpu =3D id; + irq.irq =3D 6; + kvm_vcpu_ioctl_interrupt(kvm->vcpus[id], &irq); + break; + + case CORE0_CLEAR_OFF: + s->status &=3D ~data; + if (!s->status) { + irq.cpu =3D id; + irq.irq =3D -6; + kvm_vcpu_ioctl_interrupt(kvm->vcpus[id],&irq); + } + break; + + case CORE0_BUF_20 ... CORE0_BUF_38: + pbuf =3D (void *)s->buf + (offset - 0x20); + if (len =3D=3D 8) + *(uint64_t *)pbuf =3D (uint64_t)data; + else /* Assume len =3D=3D 4 */ + *(uint32_t *)pbuf =3D (uint32_t)data; + break; + + default: + printk("loongson_vipi_write() with unknown addr %llx \n", addr); + break; + } + + return 0; +} + +static int kvm_ipi_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, void *val) +{ + unsigned long flags; + ipi_io_device *ipi_device; + struct loongson_kvm_ipi *ipi; + + ipi_device =3D container_of(dev, ipi_io_device, device); + ipi =3D ipi_device->ipi; + + spin_lock_irqsave(&ipi->lock, flags); + loongson_vipi_read(ipi, addr, len, val); + spin_unlock_irqrestore(&ipi->lock, flags); + + return 0; +} + +static int kvm_ipi_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, + gpa_t addr, int len, const void *val) +{ + unsigned long flags; + ipi_io_device *ipi_device; + struct loongson_kvm_ipi *ipi; + + ipi_device =3D container_of(dev, ipi_io_device, device); + ipi =3D ipi_device->ipi; + + spin_lock_irqsave(&ipi->lock, flags); + loongson_vipi_write(ipi, addr, len, val); + spin_unlock_irqrestore(&ipi->lock, flags); + + return 0; +} + +static const struct kvm_io_device_ops kvm_ipi_ops =3D { + .read =3D kvm_ipi_read, + .write =3D kvm_ipi_write, +}; + +void kvm_init_loongson_ipi(struct kvm *kvm) +{ + int i; + unsigned long addr; + struct loongson_kvm_ipi *s; + struct kvm_io_device *device; + + s =3D &kvm->arch.ipi; + s->kvm =3D kvm; + spin_lock_init(&s->lock); + + /* + * Initialize IPI device + */ + for (i =3D 0; i < 4; i++) { + device =3D &s->dev_ipi[i].device; + kvm_iodevice_init(device, &kvm_ipi_ops); + addr =3D (((unsigned long)i) << 44) + IPI_BASE; + mutex_lock(&kvm->slots_lock); + kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, addr, 0x400, device); + mutex_unlock(&kvm->slots_lock); + s->dev_ipi[i].ipi =3D s; + s->dev_ipi[i].node_id =3D i; + } +} diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 5c3a414..20acd50 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -128,6 +128,8 @@ int kvm_arch_check_processor_compat(void) return 0; } =20 +extern void kvm_init_loongson_ipi(struct kvm *kvm); + int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { switch (type) { @@ -147,6 +149,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long ty= pe) if (!kvm->arch.gpa_mm.pgd) return -ENOMEM; =20 +#ifdef CONFIG_CPU_LOONGSON64 + kvm_init_loongson_ipi(kvm); +#endif + return 0; } =20 --=20 2.7.0