[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240705023854.1005258-12-lixianglai@loongson.cn>
Date: Fri, 5 Jul 2024 10:38:54 +0800
From: Xianglai Li <lixianglai@...ngson.cn>
To: linux-kernel@...r.kernel.org
Cc: Bibo Mao <maobibo@...ngson.cn>,
Huacai Chen <chenhuacai@...nel.org>,
kvm@...r.kernel.org,
loongarch@...ts.linux.dev,
Min Zhou <zhoumin@...ngson.cn>,
Paolo Bonzini <pbonzini@...hat.com>,
Tianrui Zhao <zhaotianrui@...ngson.cn>,
WANG Xuerui <kernel@...0n.name>,
Xianglai li <lixianglai@...ngson.cn>
Subject: [PATCH 11/11] LoongArch: KVM: Add irqfd support
Enable the KVM_IRQ_ROUTING KVM_IRQCHIP KVM_MSI configuration item,
increase the KVM_CAP_IRQCHIP capability, and implement the query
interface of the kernel irqchip.
Signed-off-by: Xianglai Li <lixianglai@...ngson.cn>
---
Cc: Bibo Mao <maobibo@...ngson.cn>
Cc: Huacai Chen <chenhuacai@...nel.org>
Cc: kvm@...r.kernel.org
Cc: loongarch@...ts.linux.dev
Cc: Min Zhou <zhoumin@...ngson.cn>
Cc: Paolo Bonzini <pbonzini@...hat.com>
Cc: Tianrui Zhao <zhaotianrui@...ngson.cn>
Cc: WANG Xuerui <kernel@...0n.name>
Cc: Xianglai li <lixianglai@...ngson.cn>
arch/loongarch/kvm/Kconfig | 3 ++
arch/loongarch/kvm/Makefile | 1 +
arch/loongarch/kvm/intc/pch_pic.c | 28 ++++++++++
arch/loongarch/kvm/irqfd.c | 87 +++++++++++++++++++++++++++++++
arch/loongarch/kvm/vm.c | 19 ++++++-
5 files changed, 137 insertions(+), 1 deletion(-)
create mode 100644 arch/loongarch/kvm/irqfd.c
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index c4ef2b4d9797..c2ef17055995 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -29,6 +29,9 @@ config KVM
select KVM_MMIO
select HAVE_KVM_READONLY_MEM
select KVM_XFER_TO_GUEST_WORK
+ select HAVE_KVM_IRQ_ROUTING
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_MSI
help
Support hosting virtualized guest machines using
hardware virtualization extensions. You will need
diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile
index 165ecb4d408f..619ab4969458 100644
--- a/arch/loongarch/kvm/Makefile
+++ b/arch/loongarch/kvm/Makefile
@@ -21,5 +21,6 @@ kvm-y += vm.o
kvm-y += intc/ipi.o
kvm-y += intc/extioi.o
kvm-y += intc/pch_pic.o
+kvm-y += irqfd.o
CFLAGS_exit.o += $(call cc-option,-Wno-override-init,)
diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c
index abb7bab84f2d..e18e27992978 100644
--- a/arch/loongarch/kvm/intc/pch_pic.c
+++ b/arch/loongarch/kvm/intc/pch_pic.c
@@ -449,6 +449,29 @@ static int kvm_loongarch_pch_pic_set_attr(struct kvm_device *dev,
return ret;
}
+static int kvm_setup_default_irq_routing(struct kvm *kvm)
+{
+ struct kvm_irq_routing_entry *entries;
+
+ u32 nr = KVM_IRQCHIP_NUM_PINS;
+ int i, ret;
+
+ entries = kcalloc(nr, sizeof(*entries), GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < nr; i++) {
+ entries[i].gsi = i;
+ entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
+ entries[i].u.irqchip.irqchip = 0;
+ entries[i].u.irqchip.pin = i;
+ }
+ ret = kvm_set_irq_routing(kvm, entries, nr, 0);
+ kfree(entries);
+
+ return 0;
+}
+
static void kvm_loongarch_pch_pic_destroy(struct kvm_device *dev)
{
struct kvm *kvm;
@@ -474,6 +497,7 @@ static void kvm_loongarch_pch_pic_destroy(struct kvm_device *dev)
static int kvm_loongarch_pch_pic_create(struct kvm_device *dev, u32 type)
{
+ int ret;
struct loongarch_pch_pic *s;
struct kvm *kvm = dev->kvm;
@@ -481,6 +505,10 @@ static int kvm_loongarch_pch_pic_create(struct kvm_device *dev, u32 type)
if (kvm->arch.pch_pic)
return -EINVAL;
+ ret = kvm_setup_default_irq_routing(kvm);
+ if (ret)
+ return -ENOMEM;
+
s = kzalloc(sizeof(struct loongarch_pch_pic), GFP_KERNEL);
if (!s)
return -ENOMEM;
diff --git a/arch/loongarch/kvm/irqfd.c b/arch/loongarch/kvm/irqfd.c
new file mode 100644
index 000000000000..bf67f329ebc9
--- /dev/null
+++ b/arch/loongarch/kvm/irqfd.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
+ */
+
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+#include <asm/kvm_pch_pic.h>
+
+static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
+{
+ /* ioapic pin (0 ~ 64) <---> gsi(0 ~ 64) */
+ pch_pic_set_irq(kvm->arch.pch_pic, e->irqchip.pin, level);
+
+ return 0;
+}
+
+/*
+ * kvm_set_routing_entry: populate a kvm routing entry
+ * from a user routing entry
+ *
+ * @kvm: the VM this entry is applied to
+ * @e: kvm kernel routing entry handle
+ * @ue: user api routing entry handle
+ * return 0 on success, -EINVAL on errors.
+ */
+int kvm_set_routing_entry(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+{
+ int r = -EINVAL;
+
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_IRQCHIP:
+ e->set = kvm_set_ioapic_irq;
+
+ e->irqchip.irqchip = ue->u.irqchip.irqchip;
+ e->irqchip.pin = ue->u.irqchip.pin;
+
+ if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
+ goto out;
+ break;
+ case KVM_IRQ_ROUTING_MSI:
+ e->set = kvm_set_msi;
+ e->msi.address_lo = ue->u.msi.address_lo;
+ e->msi.address_hi = ue->u.msi.address_hi;
+ e->msi.data = ue->u.msi.data;
+ break;
+ default:
+ goto out;
+ }
+ r = 0;
+out:
+ return r;
+}
+
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
+{
+ if (e->type == KVM_IRQ_ROUTING_MSI) {
+ pch_msi_set_irq(kvm, e->msi.data, 1);
+ return 0;
+ }
+
+ return -EWOULDBLOCK;
+}
+
+/**
+ * kvm_set_msi: inject the MSI corresponding to the
+ * MSI routing entry
+ *
+ * This is the entry point for irqfd MSI injection
+ * and userspace MSI injection.
+ */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
+{
+ if (!level)
+ return -1;
+
+ pch_msi_set_irq(kvm, e->msi.data, level);
+ return 0;
+}
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
index decfe11be46b..72ea4bb9f912 100644
--- a/arch/loongarch/kvm/vm.c
+++ b/arch/loongarch/kvm/vm.c
@@ -71,6 +71,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
int r;
switch (ext) {
+ case KVM_CAP_IRQCHIP:
case KVM_CAP_ONE_REG:
case KVM_CAP_ENABLE_CAP:
case KVM_CAP_READONLY_MEM:
@@ -103,7 +104,18 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{
- return -ENOIOCTLCMD;
+ int r;
+
+ switch (ioctl) {
+ case KVM_CREATE_IRQCHIP: {
+ r = 1;
+ break;
+ }
+ default:
+ r = -ENOIOCTLCMD;
+ }
+
+ return r;
}
int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *data,
@@ -137,3 +149,8 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *data,
return ret;
}
+
+bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
+{
+ return (bool)((!!kvm->arch.extioi) && (!!kvm->arch.pch_pic));
+}
--
2.39.1
Powered by blists - more mailing lists