public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support
@ 2023-09-18 12:57 Anup Patel
  2023-09-18 12:57 ` [kvmtool PATCH v2 1/6] Sync-up header with Linux-6.5 for KVM RISC-V Anup Patel
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

The latest KVM in Linux-6.5 has support for:
1) Svnapot ISA extension support
2) AIA in-kernel irqchip support

This series adds corresponding changes in KVMTOOL to use the above
mentioned features for Guest/VM.

These patches can also be found in the riscv_aia_v2 branch at:
https://github.com/avpatel/kvmtool.git

Changes since v1:
 - Rebased on commit 9cb1b46cb765972326a46bdba867d441a842af56
 - Updated PATCH1 to sync header with released Linux-6.5

Anup Patel (6):
  Sync-up header with Linux-6.5 for KVM RISC-V
  riscv: Add Svnapot extension support
  riscv: Make irqchip support pluggable
  riscv: Add IRQFD support for in-kernel AIA irqchip
  riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
  riscv: Fix guest/init linkage for multilib toolchain

 Makefile                            |   3 +
 include/linux/kvm.h                 |   6 +-
 riscv/aia.c                         | 227 ++++++++++++++++++++++++++++
 riscv/fdt.c                         |  15 +-
 riscv/include/asm/kvm.h             |  81 ++++++++++
 riscv/include/kvm/fdt-arch.h        |   8 +-
 riscv/include/kvm/kvm-arch.h        |  38 ++++-
 riscv/include/kvm/kvm-config-arch.h |   3 +
 riscv/irq.c                         | 138 ++++++++++++++++-
 riscv/kvm.c                         |   2 +
 riscv/pci.c                         |  32 ++--
 riscv/plic.c                        |  61 ++++----
 12 files changed, 563 insertions(+), 51 deletions(-)
 create mode 100644 riscv/aia.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 1/6] Sync-up header with Linux-6.5 for KVM RISC-V
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-09-18 12:57 ` [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support Anup Patel
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

We sync-up Linux headers to get latest KVM RISC-V headers having
V, Svnapot, and AIA support.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 include/linux/kvm.h     |  6 ++-
 riscv/include/asm/kvm.h | 81 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 737318b..f089ab2 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -1190,6 +1190,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 225
 #define KVM_CAP_PMU_EVENT_MASKED_EVENTS 226
 #define KVM_CAP_COUNTER_OFFSET 227
+#define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228
+#define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1442,6 +1444,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_XIVE		KVM_DEV_TYPE_XIVE
 	KVM_DEV_TYPE_ARM_PV_TIME,
 #define KVM_DEV_TYPE_ARM_PV_TIME	KVM_DEV_TYPE_ARM_PV_TIME
+	KVM_DEV_TYPE_RISCV_AIA,
+#define KVM_DEV_TYPE_RISCV_AIA		KVM_DEV_TYPE_RISCV_AIA
 	KVM_DEV_TYPE_MAX,
 };
 
@@ -1613,7 +1617,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_GET_DEBUGREGS         _IOR(KVMIO,  0xa1, struct kvm_debugregs)
 #define KVM_SET_DEBUGREGS         _IOW(KVMIO,  0xa2, struct kvm_debugregs)
 /*
- * vcpu version available with KVM_ENABLE_CAP
+ * vcpu version available with KVM_CAP_ENABLE_CAP
  * vm version available with KVM_CAP_ENABLE_CAP_VM
  */
 #define KVM_ENABLE_CAP            _IOW(KVMIO,  0xa3, struct kvm_enable_cap)
diff --git a/riscv/include/asm/kvm.h b/riscv/include/asm/kvm.h
index f92790c..930fdc4 100644
--- a/riscv/include/asm/kvm.h
+++ b/riscv/include/asm/kvm.h
@@ -15,6 +15,7 @@
 #include <asm/bitsperlong.h>
 #include <asm/ptrace.h>
 
+#define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
@@ -121,6 +122,8 @@ enum KVM_RISCV_ISA_EXT_ID {
 	KVM_RISCV_ISA_EXT_ZICBOZ,
 	KVM_RISCV_ISA_EXT_ZBB,
 	KVM_RISCV_ISA_EXT_SSAIA,
+	KVM_RISCV_ISA_EXT_V,
+	KVM_RISCV_ISA_EXT_SVNAPOT,
 	KVM_RISCV_ISA_EXT_MAX,
 };
 
@@ -203,6 +206,84 @@ enum KVM_RISCV_SBI_EXT_ID {
 #define KVM_REG_RISCV_SBI_MULTI_REG_LAST	\
 		KVM_REG_RISCV_SBI_MULTI_REG(KVM_RISCV_SBI_EXT_MAX - 1)
 
+/* V extension registers are mapped as type 9 */
+#define KVM_REG_RISCV_VECTOR		(0x09 << KVM_REG_RISCV_TYPE_SHIFT)
+#define KVM_REG_RISCV_VECTOR_CSR_REG(name)	\
+		(offsetof(struct __riscv_v_ext_state, name) / sizeof(unsigned long))
+#define KVM_REG_RISCV_VECTOR_REG(n)	\
+		((n) + sizeof(struct __riscv_v_ext_state) / sizeof(unsigned long))
+
+/* Device Control API: RISC-V AIA */
+#define KVM_DEV_RISCV_APLIC_ALIGN		0x1000
+#define KVM_DEV_RISCV_APLIC_SIZE		0x4000
+#define KVM_DEV_RISCV_APLIC_MAX_HARTS		0x4000
+#define KVM_DEV_RISCV_IMSIC_ALIGN		0x1000
+#define KVM_DEV_RISCV_IMSIC_SIZE		0x1000
+
+#define KVM_DEV_RISCV_AIA_GRP_CONFIG		0
+#define KVM_DEV_RISCV_AIA_CONFIG_MODE		0
+#define KVM_DEV_RISCV_AIA_CONFIG_IDS		1
+#define KVM_DEV_RISCV_AIA_CONFIG_SRCS		2
+#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS	3
+#define KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT	4
+#define KVM_DEV_RISCV_AIA_CONFIG_HART_BITS	5
+#define KVM_DEV_RISCV_AIA_CONFIG_GUEST_BITS	6
+
+/*
+ * Modes of RISC-V AIA device:
+ * 1) EMUL (aka Emulation): Trap-n-emulate IMSIC
+ * 2) HWACCEL (aka HW Acceleration): Virtualize IMSIC using IMSIC guest files
+ * 3) AUTO (aka Automatic): Virtualize IMSIC using IMSIC guest files whenever
+ *    available otherwise fallback to trap-n-emulation
+ */
+#define KVM_DEV_RISCV_AIA_MODE_EMUL		0
+#define KVM_DEV_RISCV_AIA_MODE_HWACCEL		1
+#define KVM_DEV_RISCV_AIA_MODE_AUTO		2
+
+#define KVM_DEV_RISCV_AIA_IDS_MIN		63
+#define KVM_DEV_RISCV_AIA_IDS_MAX		2048
+#define KVM_DEV_RISCV_AIA_SRCS_MAX		1024
+#define KVM_DEV_RISCV_AIA_GROUP_BITS_MAX	8
+#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN	24
+#define KVM_DEV_RISCV_AIA_GROUP_SHIFT_MAX	56
+#define KVM_DEV_RISCV_AIA_HART_BITS_MAX		16
+#define KVM_DEV_RISCV_AIA_GUEST_BITS_MAX	8
+
+#define KVM_DEV_RISCV_AIA_GRP_ADDR		1
+#define KVM_DEV_RISCV_AIA_ADDR_APLIC		0
+#define KVM_DEV_RISCV_AIA_ADDR_IMSIC(__vcpu)	(1 + (__vcpu))
+#define KVM_DEV_RISCV_AIA_ADDR_MAX		\
+		(1 + KVM_DEV_RISCV_APLIC_MAX_HARTS)
+
+#define KVM_DEV_RISCV_AIA_GRP_CTRL		2
+#define KVM_DEV_RISCV_AIA_CTRL_INIT		0
+
+/*
+ * The device attribute type contains the memory mapped offset of the
+ * APLIC register (range 0x0000-0x3FFF) and it must be 4-byte aligned.
+ */
+#define KVM_DEV_RISCV_AIA_GRP_APLIC		3
+
+/*
+ * The lower 12-bits of the device attribute type contains the iselect
+ * value of the IMSIC register (range 0x70-0xFF) whereas the higher order
+ * bits contains the VCPU id.
+ */
+#define KVM_DEV_RISCV_AIA_GRP_IMSIC		4
+#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS	12
+#define KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK	\
+		((1U << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) - 1)
+#define KVM_DEV_RISCV_AIA_IMSIC_MKATTR(__vcpu, __isel)	\
+		(((__vcpu) << KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS) | \
+		 ((__isel) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK))
+#define KVM_DEV_RISCV_AIA_IMSIC_GET_ISEL(__attr)	\
+		((__attr) & KVM_DEV_RISCV_AIA_IMSIC_ISEL_MASK)
+#define KVM_DEV_RISCV_AIA_IMSIC_GET_VCPU(__attr)	\
+		((__attr) >> KVM_DEV_RISCV_AIA_IMSIC_ISEL_BITS)
+
+/* One single KVM irqchip, ie. the AIA */
+#define KVM_NR_IRQCHIPS			1
+
 #endif
 
 #endif /* __LINUX_KVM_RISCV_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
  2023-09-18 12:57 ` [kvmtool PATCH v2 1/6] Sync-up header with Linux-6.5 for KVM RISC-V Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-10-25 12:54   ` Andrew Jones
  2023-09-18 12:57 ` [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable Anup Patel
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

When the Svnapot extension is available expose it to the guest via
device tree so that guest can use it.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 riscv/fdt.c                         | 1 +
 riscv/include/kvm/kvm-config-arch.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/riscv/fdt.c b/riscv/fdt.c
index df71ed4..2724c6e 100644
--- a/riscv/fdt.c
+++ b/riscv/fdt.c
@@ -19,6 +19,7 @@ struct isa_ext_info isa_info_arr[] = {
 	{"ssaia", KVM_RISCV_ISA_EXT_SSAIA},
 	{"sstc", KVM_RISCV_ISA_EXT_SSTC},
 	{"svinval", KVM_RISCV_ISA_EXT_SVINVAL},
+	{"svnapot", KVM_RISCV_ISA_EXT_SVNAPOT},
 	{"svpbmt", KVM_RISCV_ISA_EXT_SVPBMT},
 	{"zbb", KVM_RISCV_ISA_EXT_ZBB},
 	{"zicbom", KVM_RISCV_ISA_EXT_ZICBOM},
diff --git a/riscv/include/kvm/kvm-config-arch.h b/riscv/include/kvm/kvm-config-arch.h
index b0a7e25..863baea 100644
--- a/riscv/include/kvm/kvm-config-arch.h
+++ b/riscv/include/kvm/kvm-config-arch.h
@@ -34,6 +34,9 @@ struct kvm_config_arch {
 	OPT_BOOLEAN('\0', "disable-svinval",				\
 		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVINVAL],	\
 		    "Disable Svinval Extension"),			\
+	OPT_BOOLEAN('\0', "disable-svnapot",				\
+		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVNAPOT],	\
+		    "Disable Svnapot Extension"),			\
 	OPT_BOOLEAN('\0', "disable-svpbmt",				\
 		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVPBMT],	\
 		    "Disable Svpbmt Extension"),			\
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
  2023-09-18 12:57 ` [kvmtool PATCH v2 1/6] Sync-up header with Linux-6.5 for KVM RISC-V Anup Patel
  2023-09-18 12:57 ` [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-10-25 13:10   ` Andrew Jones
  2023-09-18 12:57 ` [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip Anup Patel
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

We will be having different types of irqchip:
1) PLIC emulated by user-space
2) AIA APLIC and IMSIC provided by in-kernel KVM module

To support above, we de-couple PLIC specific code from generic
RISC-V code (such as FDT generation) so that we can easily add
other types of irqchip.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 riscv/fdt.c                  | 14 ++++++--
 riscv/include/kvm/kvm-arch.h | 25 ++++++++++++---
 riscv/irq.c                  | 62 ++++++++++++++++++++++++++++++++++--
 riscv/kvm.c                  |  2 ++
 riscv/pci.c                  | 32 +++++++++++++------
 riscv/plic.c                 | 61 +++++++++++++++++------------------
 6 files changed, 147 insertions(+), 49 deletions(-)

diff --git a/riscv/fdt.c b/riscv/fdt.c
index 2724c6e..9af71b5 100644
--- a/riscv/fdt.c
+++ b/riscv/fdt.c
@@ -209,19 +209,26 @@ static int setup_fdt(struct kvm *kvm)
 	/* CPUs */
 	generate_cpu_nodes(fdt, kvm);
 
+	/* IRQCHIP */
+	if (!riscv_irqchip_generate_fdt_node)
+		die("No way to generate IRQCHIP FDT node\n");
+	riscv_irqchip_generate_fdt_node(fdt, kvm);
+
 	/* Simple Bus */
 	_FDT(fdt_begin_node(fdt, "smb"));
 	_FDT(fdt_property_string(fdt, "compatible", "simple-bus"));
 	_FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
 	_FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
-	_FDT(fdt_property_cell(fdt, "interrupt-parent", PHANDLE_PLIC));
+	_FDT(fdt_property_cell(fdt, "interrupt-parent",
+			       riscv_irqchip_phandle));
 	_FDT(fdt_property(fdt, "ranges", NULL, 0));
 
 	/* Virtio MMIO devices */
 	dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
 	while (dev_hdr) {
 		generate_mmio_fdt_nodes = dev_hdr->data;
-		generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
+		generate_mmio_fdt_nodes(fdt, dev_hdr,
+					riscv__generate_irq_prop);
 		dev_hdr = device__next_dev(dev_hdr);
 	}
 
@@ -229,7 +236,8 @@ static int setup_fdt(struct kvm *kvm)
 	dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
 	while (dev_hdr) {
 		generate_mmio_fdt_nodes = dev_hdr->data;
-		generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
+		generate_mmio_fdt_nodes(fdt, dev_hdr,
+					riscv__generate_irq_prop);
 		dev_hdr = device__next_dev(dev_hdr);
 	}
 
diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
index 660355b..cd37fc6 100644
--- a/riscv/include/kvm/kvm-arch.h
+++ b/riscv/include/kvm/kvm-arch.h
@@ -10,8 +10,8 @@
 
 #define RISCV_IOPORT		0x00000000ULL
 #define RISCV_IOPORT_SIZE	SZ_64K
-#define RISCV_PLIC		0x0c000000ULL
-#define RISCV_PLIC_SIZE		SZ_64M
+#define RISCV_IRQCHIP		0x08000000ULL
+#define RISCV_IRQCHIP_SIZE		SZ_128M
 #define RISCV_MMIO		0x10000000ULL
 #define RISCV_MMIO_SIZE		SZ_512M
 #define RISCV_PCI		0x30000000ULL
@@ -84,10 +84,27 @@ static inline bool riscv_addr_in_ioport_region(u64 phys_addr)
 
 enum irq_type;
 
-void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
+enum irqchip_type {
+	IRQCHIP_UNKNOWN = 0,
+	IRQCHIP_PLIC,
+	IRQCHIP_AIA
+};
+
+extern enum irqchip_type riscv_irqchip;
+extern bool riscv_irqchip_inkernel;
+extern void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq,
+				     int level, bool edge);
+extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
+extern u32 riscv_irqchip_phandle;
+extern u32 riscv_irqchip_msi_phandle;
+extern bool riscv_irqchip_line_sensing;
 
-void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge);
+void plic__create(struct kvm *kvm);
 
 void pci__generate_fdt_nodes(void *fdt);
 
+void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
+
+void riscv__irqchip_create(struct kvm *kvm);
+
 #endif /* KVM__KVM_ARCH_H */
diff --git a/riscv/irq.c b/riscv/irq.c
index 78a582d..b608a2f 100644
--- a/riscv/irq.c
+++ b/riscv/irq.c
@@ -1,13 +1,71 @@
 #include "kvm/kvm.h"
 #include "kvm/kvm-cpu.h"
 #include "kvm/irq.h"
+#include "kvm/fdt.h"
+#include "kvm/virtio.h"
+
+enum irqchip_type riscv_irqchip = IRQCHIP_UNKNOWN;
+bool riscv_irqchip_inkernel = false;
+void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq, int level, bool edge)
+				= NULL;
+void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
+u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
+u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
+bool riscv_irqchip_line_sensing = false;
 
 void kvm__irq_line(struct kvm *kvm, int irq, int level)
 {
-	plic__irq_trig(kvm, irq, level, false);
+	struct kvm_irq_level irq_level;
+
+	if (riscv_irqchip_inkernel) {
+		irq_level.irq = irq;
+		irq_level.level = !!level;
+		if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
+			pr_warning("%s: Could not KVM_IRQ_LINE for irq %d\n",
+				   __func__, irq);
+	} else {
+		if (riscv_irqchip_trigger)
+			riscv_irqchip_trigger(kvm, irq, level, false);
+		else
+			pr_warning("%s: Can't change level for irq %d\n",
+				   __func__, irq);
+	}
 }
 
 void kvm__irq_trigger(struct kvm *kvm, int irq)
 {
-	plic__irq_trig(kvm, irq, 1, true);
+	if (riscv_irqchip_inkernel) {
+		kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
+		kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
+	} else {
+		if (riscv_irqchip_trigger)
+			riscv_irqchip_trigger(kvm, irq, 1, true);
+		else
+			pr_warning("%s: Can't trigger irq %d\n",
+				   __func__, irq);
+	}
+}
+
+void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
+{
+	u32 prop[2], size;
+
+	prop[0] = cpu_to_fdt32(irq);
+	size = sizeof(u32);
+	if (riscv_irqchip_line_sensing) {
+		prop[1] = cpu_to_fdt32(irq_type);
+		size += sizeof(u32);
+	}
+
+	_FDT(fdt_property(fdt, "interrupts", prop, size));
+}
+
+void riscv__irqchip_create(struct kvm *kvm)
+{
+	/* Try PLIC irqchip */
+	plic__create(kvm);
+
+	/* Fail if irqchip unknown */
+	if (riscv_irqchip == IRQCHIP_UNKNOWN)
+		die("No IRQCHIP found\n");
 }
diff --git a/riscv/kvm.c b/riscv/kvm.c
index 8daad94..1d49479 100644
--- a/riscv/kvm.c
+++ b/riscv/kvm.c
@@ -96,6 +96,8 @@ void kvm__arch_init(struct kvm *kvm)
 
 	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
 		MADV_HUGEPAGE);
+
+	riscv__irqchip_create(kvm);
 }
 
 #define FDT_ALIGN	SZ_4M
diff --git a/riscv/pci.c b/riscv/pci.c
index 604fd20..61dee06 100644
--- a/riscv/pci.c
+++ b/riscv/pci.c
@@ -7,20 +7,21 @@
 
 /*
  * An entry in the interrupt-map table looks like:
- * <pci unit address> <pci interrupt pin> <plic phandle> <plic interrupt>
+ * <pci unit address> <pci interrupt pin> <irqchip phandle> <irqchip line>
  */
 
 struct of_interrupt_map_entry {
 	struct of_pci_irq_mask		pci_irq_mask;
-	u32				plic_phandle;
-	u32				plic_irq;
+	u32				irqchip_phandle;
+	u32				irqchip_line;
+	u32				irqchip_sense;
 } __attribute__((packed));
 
 void pci__generate_fdt_nodes(void *fdt)
 {
 	struct device_header *dev_hdr;
 	struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
-	unsigned nentries = 0;
+	unsigned nentries = 0, nsize;
 	/* Bus range */
 	u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
 	/* Configuration Space */
@@ -48,6 +49,11 @@ void pci__generate_fdt_nodes(void *fdt)
 		},
 	};
 
+	/* Find size of each interrupt map entery */
+	nsize = sizeof(struct of_interrupt_map_entry);
+	if (!riscv_irqchip_line_sensing)
+		nsize -= sizeof(u32);
+
 	/* Boilerplate PCI properties */
 	_FDT(fdt_begin_node(fdt, "pci"));
 	_FDT(fdt_property_string(fdt, "device_type", "pci"));
@@ -64,12 +70,13 @@ void pci__generate_fdt_nodes(void *fdt)
 	/* Generate the interrupt map ... */
 	dev_hdr = device__first_dev(DEVICE_BUS_PCI);
 	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
-		struct of_interrupt_map_entry *entry = &irq_map[nentries];
+		struct of_interrupt_map_entry *entry;
 		struct pci_device_header *pci_hdr = dev_hdr->data;
 		u8 dev_num = dev_hdr->dev_num;
 		u8 pin = pci_hdr->irq_pin;
 		u8 irq = pci_hdr->irq_line;
 
+		entry = ((void *)irq_map) + (nsize * nentries);
 		*entry = (struct of_interrupt_map_entry) {
 			.pci_irq_mask = {
 				.pci_addr = {
@@ -79,16 +86,18 @@ void pci__generate_fdt_nodes(void *fdt)
 				},
 				.pci_pin	= cpu_to_fdt32(pin),
 			},
-			.plic_phandle	= cpu_to_fdt32(PHANDLE_PLIC),
-			.plic_irq	= cpu_to_fdt32(irq),
+			.irqchip_phandle	= cpu_to_fdt32(riscv_irqchip_phandle),
+			.irqchip_line		= cpu_to_fdt32(irq),
 		};
 
+		if (riscv_irqchip_line_sensing)
+			entry->irqchip_sense = cpu_to_fdt32(IRQ_TYPE_LEVEL_HIGH);
+
 		nentries++;
 		dev_hdr = device__next_dev(dev_hdr);
 	}
 
-	_FDT(fdt_property(fdt, "interrupt-map", irq_map,
-			  sizeof(struct of_interrupt_map_entry) * nentries));
+	_FDT(fdt_property(fdt, "interrupt-map", irq_map, nsize * nentries));
 
 	/* ... and the corresponding mask. */
 	if (nentries) {
@@ -105,5 +114,10 @@ void pci__generate_fdt_nodes(void *fdt)
 				  sizeof(irq_mask)));
 	}
 
+	/* Set MSI parent if available */
+	if (riscv_irqchip_msi_phandle != PHANDLE_RESERVED)
+		_FDT(fdt_property_cell(fdt, "msi-parent",
+				       riscv_irqchip_msi_phandle));
+
 	_FDT(fdt_end_node(fdt));
 }
diff --git a/riscv/plic.c b/riscv/plic.c
index 6242286..ab7c574 100644
--- a/riscv/plic.c
+++ b/riscv/plic.c
@@ -118,7 +118,6 @@ struct plic_context {
 struct plic_state {
 	bool ready;
 	struct kvm *kvm;
-	struct device_header dev_hdr;
 
 	/* Static Configuration */
 	u32 num_irq;
@@ -204,7 +203,7 @@ static u32 __plic_context_irq_claim(struct plic_state *s,
 	return best_irq;
 }
 
-void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
+static void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
 {
 	bool irq_marked = false;
 	u8 i, irq_prio, irq_word;
@@ -425,7 +424,7 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
 		die("plic: invalid len=%d", len);
 
 	addr &= ~0x3;
-	addr -= RISCV_PLIC;
+	addr -= RISCV_IRQCHIP;
 
 	if (is_write) {
 		if (PRIORITY_BASE <= addr && addr < ENABLE_BASE) {
@@ -464,34 +463,23 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
 	}
 }
 
-void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
-{
-	u32 irq_prop[] = {
-		cpu_to_fdt32(irq)
-	};
-
-	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
-}
-
-static void plic__generate_fdt_node(void *fdt,
-				    struct device_header *dev_hdr,
-				    void (*generate_irq_prop)(void *fdt,
-							      u8 irq,
-							      enum irq_type))
+static void plic__generate_fdt_node(void *fdt, struct kvm *kvm)
 {
 	u32 i;
+	char name[64];
 	u32 reg_cells[4], *irq_cells;
 
 	reg_cells[0] = 0;
-	reg_cells[1] = cpu_to_fdt32(RISCV_PLIC);
+	reg_cells[1] = cpu_to_fdt32(RISCV_IRQCHIP);
 	reg_cells[2] = 0;
-	reg_cells[3] = cpu_to_fdt32(RISCV_PLIC_SIZE);
+	reg_cells[3] = cpu_to_fdt32(RISCV_IRQCHIP_SIZE);
 
 	irq_cells = calloc(plic.num_context * 2, sizeof(u32));
 	if (!irq_cells)
 		die("Failed to alloc irq_cells");
 
-	_FDT(fdt_begin_node(fdt, "interrupt-controller@0c000000"));
+	sprintf(name, "interrupt-controller@%08x", (u32)RISCV_IRQCHIP);
+	_FDT(fdt_begin_node(fdt, name));
 	_FDT(fdt_property_string(fdt, "compatible", "riscv,plic0"));
 	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
 	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 1));
@@ -518,12 +506,10 @@ static int plic__init(struct kvm *kvm)
 	int ret;
 	struct plic_context *c;
 
-	plic.kvm = kvm;
-	plic.dev_hdr = (struct device_header) {
-		.bus_type	= DEVICE_BUS_MMIO,
-		.data		= plic__generate_fdt_node,
-	};
+	if (riscv_irqchip != IRQCHIP_PLIC)
+		return 0;
 
+	plic.kvm = kvm;
 	plic.num_irq = MAX_DEVICES;
 	plic.num_irq_word = plic.num_irq / 32;
 	if ((plic.num_irq_word * 32) < plic.num_irq)
@@ -544,15 +530,11 @@ static int plic__init(struct kvm *kvm)
 
 	mutex_init(&plic.irq_lock);
 
-	ret = kvm__register_mmio(kvm, RISCV_PLIC, RISCV_PLIC_SIZE,
+	ret = kvm__register_mmio(kvm, RISCV_IRQCHIP, RISCV_IRQCHIP_SIZE,
 				 false, plic__mmio_callback, &plic);
 	if (ret)
 		return ret;
 
-	ret = device__register(&plic.dev_hdr);
-	if (ret)
-		return ret;
-
 	plic.ready = true;
 
 	return 0;
@@ -562,10 +544,27 @@ dev_init(plic__init);
 
 static int plic__exit(struct kvm *kvm)
 {
+	if (riscv_irqchip != IRQCHIP_PLIC)
+		return 0;
+
 	plic.ready = false;
-	kvm__deregister_mmio(kvm, RISCV_PLIC);
+	kvm__deregister_mmio(kvm, RISCV_IRQCHIP);
 	free(plic.contexts);
 
 	return 0;
 }
 dev_exit(plic__exit);
+
+void plic__create(struct kvm *kvm)
+{
+	if (riscv_irqchip != IRQCHIP_UNKNOWN)
+		return;
+
+	riscv_irqchip = IRQCHIP_PLIC;
+	riscv_irqchip_inkernel = false;
+	riscv_irqchip_trigger = plic__irq_trig;
+	riscv_irqchip_generate_fdt_node = plic__generate_fdt_node;
+	riscv_irqchip_phandle = PHANDLE_PLIC;
+	riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
+	riscv_irqchip_line_sensing = false;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
                   ` (2 preceding siblings ...)
  2023-09-18 12:57 ` [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-10-25 13:17   ` Andrew Jones
  2023-09-18 12:57 ` [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports Anup Patel
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

To use irqfd with in-kernel AIA irqchip, we add custom
irq__add_irqfd and irq__del_irqfd functions. This allows
us to defer actual KVM_IRQFD ioctl() until AIA irqchip
is initialized by KVMTOOL.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 riscv/include/kvm/kvm-arch.h | 11 ++++++
 riscv/irq.c                  | 73 ++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+)

diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
index cd37fc6..1a8af6a 100644
--- a/riscv/include/kvm/kvm-arch.h
+++ b/riscv/include/kvm/kvm-arch.h
@@ -98,11 +98,22 @@ extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
 extern u32 riscv_irqchip_phandle;
 extern u32 riscv_irqchip_msi_phandle;
 extern bool riscv_irqchip_line_sensing;
+extern bool riscv_irqchip_irqfd_ready;
 
 void plic__create(struct kvm *kvm);
 
 void pci__generate_fdt_nodes(void *fdt);
 
+int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+		     int resample_fd);
+
+void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
+
+#define irq__add_irqfd riscv__add_irqfd
+#define irq__del_irqfd riscv__del_irqfd
+
+int riscv__setup_irqfd_lines(struct kvm *kvm);
+
 void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
 
 void riscv__irqchip_create(struct kvm *kvm);
diff --git a/riscv/irq.c b/riscv/irq.c
index b608a2f..e6c0939 100644
--- a/riscv/irq.c
+++ b/riscv/irq.c
@@ -12,6 +12,7 @@ void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
 u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
 u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
 bool riscv_irqchip_line_sensing = false;
+bool riscv_irqchip_irqfd_ready = false;
 
 void kvm__irq_line(struct kvm *kvm, int irq, int level)
 {
@@ -46,6 +47,78 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
 	}
 }
 
+struct riscv_irqfd_line {
+	unsigned int		gsi;
+	int			trigger_fd;
+	int			resample_fd;
+	struct list_head	list;
+};
+
+static LIST_HEAD(irqfd_lines);
+
+int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
+		     int resample_fd)
+{
+	struct riscv_irqfd_line *line;
+
+	if (riscv_irqchip_irqfd_ready)
+		return irq__common_add_irqfd(kvm, gsi, trigger_fd,
+					     resample_fd);
+
+	/* Postpone the routing setup until we have a distributor */
+	line = malloc(sizeof(*line));
+	if (!line)
+		return -ENOMEM;
+
+	*line = (struct riscv_irqfd_line) {
+		.gsi		= gsi,
+		.trigger_fd	= trigger_fd,
+		.resample_fd	= resample_fd,
+	};
+	list_add(&line->list, &irqfd_lines);
+
+	return 0;
+}
+
+void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd)
+{
+	struct riscv_irqfd_line *line;
+
+	if (riscv_irqchip_irqfd_ready) {
+		irq__common_del_irqfd(kvm, gsi, trigger_fd);
+		return;
+	}
+
+	list_for_each_entry(line, &irqfd_lines, list) {
+		if (line->gsi != gsi)
+			continue;
+
+		list_del(&line->list);
+		free(line);
+		break;
+	}
+}
+
+int riscv__setup_irqfd_lines(struct kvm *kvm)
+{
+	int ret;
+	struct riscv_irqfd_line *line, *tmp;
+
+	list_for_each_entry_safe(line, tmp, &irqfd_lines, list) {
+		ret = irq__common_add_irqfd(kvm, line->gsi, line->trigger_fd,
+					    line->resample_fd);
+		if (ret < 0) {
+			pr_err("Failed to register IRQFD");
+			return ret;
+		}
+
+		list_del(&line->list);
+		free(line);
+	}
+
+	return 0;
+}
+
 void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
 {
 	u32 prop[2], size;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
                   ` (3 preceding siblings ...)
  2023-09-18 12:57 ` [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-10-25 13:39   ` Andrew Jones
  2023-09-18 12:57 ` [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain Anup Patel
  2023-10-12  4:20 ` [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

The KVM RISC-V kernel module supports AIA in-kernel irqchip when
underlying host has AIA support. We detect and use AIA in-kernel
irqchip whenever possible otherwise we fallback to PLIC emulated
in user-space.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 Makefile                     |   1 +
 riscv/aia.c                  | 227 +++++++++++++++++++++++++++++++++++
 riscv/include/kvm/fdt-arch.h |   8 +-
 riscv/include/kvm/kvm-arch.h |   2 +
 riscv/irq.c                  |   3 +
 5 files changed, 240 insertions(+), 1 deletion(-)
 create mode 100644 riscv/aia.c

diff --git a/Makefile b/Makefile
index e711670..acd5ffd 100644
--- a/Makefile
+++ b/Makefile
@@ -220,6 +220,7 @@ ifeq ($(ARCH),riscv)
 	OBJS		+= riscv/kvm-cpu.o
 	OBJS		+= riscv/pci.o
 	OBJS		+= riscv/plic.o
+	OBJS		+= riscv/aia.o
 	ifeq ($(RISCV_XLEN),32)
 		CFLAGS	+= -mabi=ilp32d -march=rv32gc
 	endif
diff --git a/riscv/aia.c b/riscv/aia.c
new file mode 100644
index 0000000..8c85b3f
--- /dev/null
+++ b/riscv/aia.c
@@ -0,0 +1,227 @@
+#include "kvm/devices.h"
+#include "kvm/fdt.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/irq.h"
+#include "kvm/util.h"
+
+static int aia_fd = -1;
+
+static u32 aia_mode = KVM_DEV_RISCV_AIA_MODE_EMUL;
+static struct kvm_device_attr aia_mode_attr = {
+	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
+	.attr	= KVM_DEV_RISCV_AIA_CONFIG_MODE,
+};
+
+static u32 aia_nr_ids = 0;
+static struct kvm_device_attr aia_nr_ids_attr = {
+	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
+	.attr	= KVM_DEV_RISCV_AIA_CONFIG_IDS,
+};
+
+static u32 aia_nr_sources = 0;
+static struct kvm_device_attr aia_nr_sources_attr = {
+	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
+	.attr	= KVM_DEV_RISCV_AIA_CONFIG_SRCS,
+};
+
+static u32 aia_hart_bits = 0;
+static struct kvm_device_attr aia_hart_bits_attr = {
+	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
+	.attr	= KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
+};
+
+static u32 aia_nr_harts = 0;
+
+#define IRQCHIP_AIA_NR			0
+
+#define AIA_IMSIC_BASE			RISCV_IRQCHIP
+#define AIA_IMSIC_ADDR(__hart)		\
+	(AIA_IMSIC_BASE + (__hart) * KVM_DEV_RISCV_IMSIC_SIZE)
+#define AIA_IMSIC_SIZE			\
+	(aia_nr_harts * KVM_DEV_RISCV_IMSIC_SIZE)
+#define AIA_APLIC_ADDR(__nr_harts)	\
+	(AIA_IMSIC_BASE + (__nr_harts) * KVM_DEV_RISCV_IMSIC_SIZE)
+
+static void aia__generate_fdt_node(void *fdt, struct kvm *kvm)
+{
+	u32 i;
+	char name[64];
+	u32 reg_cells[4], *irq_cells;
+
+	irq_cells = calloc(aia_nr_harts * 2, sizeof(u32));
+	if (!irq_cells)
+		die("Failed to alloc irq_cells");
+
+	sprintf(name, "imsics@%08x", (u32)AIA_IMSIC_BASE);
+	_FDT(fdt_begin_node(fdt, name));
+	_FDT(fdt_property_string(fdt, "compatible", "riscv,imsics"));
+	reg_cells[0] = 0;
+	reg_cells[1] = cpu_to_fdt32(AIA_IMSIC_BASE);
+	reg_cells[2] = 0;
+	reg_cells[3] = cpu_to_fdt32(AIA_IMSIC_SIZE);
+	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
+	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 0));
+	_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
+	_FDT(fdt_property(fdt, "msi-controller", NULL, 0));
+	_FDT(fdt_property_cell(fdt, "riscv,num-ids", aia_nr_ids));
+	_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_IMSIC));
+	for (i = 0; i < aia_nr_harts; i++) {
+		irq_cells[2*i + 0] = cpu_to_fdt32(PHANDLE_CPU_INTC_BASE + i);
+		irq_cells[2*i + 1] = cpu_to_fdt32(9);
+	}
+	_FDT(fdt_property(fdt, "interrupts-extended", irq_cells,
+			  sizeof(u32) * aia_nr_harts * 2));
+	_FDT(fdt_end_node(fdt));
+
+	free(irq_cells);
+
+	/* Skip APLIC node if we have no interrupt sources */
+	if (!aia_nr_sources)
+		return;
+
+	sprintf(name, "aplic@%08x", (u32)AIA_APLIC_ADDR(aia_nr_harts));
+	_FDT(fdt_begin_node(fdt, name));
+	_FDT(fdt_property_string(fdt, "compatible", "riscv,aplic"));
+	reg_cells[0] = 0;
+	reg_cells[1] = cpu_to_fdt32(AIA_APLIC_ADDR(aia_nr_harts));
+	reg_cells[2] = 0;
+	reg_cells[3] = cpu_to_fdt32(KVM_DEV_RISCV_APLIC_SIZE);
+	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
+	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 2));
+	_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
+	_FDT(fdt_property_cell(fdt, "riscv,num-sources", aia_nr_sources));
+	_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_APLIC));
+	_FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_AIA_IMSIC));
+	_FDT(fdt_end_node(fdt));
+}
+
+static int aia__irq_routing_init(struct kvm *kvm)
+{
+	int r;
+	int irqlines = aia_nr_sources + 1;
+
+	/* Skip this if we have no interrupt sources */
+	if (!aia_nr_sources)
+		return 0;
+
+	/*
+	 * This describes the default routing that the kernel uses without
+	 * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we
+	 * don't need to commit these setting right now. The first actual
+	 * user (MSI routing) will engage these mappings then.
+	 */
+	for (next_gsi = 0; next_gsi < irqlines; next_gsi++) {
+		r = irq__allocate_routing_entry();
+		if (r)
+			return r;
+
+		irq_routing->entries[irq_routing->nr++] =
+			(struct kvm_irq_routing_entry) {
+				.gsi = next_gsi,
+				.type = KVM_IRQ_ROUTING_IRQCHIP,
+				.u.irqchip.irqchip = IRQCHIP_AIA_NR,
+				.u.irqchip.pin = next_gsi,
+		};
+	}
+
+	return 0;
+}
+
+static int aia__init(struct kvm *kvm)
+{
+	int i, ret;
+	u64 aia_addr = 0;
+	struct kvm_device_attr aia_addr_attr = {
+		.group	= KVM_DEV_RISCV_AIA_GRP_ADDR,
+		.addr	= (u64)(unsigned long)&aia_addr,
+	};
+	struct kvm_device_attr aia_init_attr = {
+		.group	= KVM_DEV_RISCV_AIA_GRP_CTRL,
+		.attr	= KVM_DEV_RISCV_AIA_CTRL_INIT,
+	};
+
+	/* Setup global device attribute variables */
+	aia_mode_attr.addr = (u64)(unsigned long)&aia_mode;
+	aia_nr_ids_attr.addr = (u64)(unsigned long)&aia_nr_ids;
+	aia_nr_sources_attr.addr = (u64)(unsigned long)&aia_nr_sources;
+	aia_hart_bits_attr.addr = (u64)(unsigned long)&aia_hart_bits;
+
+	/* Do nothing if AIA device not created */
+	if (aia_fd < 0)
+		return 0;
+
+	/* Set/Get AIA device config parameters */
+	ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_mode_attr);
+	if (ret)
+		return ret;
+	ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_nr_ids_attr);
+	if (ret)
+		return ret;
+	aia_nr_sources = irq__get_nr_allocated_lines();
+	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_nr_sources_attr);
+	if (ret)
+		return ret;
+	aia_hart_bits = fls_long(kvm->nrcpus);
+	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_hart_bits_attr);
+	if (ret)
+		return ret;
+
+	/* Save number of HARTs for FDT generation */
+	aia_nr_harts = kvm->nrcpus;
+
+	/* Set AIA device addresses */
+	aia_addr = AIA_APLIC_ADDR(aia_nr_harts);
+	aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_APLIC;
+	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
+	if (ret)
+		return ret;
+	for (i = 0; i < kvm->nrcpus; i++) {
+		aia_addr = AIA_IMSIC_ADDR(i);
+		aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_IMSIC(i);
+		ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
+		if (ret)
+			return ret;
+	}
+
+	/* Setup default IRQ routing */
+	aia__irq_routing_init(kvm);
+
+	/* Initialize the AIA device */
+	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_init_attr);
+	if (ret)
+		return ret;
+
+	/* Mark IRQFD as ready */
+	riscv_irqchip_irqfd_ready = true;
+
+	return 0;
+}
+late_init(aia__init);
+
+void aia__create(struct kvm *kvm)
+{
+	int err;
+	struct kvm_create_device aia_device = {
+		.type = KVM_DEV_TYPE_RISCV_AIA,
+		.flags = 0,
+	};
+
+	if (kvm->cfg.arch.ext_disabled[KVM_RISCV_ISA_EXT_SSAIA])
+		return;
+
+	err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &aia_device);
+	if (err)
+		return;
+	aia_fd = aia_device.fd;
+
+	riscv_irqchip = IRQCHIP_AIA;
+	riscv_irqchip_inkernel = true;
+	riscv_irqchip_trigger = NULL;
+	riscv_irqchip_generate_fdt_node = aia__generate_fdt_node;
+	riscv_irqchip_phandle = PHANDLE_AIA_APLIC;
+	riscv_irqchip_msi_phandle = PHANDLE_AIA_IMSIC;
+	riscv_irqchip_line_sensing = true;
+}
diff --git a/riscv/include/kvm/fdt-arch.h b/riscv/include/kvm/fdt-arch.h
index f7548e8..d88b832 100644
--- a/riscv/include/kvm/fdt-arch.h
+++ b/riscv/include/kvm/fdt-arch.h
@@ -1,7 +1,13 @@
 #ifndef KVM__KVM_FDT_H
 #define KVM__KVM_FDT_H
 
-enum phandles {PHANDLE_RESERVED = 0, PHANDLE_PLIC, PHANDLES_MAX};
+enum phandles {
+	PHANDLE_RESERVED = 0,
+	PHANDLE_PLIC,
+	PHANDLE_AIA_APLIC,
+	PHANDLE_AIA_IMSIC,
+	PHANDLES_MAX
+};
 
 #define PHANDLE_CPU_INTC_BASE	PHANDLES_MAX
 
diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
index 1a8af6a..9f2159f 100644
--- a/riscv/include/kvm/kvm-arch.h
+++ b/riscv/include/kvm/kvm-arch.h
@@ -100,6 +100,8 @@ extern u32 riscv_irqchip_msi_phandle;
 extern bool riscv_irqchip_line_sensing;
 extern bool riscv_irqchip_irqfd_ready;
 
+void aia__create(struct kvm *kvm);
+
 void plic__create(struct kvm *kvm);
 
 void pci__generate_fdt_nodes(void *fdt);
diff --git a/riscv/irq.c b/riscv/irq.c
index e6c0939..be3e7ac 100644
--- a/riscv/irq.c
+++ b/riscv/irq.c
@@ -135,6 +135,9 @@ void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
 
 void riscv__irqchip_create(struct kvm *kvm)
 {
+	/* Try AIA in-kernel irqchip. */
+	aia__create(kvm);
+
 	/* Try PLIC irqchip */
 	plic__create(kvm);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
                   ` (4 preceding siblings ...)
  2023-09-18 12:57 ` [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports Anup Patel
@ 2023-09-18 12:57 ` Anup Patel
  2023-10-25 13:42   ` Andrew Jones
  2023-10-12  4:20 ` [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-09-18 12:57 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv, Anup Patel

For RISC-V multilib toolchains, we must specify -mabi and -march
options when linking guest/init.

Fixes: 2e99678314c2 ("riscv: Initial skeletal support")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Makefile b/Makefile
index acd5ffd..d84dc8e 100644
--- a/Makefile
+++ b/Makefile
@@ -223,9 +223,11 @@ ifeq ($(ARCH),riscv)
 	OBJS		+= riscv/aia.o
 	ifeq ($(RISCV_XLEN),32)
 		CFLAGS	+= -mabi=ilp32d -march=rv32gc
+		GUEST_INIT_FLAGS += -mabi=ilp32d -march=rv32gc
 	endif
 	ifeq ($(RISCV_XLEN),64)
 		CFLAGS	+= -mabi=lp64d -march=rv64gc
+		GUEST_INIT_FLAGS += -mabi=lp64d -march=rv64gc
 	endif
 
 	ARCH_WANT_LIBFDT := y
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support
  2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
                   ` (5 preceding siblings ...)
  2023-09-18 12:57 ` [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain Anup Patel
@ 2023-10-12  4:20 ` Anup Patel
  2023-11-07 11:11   ` Will Deacon
  6 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2023-10-12  4:20 UTC (permalink / raw)
  To: Will Deacon, julien.thierry.kdev, maz
  Cc: Paolo Bonzini, Atish Patra, Andrew Jones, Anup Patel, kvm,
	kvm-riscv

Hi Will,

On Mon, Sep 18, 2023 at 6:27 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> The latest KVM in Linux-6.5 has support for:
> 1) Svnapot ISA extension support
> 2) AIA in-kernel irqchip support
>
> This series adds corresponding changes in KVMTOOL to use the above
> mentioned features for Guest/VM.
>
> These patches can also be found in the riscv_aia_v2 branch at:
> https://github.com/avpatel/kvmtool.git
>
> Changes since v1:
>  - Rebased on commit 9cb1b46cb765972326a46bdba867d441a842af56
>  - Updated PATCH1 to sync header with released Linux-6.5
>
> Anup Patel (6):
>   Sync-up header with Linux-6.5 for KVM RISC-V
>   riscv: Add Svnapot extension support
>   riscv: Make irqchip support pluggable
>   riscv: Add IRQFD support for in-kernel AIA irqchip
>   riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
>   riscv: Fix guest/init linkage for multilib toolchain

Friendly ping ?

>
>  Makefile                            |   3 +
>  include/linux/kvm.h                 |   6 +-
>  riscv/aia.c                         | 227 ++++++++++++++++++++++++++++
>  riscv/fdt.c                         |  15 +-
>  riscv/include/asm/kvm.h             |  81 ++++++++++
>  riscv/include/kvm/fdt-arch.h        |   8 +-
>  riscv/include/kvm/kvm-arch.h        |  38 ++++-
>  riscv/include/kvm/kvm-config-arch.h |   3 +
>  riscv/irq.c                         | 138 ++++++++++++++++-
>  riscv/kvm.c                         |   2 +
>  riscv/pci.c                         |  32 ++--
>  riscv/plic.c                        |  61 ++++----
>  12 files changed, 563 insertions(+), 51 deletions(-)
>  create mode 100644 riscv/aia.c
>
> --
> 2.34.1
>

Regards,
Anup

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support
  2023-09-18 12:57 ` [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support Anup Patel
@ 2023-10-25 12:54   ` Andrew Jones
  0 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2023-10-25 12:54 UTC (permalink / raw)
  To: Anup Patel
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Mon, Sep 18, 2023 at 06:27:26PM +0530, Anup Patel wrote:
> When the Svnapot extension is available expose it to the guest via
> device tree so that guest can use it.
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
>  riscv/fdt.c                         | 1 +
>  riscv/include/kvm/kvm-config-arch.h | 3 +++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/riscv/fdt.c b/riscv/fdt.c
> index df71ed4..2724c6e 100644
> --- a/riscv/fdt.c
> +++ b/riscv/fdt.c
> @@ -19,6 +19,7 @@ struct isa_ext_info isa_info_arr[] = {
>  	{"ssaia", KVM_RISCV_ISA_EXT_SSAIA},
>  	{"sstc", KVM_RISCV_ISA_EXT_SSTC},
>  	{"svinval", KVM_RISCV_ISA_EXT_SVINVAL},
> +	{"svnapot", KVM_RISCV_ISA_EXT_SVNAPOT},
>  	{"svpbmt", KVM_RISCV_ISA_EXT_SVPBMT},
>  	{"zbb", KVM_RISCV_ISA_EXT_ZBB},
>  	{"zicbom", KVM_RISCV_ISA_EXT_ZICBOM},
> diff --git a/riscv/include/kvm/kvm-config-arch.h b/riscv/include/kvm/kvm-config-arch.h
> index b0a7e25..863baea 100644
> --- a/riscv/include/kvm/kvm-config-arch.h
> +++ b/riscv/include/kvm/kvm-config-arch.h
> @@ -34,6 +34,9 @@ struct kvm_config_arch {
>  	OPT_BOOLEAN('\0', "disable-svinval",				\
>  		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVINVAL],	\
>  		    "Disable Svinval Extension"),			\
> +	OPT_BOOLEAN('\0', "disable-svnapot",				\
> +		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVNAPOT],	\
> +		    "Disable Svnapot Extension"),			\
>  	OPT_BOOLEAN('\0', "disable-svpbmt",				\
>  		    &(cfg)->ext_disabled[KVM_RISCV_ISA_EXT_SVPBMT],	\
>  		    "Disable Svpbmt Extension"),			\
> -- 
> 2.34.1
>


Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable
  2023-09-18 12:57 ` [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable Anup Patel
@ 2023-10-25 13:10   ` Andrew Jones
  2023-11-18 12:59     ` Anup Patel
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Jones @ 2023-10-25 13:10 UTC (permalink / raw)
  To: Anup Patel
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Mon, Sep 18, 2023 at 06:27:27PM +0530, Anup Patel wrote:
> We will be having different types of irqchip:
> 1) PLIC emulated by user-space
> 2) AIA APLIC and IMSIC provided by in-kernel KVM module
> 
> To support above, we de-couple PLIC specific code from generic
> RISC-V code (such as FDT generation) so that we can easily add
> other types of irqchip.
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
>  riscv/fdt.c                  | 14 ++++++--
>  riscv/include/kvm/kvm-arch.h | 25 ++++++++++++---
>  riscv/irq.c                  | 62 ++++++++++++++++++++++++++++++++++--
>  riscv/kvm.c                  |  2 ++
>  riscv/pci.c                  | 32 +++++++++++++------
>  riscv/plic.c                 | 61 +++++++++++++++++------------------
>  6 files changed, 147 insertions(+), 49 deletions(-)
> 
> diff --git a/riscv/fdt.c b/riscv/fdt.c
> index 2724c6e..9af71b5 100644
> --- a/riscv/fdt.c
> +++ b/riscv/fdt.c
> @@ -209,19 +209,26 @@ static int setup_fdt(struct kvm *kvm)
>  	/* CPUs */
>  	generate_cpu_nodes(fdt, kvm);
>  
> +	/* IRQCHIP */
> +	if (!riscv_irqchip_generate_fdt_node)
> +		die("No way to generate IRQCHIP FDT node\n");
> +	riscv_irqchip_generate_fdt_node(fdt, kvm);
> +
>  	/* Simple Bus */
>  	_FDT(fdt_begin_node(fdt, "smb"));
>  	_FDT(fdt_property_string(fdt, "compatible", "simple-bus"));
>  	_FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
>  	_FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
> -	_FDT(fdt_property_cell(fdt, "interrupt-parent", PHANDLE_PLIC));
> +	_FDT(fdt_property_cell(fdt, "interrupt-parent",
> +			       riscv_irqchip_phandle));
>  	_FDT(fdt_property(fdt, "ranges", NULL, 0));
>  
>  	/* Virtio MMIO devices */
>  	dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
>  	while (dev_hdr) {
>  		generate_mmio_fdt_nodes = dev_hdr->data;
> -		generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
> +		generate_mmio_fdt_nodes(fdt, dev_hdr,
> +					riscv__generate_irq_prop);
>  		dev_hdr = device__next_dev(dev_hdr);
>  	}
>  
> @@ -229,7 +236,8 @@ static int setup_fdt(struct kvm *kvm)
>  	dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
>  	while (dev_hdr) {
>  		generate_mmio_fdt_nodes = dev_hdr->data;
> -		generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
> +		generate_mmio_fdt_nodes(fdt, dev_hdr,
> +					riscv__generate_irq_prop);
>  		dev_hdr = device__next_dev(dev_hdr);
>  	}

nit: I'd let the above lines run long, but I know you prefer wrapping
     at 80.

>  
> diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> index 660355b..cd37fc6 100644
> --- a/riscv/include/kvm/kvm-arch.h
> +++ b/riscv/include/kvm/kvm-arch.h
> @@ -10,8 +10,8 @@
>  
>  #define RISCV_IOPORT		0x00000000ULL
>  #define RISCV_IOPORT_SIZE	SZ_64K
> -#define RISCV_PLIC		0x0c000000ULL
> -#define RISCV_PLIC_SIZE		SZ_64M
> +#define RISCV_IRQCHIP		0x08000000ULL
> +#define RISCV_IRQCHIP_SIZE		SZ_128M

I checked the applied patch and the SZ_128M is over indented.

>  #define RISCV_MMIO		0x10000000ULL
>  #define RISCV_MMIO_SIZE		SZ_512M
>  #define RISCV_PCI		0x30000000ULL
> @@ -84,10 +84,27 @@ static inline bool riscv_addr_in_ioport_region(u64 phys_addr)
>  
>  enum irq_type;
>  
> -void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
> +enum irqchip_type {
> +	IRQCHIP_UNKNOWN = 0,
> +	IRQCHIP_PLIC,
> +	IRQCHIP_AIA
> +};
> +
> +extern enum irqchip_type riscv_irqchip;
> +extern bool riscv_irqchip_inkernel;
> +extern void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq,
> +				     int level, bool edge);
> +extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
> +extern u32 riscv_irqchip_phandle;
> +extern u32 riscv_irqchip_msi_phandle;
> +extern bool riscv_irqchip_line_sensing;
>  
> -void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge);
> +void plic__create(struct kvm *kvm);
>  
>  void pci__generate_fdt_nodes(void *fdt);
>  
> +void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
> +
> +void riscv__irqchip_create(struct kvm *kvm);
> +
>  #endif /* KVM__KVM_ARCH_H */
> diff --git a/riscv/irq.c b/riscv/irq.c
> index 78a582d..b608a2f 100644
> --- a/riscv/irq.c
> +++ b/riscv/irq.c
> @@ -1,13 +1,71 @@
>  #include "kvm/kvm.h"
>  #include "kvm/kvm-cpu.h"
>  #include "kvm/irq.h"
> +#include "kvm/fdt.h"
> +#include "kvm/virtio.h"
> +
> +enum irqchip_type riscv_irqchip = IRQCHIP_UNKNOWN;
> +bool riscv_irqchip_inkernel = false;
> +void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq, int level, bool edge)
> +				= NULL;
> +void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
> +u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
> +u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
> +bool riscv_irqchip_line_sensing = false;

nit: no need to init BSS symbols with zeros.

>  
>  void kvm__irq_line(struct kvm *kvm, int irq, int level)
>  {
> -	plic__irq_trig(kvm, irq, level, false);
> +	struct kvm_irq_level irq_level;
> +
> +	if (riscv_irqchip_inkernel) {
> +		irq_level.irq = irq;
> +		irq_level.level = !!level;
> +		if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> +			pr_warning("%s: Could not KVM_IRQ_LINE for irq %d\n",
> +				   __func__, irq);
> +	} else {
> +		if (riscv_irqchip_trigger)
> +			riscv_irqchip_trigger(kvm, irq, level, false);
> +		else
> +			pr_warning("%s: Can't change level for irq %d\n",
> +				   __func__, irq);
> +	}
>  }
>  
>  void kvm__irq_trigger(struct kvm *kvm, int irq)
>  {
> -	plic__irq_trig(kvm, irq, 1, true);
> +	if (riscv_irqchip_inkernel) {
> +		kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
> +		kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
> +	} else {
> +		if (riscv_irqchip_trigger)
> +			riscv_irqchip_trigger(kvm, irq, 1, true);
> +		else
> +			pr_warning("%s: Can't trigger irq %d\n",
> +				   __func__, irq);
> +	}
> +}
> +
> +void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> +{
> +	u32 prop[2], size;
> +
> +	prop[0] = cpu_to_fdt32(irq);
> +	size = sizeof(u32);
> +	if (riscv_irqchip_line_sensing) {
> +		prop[1] = cpu_to_fdt32(irq_type);
> +		size += sizeof(u32);
> +	}
> +
> +	_FDT(fdt_property(fdt, "interrupts", prop, size));
> +}
> +
> +void riscv__irqchip_create(struct kvm *kvm)
> +{
> +	/* Try PLIC irqchip */
> +	plic__create(kvm);
> +
> +	/* Fail if irqchip unknown */
> +	if (riscv_irqchip == IRQCHIP_UNKNOWN)
> +		die("No IRQCHIP found\n");
>  }
> diff --git a/riscv/kvm.c b/riscv/kvm.c
> index 8daad94..1d49479 100644
> --- a/riscv/kvm.c
> +++ b/riscv/kvm.c
> @@ -96,6 +96,8 @@ void kvm__arch_init(struct kvm *kvm)
>  
>  	madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
>  		MADV_HUGEPAGE);
> +
> +	riscv__irqchip_create(kvm);
>  }
>  
>  #define FDT_ALIGN	SZ_4M
> diff --git a/riscv/pci.c b/riscv/pci.c
> index 604fd20..61dee06 100644
> --- a/riscv/pci.c
> +++ b/riscv/pci.c
> @@ -7,20 +7,21 @@
>  
>  /*
>   * An entry in the interrupt-map table looks like:
> - * <pci unit address> <pci interrupt pin> <plic phandle> <plic interrupt>
> + * <pci unit address> <pci interrupt pin> <irqchip phandle> <irqchip line>
>   */
>  
>  struct of_interrupt_map_entry {
>  	struct of_pci_irq_mask		pci_irq_mask;
> -	u32				plic_phandle;
> -	u32				plic_irq;
> +	u32				irqchip_phandle;
> +	u32				irqchip_line;
> +	u32				irqchip_sense;
>  } __attribute__((packed));
>  
>  void pci__generate_fdt_nodes(void *fdt)
>  {
>  	struct device_header *dev_hdr;
>  	struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
> -	unsigned nentries = 0;
> +	unsigned nentries = 0, nsize;
>  	/* Bus range */
>  	u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
>  	/* Configuration Space */
> @@ -48,6 +49,11 @@ void pci__generate_fdt_nodes(void *fdt)
>  		},
>  	};
>  
> +	/* Find size of each interrupt map entery */
> +	nsize = sizeof(struct of_interrupt_map_entry);
> +	if (!riscv_irqchip_line_sensing)
> +		nsize -= sizeof(u32);
> +
>  	/* Boilerplate PCI properties */
>  	_FDT(fdt_begin_node(fdt, "pci"));
>  	_FDT(fdt_property_string(fdt, "device_type", "pci"));
> @@ -64,12 +70,13 @@ void pci__generate_fdt_nodes(void *fdt)
>  	/* Generate the interrupt map ... */
>  	dev_hdr = device__first_dev(DEVICE_BUS_PCI);
>  	while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
> -		struct of_interrupt_map_entry *entry = &irq_map[nentries];
> +		struct of_interrupt_map_entry *entry;
>  		struct pci_device_header *pci_hdr = dev_hdr->data;
>  		u8 dev_num = dev_hdr->dev_num;
>  		u8 pin = pci_hdr->irq_pin;
>  		u8 irq = pci_hdr->irq_line;
>  
> +		entry = ((void *)irq_map) + (nsize * nentries);

nit: The outer () of both terms are superfluous.

>  		*entry = (struct of_interrupt_map_entry) {
>  			.pci_irq_mask = {
>  				.pci_addr = {
> @@ -79,16 +86,18 @@ void pci__generate_fdt_nodes(void *fdt)
>  				},
>  				.pci_pin	= cpu_to_fdt32(pin),
>  			},
> -			.plic_phandle	= cpu_to_fdt32(PHANDLE_PLIC),
> -			.plic_irq	= cpu_to_fdt32(irq),
> +			.irqchip_phandle	= cpu_to_fdt32(riscv_irqchip_phandle),
> +			.irqchip_line		= cpu_to_fdt32(irq),
>  		};
>  
> +		if (riscv_irqchip_line_sensing)
> +			entry->irqchip_sense = cpu_to_fdt32(IRQ_TYPE_LEVEL_HIGH);
> +
>  		nentries++;
>  		dev_hdr = device__next_dev(dev_hdr);
>  	}
>  
> -	_FDT(fdt_property(fdt, "interrupt-map", irq_map,
> -			  sizeof(struct of_interrupt_map_entry) * nentries));
> +	_FDT(fdt_property(fdt, "interrupt-map", irq_map, nsize * nentries));
>  
>  	/* ... and the corresponding mask. */
>  	if (nentries) {
> @@ -105,5 +114,10 @@ void pci__generate_fdt_nodes(void *fdt)
>  				  sizeof(irq_mask)));
>  	}
>  
> +	/* Set MSI parent if available */
> +	if (riscv_irqchip_msi_phandle != PHANDLE_RESERVED)
> +		_FDT(fdt_property_cell(fdt, "msi-parent",
> +				       riscv_irqchip_msi_phandle));
> +
>  	_FDT(fdt_end_node(fdt));
>  }
> diff --git a/riscv/plic.c b/riscv/plic.c
> index 6242286..ab7c574 100644
> --- a/riscv/plic.c
> +++ b/riscv/plic.c
> @@ -118,7 +118,6 @@ struct plic_context {
>  struct plic_state {
>  	bool ready;
>  	struct kvm *kvm;
> -	struct device_header dev_hdr;
>  
>  	/* Static Configuration */
>  	u32 num_irq;
> @@ -204,7 +203,7 @@ static u32 __plic_context_irq_claim(struct plic_state *s,
>  	return best_irq;
>  }
>  
> -void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
> +static void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
>  {
>  	bool irq_marked = false;
>  	u8 i, irq_prio, irq_word;
> @@ -425,7 +424,7 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
>  		die("plic: invalid len=%d", len);
>  
>  	addr &= ~0x3;
> -	addr -= RISCV_PLIC;
> +	addr -= RISCV_IRQCHIP;
>  
>  	if (is_write) {
>  		if (PRIORITY_BASE <= addr && addr < ENABLE_BASE) {
> @@ -464,34 +463,23 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
>  	}
>  }
>  
> -void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> -{
> -	u32 irq_prop[] = {
> -		cpu_to_fdt32(irq)
> -	};
> -
> -	_FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
> -}
> -
> -static void plic__generate_fdt_node(void *fdt,
> -				    struct device_header *dev_hdr,
> -				    void (*generate_irq_prop)(void *fdt,
> -							      u8 irq,
> -							      enum irq_type))
> +static void plic__generate_fdt_node(void *fdt, struct kvm *kvm)
>  {
>  	u32 i;
> +	char name[64];
>  	u32 reg_cells[4], *irq_cells;
>  
>  	reg_cells[0] = 0;
> -	reg_cells[1] = cpu_to_fdt32(RISCV_PLIC);
> +	reg_cells[1] = cpu_to_fdt32(RISCV_IRQCHIP);
>  	reg_cells[2] = 0;
> -	reg_cells[3] = cpu_to_fdt32(RISCV_PLIC_SIZE);
> +	reg_cells[3] = cpu_to_fdt32(RISCV_IRQCHIP_SIZE);
>  
>  	irq_cells = calloc(plic.num_context * 2, sizeof(u32));
>  	if (!irq_cells)
>  		die("Failed to alloc irq_cells");
>  
> -	_FDT(fdt_begin_node(fdt, "interrupt-controller@0c000000"));
> +	sprintf(name, "interrupt-controller@%08x", (u32)RISCV_IRQCHIP);
> +	_FDT(fdt_begin_node(fdt, name));
>  	_FDT(fdt_property_string(fdt, "compatible", "riscv,plic0"));
>  	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
>  	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 1));
> @@ -518,12 +506,10 @@ static int plic__init(struct kvm *kvm)
>  	int ret;
>  	struct plic_context *c;
>  
> -	plic.kvm = kvm;
> -	plic.dev_hdr = (struct device_header) {
> -		.bus_type	= DEVICE_BUS_MMIO,
> -		.data		= plic__generate_fdt_node,
> -	};
> +	if (riscv_irqchip != IRQCHIP_PLIC)
> +		return 0;
>  
> +	plic.kvm = kvm;
>  	plic.num_irq = MAX_DEVICES;
>  	plic.num_irq_word = plic.num_irq / 32;
>  	if ((plic.num_irq_word * 32) < plic.num_irq)
> @@ -544,15 +530,11 @@ static int plic__init(struct kvm *kvm)
>  
>  	mutex_init(&plic.irq_lock);
>  
> -	ret = kvm__register_mmio(kvm, RISCV_PLIC, RISCV_PLIC_SIZE,
> +	ret = kvm__register_mmio(kvm, RISCV_IRQCHIP, RISCV_IRQCHIP_SIZE,
>  				 false, plic__mmio_callback, &plic);
>  	if (ret)
>  		return ret;
>  
> -	ret = device__register(&plic.dev_hdr);
> -	if (ret)
> -		return ret;
> -

Dropping this device__register() made me scratch my head a bit. I think
it's not necessary to enumerate the irqchip in the device list and its
fdt node is now generated by riscv_irqchip_generate_fdt_node(), but it'd
be a lot easier for me if the commit message explained why this is OK.

>  	plic.ready = true;
>  
>  	return 0;
> @@ -562,10 +544,27 @@ dev_init(plic__init);
>  
>  static int plic__exit(struct kvm *kvm)
>  {
> +	if (riscv_irqchip != IRQCHIP_PLIC)
> +		return 0;
> +
>  	plic.ready = false;
> -	kvm__deregister_mmio(kvm, RISCV_PLIC);
> +	kvm__deregister_mmio(kvm, RISCV_IRQCHIP);
>  	free(plic.contexts);
>  
>  	return 0;
>  }
>  dev_exit(plic__exit);
> +
> +void plic__create(struct kvm *kvm)
> +{
> +	if (riscv_irqchip != IRQCHIP_UNKNOWN)
> +		return;
> +
> +	riscv_irqchip = IRQCHIP_PLIC;
> +	riscv_irqchip_inkernel = false;
> +	riscv_irqchip_trigger = plic__irq_trig;
> +	riscv_irqchip_generate_fdt_node = plic__generate_fdt_node;
> +	riscv_irqchip_phandle = PHANDLE_PLIC;
> +	riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
> +	riscv_irqchip_line_sensing = false;
> +}
> -- 
> 2.34.1
>

Besides the nits, the whitespace issue, and request for another sentence
in the commit message,

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Thanks,
drew

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip
  2023-09-18 12:57 ` [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip Anup Patel
@ 2023-10-25 13:17   ` Andrew Jones
  2023-11-18 12:59     ` Anup Patel
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Jones @ 2023-10-25 13:17 UTC (permalink / raw)
  To: Anup Patel
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Mon, Sep 18, 2023 at 06:27:28PM +0530, Anup Patel wrote:
> To use irqfd with in-kernel AIA irqchip, we add custom
> irq__add_irqfd and irq__del_irqfd functions. This allows
> us to defer actual KVM_IRQFD ioctl() until AIA irqchip
> is initialized by KVMTOOL.
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
>  riscv/include/kvm/kvm-arch.h | 11 ++++++
>  riscv/irq.c                  | 73 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 84 insertions(+)
> 
> diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> index cd37fc6..1a8af6a 100644
> --- a/riscv/include/kvm/kvm-arch.h
> +++ b/riscv/include/kvm/kvm-arch.h
> @@ -98,11 +98,22 @@ extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
>  extern u32 riscv_irqchip_phandle;
>  extern u32 riscv_irqchip_msi_phandle;
>  extern bool riscv_irqchip_line_sensing;
> +extern bool riscv_irqchip_irqfd_ready;
>  
>  void plic__create(struct kvm *kvm);
>  
>  void pci__generate_fdt_nodes(void *fdt);
>  
> +int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
> +		     int resample_fd);
> +
> +void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
> +
> +#define irq__add_irqfd riscv__add_irqfd
> +#define irq__del_irqfd riscv__del_irqfd
> +
> +int riscv__setup_irqfd_lines(struct kvm *kvm);
> +
>  void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
>  
>  void riscv__irqchip_create(struct kvm *kvm);
> diff --git a/riscv/irq.c b/riscv/irq.c
> index b608a2f..e6c0939 100644
> --- a/riscv/irq.c
> +++ b/riscv/irq.c
> @@ -12,6 +12,7 @@ void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
>  u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
>  u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
>  bool riscv_irqchip_line_sensing = false;
> +bool riscv_irqchip_irqfd_ready = false;
>  
>  void kvm__irq_line(struct kvm *kvm, int irq, int level)
>  {
> @@ -46,6 +47,78 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
>  	}
>  }
>  
> +struct riscv_irqfd_line {
> +	unsigned int		gsi;
> +	int			trigger_fd;
> +	int			resample_fd;
> +	struct list_head	list;
> +};
> +
> +static LIST_HEAD(irqfd_lines);
> +
> +int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
> +		     int resample_fd)
> +{
> +	struct riscv_irqfd_line *line;
> +
> +	if (riscv_irqchip_irqfd_ready)
> +		return irq__common_add_irqfd(kvm, gsi, trigger_fd,
> +					     resample_fd);
> +
> +	/* Postpone the routing setup until we have a distributor */

This comment comes from the Arm code. We probably want to replace
distributor with "until the AIA is initialized" or something.

> +	line = malloc(sizeof(*line));
> +	if (!line)
> +		return -ENOMEM;
> +
> +	*line = (struct riscv_irqfd_line) {
> +		.gsi		= gsi,
> +		.trigger_fd	= trigger_fd,
> +		.resample_fd	= resample_fd,
> +	};
> +	list_add(&line->list, &irqfd_lines);
> +
> +	return 0;
> +}
> +
> +void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd)
> +{
> +	struct riscv_irqfd_line *line;
> +
> +	if (riscv_irqchip_irqfd_ready) {
> +		irq__common_del_irqfd(kvm, gsi, trigger_fd);
> +		return;
> +	}
> +
> +	list_for_each_entry(line, &irqfd_lines, list) {
> +		if (line->gsi != gsi)
> +			continue;
> +
> +		list_del(&line->list);
> +		free(line);
> +		break;
> +	}
> +}
> +
> +int riscv__setup_irqfd_lines(struct kvm *kvm)
> +{
> +	int ret;
> +	struct riscv_irqfd_line *line, *tmp;
> +
> +	list_for_each_entry_safe(line, tmp, &irqfd_lines, list) {
> +		ret = irq__common_add_irqfd(kvm, line->gsi, line->trigger_fd,
> +					    line->resample_fd);
> +		if (ret < 0) {
> +			pr_err("Failed to register IRQFD");
> +			return ret;
> +		}
> +
> +		list_del(&line->list);
> +		free(line);
> +	}
> +
> +	return 0;
> +}
> +
>  void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
>  {
>  	u32 prop[2], size;
> -- 
> 2.34.1
>

Other than the comment,

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
  2023-09-18 12:57 ` [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports Anup Patel
@ 2023-10-25 13:39   ` Andrew Jones
  2023-11-18 13:01     ` Anup Patel
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Jones @ 2023-10-25 13:39 UTC (permalink / raw)
  To: Anup Patel
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Mon, Sep 18, 2023 at 06:27:29PM +0530, Anup Patel wrote:
> The KVM RISC-V kernel module supports AIA in-kernel irqchip when
> underlying host has AIA support. We detect and use AIA in-kernel
> irqchip whenever possible otherwise we fallback to PLIC emulated
> in user-space.
> 
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
>  Makefile                     |   1 +
>  riscv/aia.c                  | 227 +++++++++++++++++++++++++++++++++++
>  riscv/include/kvm/fdt-arch.h |   8 +-
>  riscv/include/kvm/kvm-arch.h |   2 +
>  riscv/irq.c                  |   3 +
>  5 files changed, 240 insertions(+), 1 deletion(-)
>  create mode 100644 riscv/aia.c
> 
> diff --git a/Makefile b/Makefile
> index e711670..acd5ffd 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -220,6 +220,7 @@ ifeq ($(ARCH),riscv)
>  	OBJS		+= riscv/kvm-cpu.o
>  	OBJS		+= riscv/pci.o
>  	OBJS		+= riscv/plic.o
> +	OBJS		+= riscv/aia.o
>  	ifeq ($(RISCV_XLEN),32)
>  		CFLAGS	+= -mabi=ilp32d -march=rv32gc
>  	endif
> diff --git a/riscv/aia.c b/riscv/aia.c
> new file mode 100644
> index 0000000..8c85b3f
> --- /dev/null
> +++ b/riscv/aia.c
> @@ -0,0 +1,227 @@
> +#include "kvm/devices.h"
> +#include "kvm/fdt.h"
> +#include "kvm/ioeventfd.h"
> +#include "kvm/ioport.h"
> +#include "kvm/kvm.h"
> +#include "kvm/kvm-cpu.h"
> +#include "kvm/irq.h"
> +#include "kvm/util.h"
> +
> +static int aia_fd = -1;
> +
> +static u32 aia_mode = KVM_DEV_RISCV_AIA_MODE_EMUL;
> +static struct kvm_device_attr aia_mode_attr = {
> +	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
> +	.attr	= KVM_DEV_RISCV_AIA_CONFIG_MODE,
> +};
> +
> +static u32 aia_nr_ids = 0;
> +static struct kvm_device_attr aia_nr_ids_attr = {
> +	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
> +	.attr	= KVM_DEV_RISCV_AIA_CONFIG_IDS,
> +};
> +
> +static u32 aia_nr_sources = 0;
> +static struct kvm_device_attr aia_nr_sources_attr = {
> +	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
> +	.attr	= KVM_DEV_RISCV_AIA_CONFIG_SRCS,
> +};
> +
> +static u32 aia_hart_bits = 0;
> +static struct kvm_device_attr aia_hart_bits_attr = {
> +	.group	= KVM_DEV_RISCV_AIA_GRP_CONFIG,
> +	.attr	= KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
> +};
> +
> +static u32 aia_nr_harts = 0;
> +
> +#define IRQCHIP_AIA_NR			0
> +
> +#define AIA_IMSIC_BASE			RISCV_IRQCHIP
> +#define AIA_IMSIC_ADDR(__hart)		\
> +	(AIA_IMSIC_BASE + (__hart) * KVM_DEV_RISCV_IMSIC_SIZE)
> +#define AIA_IMSIC_SIZE			\
> +	(aia_nr_harts * KVM_DEV_RISCV_IMSIC_SIZE)
> +#define AIA_APLIC_ADDR(__nr_harts)	\
> +	(AIA_IMSIC_BASE + (__nr_harts) * KVM_DEV_RISCV_IMSIC_SIZE)

AIA_APLIC_ADDR() probably doesn't need to take nr_harts since it's
always called with aia_nr_harts. So it could just be defined as

 #define AIA_APLIC_ADDR (AIA_IMSIC_BASE + AIA_IMSIC_SIZE)

> +
> +static void aia__generate_fdt_node(void *fdt, struct kvm *kvm)
> +{
> +	u32 i;
> +	char name[64];
> +	u32 reg_cells[4], *irq_cells;
> +
> +	irq_cells = calloc(aia_nr_harts * 2, sizeof(u32));
> +	if (!irq_cells)
> +		die("Failed to alloc irq_cells");
> +
> +	sprintf(name, "imsics@%08x", (u32)AIA_IMSIC_BASE);
> +	_FDT(fdt_begin_node(fdt, name));
> +	_FDT(fdt_property_string(fdt, "compatible", "riscv,imsics"));
> +	reg_cells[0] = 0;
> +	reg_cells[1] = cpu_to_fdt32(AIA_IMSIC_BASE);
> +	reg_cells[2] = 0;
> +	reg_cells[3] = cpu_to_fdt32(AIA_IMSIC_SIZE);
> +	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
> +	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 0));
> +	_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> +	_FDT(fdt_property(fdt, "msi-controller", NULL, 0));
> +	_FDT(fdt_property_cell(fdt, "riscv,num-ids", aia_nr_ids));
> +	_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_IMSIC));
> +	for (i = 0; i < aia_nr_harts; i++) {
> +		irq_cells[2*i + 0] = cpu_to_fdt32(PHANDLE_CPU_INTC_BASE + i);
> +		irq_cells[2*i + 1] = cpu_to_fdt32(9);
> +	}
> +	_FDT(fdt_property(fdt, "interrupts-extended", irq_cells,
> +			  sizeof(u32) * aia_nr_harts * 2));
> +	_FDT(fdt_end_node(fdt));
> +
> +	free(irq_cells);
> +
> +	/* Skip APLIC node if we have no interrupt sources */
> +	if (!aia_nr_sources)
> +		return;
> +
> +	sprintf(name, "aplic@%08x", (u32)AIA_APLIC_ADDR(aia_nr_harts));
> +	_FDT(fdt_begin_node(fdt, name));
> +	_FDT(fdt_property_string(fdt, "compatible", "riscv,aplic"));
> +	reg_cells[0] = 0;
> +	reg_cells[1] = cpu_to_fdt32(AIA_APLIC_ADDR(aia_nr_harts));
> +	reg_cells[2] = 0;
> +	reg_cells[3] = cpu_to_fdt32(KVM_DEV_RISCV_APLIC_SIZE);
> +	_FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
> +	_FDT(fdt_property_cell(fdt, "#interrupt-cells", 2));
> +	_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> +	_FDT(fdt_property_cell(fdt, "riscv,num-sources", aia_nr_sources));
> +	_FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_APLIC));
> +	_FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_AIA_IMSIC));
> +	_FDT(fdt_end_node(fdt));
> +}
> +
> +static int aia__irq_routing_init(struct kvm *kvm)
> +{
> +	int r;
> +	int irqlines = aia_nr_sources + 1;
> +
> +	/* Skip this if we have no interrupt sources */
> +	if (!aia_nr_sources)
> +		return 0;
> +
> +	/*
> +	 * This describes the default routing that the kernel uses without
> +	 * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we
> +	 * don't need to commit these setting right now. The first actual
> +	 * user (MSI routing) will engage these mappings then.
> +	 */
> +	for (next_gsi = 0; next_gsi < irqlines; next_gsi++) {
> +		r = irq__allocate_routing_entry();
> +		if (r)
> +			return r;
> +
> +		irq_routing->entries[irq_routing->nr++] =
> +			(struct kvm_irq_routing_entry) {
> +				.gsi = next_gsi,
> +				.type = KVM_IRQ_ROUTING_IRQCHIP,
> +				.u.irqchip.irqchip = IRQCHIP_AIA_NR,
> +				.u.irqchip.pin = next_gsi,
> +		};
> +	}
> +
> +	return 0;
> +}
> +
> +static int aia__init(struct kvm *kvm)
> +{
> +	int i, ret;
> +	u64 aia_addr = 0;
> +	struct kvm_device_attr aia_addr_attr = {
> +		.group	= KVM_DEV_RISCV_AIA_GRP_ADDR,
> +		.addr	= (u64)(unsigned long)&aia_addr,
> +	};
> +	struct kvm_device_attr aia_init_attr = {
> +		.group	= KVM_DEV_RISCV_AIA_GRP_CTRL,
> +		.attr	= KVM_DEV_RISCV_AIA_CTRL_INIT,
> +	};
> +
> +	/* Setup global device attribute variables */
> +	aia_mode_attr.addr = (u64)(unsigned long)&aia_mode;
> +	aia_nr_ids_attr.addr = (u64)(unsigned long)&aia_nr_ids;
> +	aia_nr_sources_attr.addr = (u64)(unsigned long)&aia_nr_sources;
> +	aia_hart_bits_attr.addr = (u64)(unsigned long)&aia_hart_bits;
> +
> +	/* Do nothing if AIA device not created */
> +	if (aia_fd < 0)
> +		return 0;
> +
> +	/* Set/Get AIA device config parameters */
> +	ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_mode_attr);
> +	if (ret)
> +		return ret;
> +	ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_nr_ids_attr);
> +	if (ret)
> +		return ret;
> +	aia_nr_sources = irq__get_nr_allocated_lines();
> +	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_nr_sources_attr);
> +	if (ret)
> +		return ret;
> +	aia_hart_bits = fls_long(kvm->nrcpus);
> +	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_hart_bits_attr);
> +	if (ret)
> +		return ret;
> +
> +	/* Save number of HARTs for FDT generation */
> +	aia_nr_harts = kvm->nrcpus;
> +
> +	/* Set AIA device addresses */
> +	aia_addr = AIA_APLIC_ADDR(aia_nr_harts);
> +	aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_APLIC;
> +	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
> +	if (ret)
> +		return ret;
> +	for (i = 0; i < kvm->nrcpus; i++) {
> +		aia_addr = AIA_IMSIC_ADDR(i);
> +		aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_IMSIC(i);
> +		ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	/* Setup default IRQ routing */
> +	aia__irq_routing_init(kvm);
> +
> +	/* Initialize the AIA device */
> +	ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_init_attr);
> +	if (ret)
> +		return ret;
> +
> +	/* Mark IRQFD as ready */
> +	riscv_irqchip_irqfd_ready = true;
> +
> +	return 0;
> +}
> +late_init(aia__init);
> +
> +void aia__create(struct kvm *kvm)
> +{
> +	int err;
> +	struct kvm_create_device aia_device = {
> +		.type = KVM_DEV_TYPE_RISCV_AIA,
> +		.flags = 0,
> +	};
> +
> +	if (kvm->cfg.arch.ext_disabled[KVM_RISCV_ISA_EXT_SSAIA])
> +		return;
> +
> +	err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &aia_device);
> +	if (err)
> +		return;
> +	aia_fd = aia_device.fd;
> +
> +	riscv_irqchip = IRQCHIP_AIA;
> +	riscv_irqchip_inkernel = true;
> +	riscv_irqchip_trigger = NULL;
> +	riscv_irqchip_generate_fdt_node = aia__generate_fdt_node;
> +	riscv_irqchip_phandle = PHANDLE_AIA_APLIC;
> +	riscv_irqchip_msi_phandle = PHANDLE_AIA_IMSIC;
> +	riscv_irqchip_line_sensing = true;
> +}
> diff --git a/riscv/include/kvm/fdt-arch.h b/riscv/include/kvm/fdt-arch.h
> index f7548e8..d88b832 100644
> --- a/riscv/include/kvm/fdt-arch.h
> +++ b/riscv/include/kvm/fdt-arch.h
> @@ -1,7 +1,13 @@
>  #ifndef KVM__KVM_FDT_H
>  #define KVM__KVM_FDT_H
>  
> -enum phandles {PHANDLE_RESERVED = 0, PHANDLE_PLIC, PHANDLES_MAX};
> +enum phandles {
> +	PHANDLE_RESERVED = 0,
> +	PHANDLE_PLIC,
> +	PHANDLE_AIA_APLIC,
> +	PHANDLE_AIA_IMSIC,
> +	PHANDLES_MAX
> +};
>  
>  #define PHANDLE_CPU_INTC_BASE	PHANDLES_MAX
>  
> diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> index 1a8af6a..9f2159f 100644
> --- a/riscv/include/kvm/kvm-arch.h
> +++ b/riscv/include/kvm/kvm-arch.h
> @@ -100,6 +100,8 @@ extern u32 riscv_irqchip_msi_phandle;
>  extern bool riscv_irqchip_line_sensing;
>  extern bool riscv_irqchip_irqfd_ready;
>  
> +void aia__create(struct kvm *kvm);
> +

nit: I'd remove the blank line between *__create functions.

>  void plic__create(struct kvm *kvm);
>  
>  void pci__generate_fdt_nodes(void *fdt);
> diff --git a/riscv/irq.c b/riscv/irq.c
> index e6c0939..be3e7ac 100644
> --- a/riscv/irq.c
> +++ b/riscv/irq.c
> @@ -135,6 +135,9 @@ void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
>  
>  void riscv__irqchip_create(struct kvm *kvm)
>  {
> +	/* Try AIA in-kernel irqchip. */
> +	aia__create(kvm);
> +
>  	/* Try PLIC irqchip */
>  	plic__create(kvm);

I realize plic__create() just returns if aia__create() successful set up
the irqchip, but structuring this like

 ret = aia__create(kvm);
 if (!ret)
    ret = plic__create(kvm);
 if (!ret)
    die(...);

Might be a little easier to for future readers of the code to grok on
first read.


Either way,

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Thanks,
drew

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain
  2023-09-18 12:57 ` [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain Anup Patel
@ 2023-10-25 13:42   ` Andrew Jones
  0 siblings, 0 replies; 18+ messages in thread
From: Andrew Jones @ 2023-10-25 13:42 UTC (permalink / raw)
  To: Anup Patel
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Mon, Sep 18, 2023 at 06:27:30PM +0530, Anup Patel wrote:
> For RISC-V multilib toolchains, we must specify -mabi and -march
> options when linking guest/init.
> 
> Fixes: 2e99678314c2 ("riscv: Initial skeletal support")
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
>  Makefile | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Makefile b/Makefile
> index acd5ffd..d84dc8e 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -223,9 +223,11 @@ ifeq ($(ARCH),riscv)
>  	OBJS		+= riscv/aia.o
>  	ifeq ($(RISCV_XLEN),32)
>  		CFLAGS	+= -mabi=ilp32d -march=rv32gc
> +		GUEST_INIT_FLAGS += -mabi=ilp32d -march=rv32gc
>  	endif
>  	ifeq ($(RISCV_XLEN),64)
>  		CFLAGS	+= -mabi=lp64d -march=rv64gc
> +		GUEST_INIT_FLAGS += -mabi=lp64d -march=rv64gc
>  	endif
>  
>  	ARCH_WANT_LIBFDT := y
> -- 
> 2.34.1
>

Looks good and like something that could be posted independently of this
series.

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Thanks,
drew

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support
  2023-10-12  4:20 ` [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
@ 2023-11-07 11:11   ` Will Deacon
  2023-11-18 13:52     ` Anup Patel
  0 siblings, 1 reply; 18+ messages in thread
From: Will Deacon @ 2023-11-07 11:11 UTC (permalink / raw)
  To: Anup Patel
  Cc: julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Andrew Jones, Anup Patel, kvm, kvm-riscv

On Thu, Oct 12, 2023 at 09:50:29AM +0530, Anup Patel wrote:
> On Mon, Sep 18, 2023 at 6:27 PM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > The latest KVM in Linux-6.5 has support for:
> > 1) Svnapot ISA extension support
> > 2) AIA in-kernel irqchip support
> >
> > This series adds corresponding changes in KVMTOOL to use the above
> > mentioned features for Guest/VM.
> >
> > These patches can also be found in the riscv_aia_v2 branch at:
> > https://github.com/avpatel/kvmtool.git
> >
> > Changes since v1:
> >  - Rebased on commit 9cb1b46cb765972326a46bdba867d441a842af56
> >  - Updated PATCH1 to sync header with released Linux-6.5
> >
> > Anup Patel (6):
> >   Sync-up header with Linux-6.5 for KVM RISC-V
> >   riscv: Add Svnapot extension support
> >   riscv: Make irqchip support pluggable
> >   riscv: Add IRQFD support for in-kernel AIA irqchip
> >   riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
> >   riscv: Fix guest/init linkage for multilib toolchain
> 
> Friendly ping ?

There are a bunch of open review comments from Drew that need to be
addressed in a subsequent version.

Will

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable
  2023-10-25 13:10   ` Andrew Jones
@ 2023-11-18 12:59     ` Anup Patel
  0 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2023-11-18 12:59 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Wed, Oct 25, 2023 at 6:40 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Mon, Sep 18, 2023 at 06:27:27PM +0530, Anup Patel wrote:
> > We will be having different types of irqchip:
> > 1) PLIC emulated by user-space
> > 2) AIA APLIC and IMSIC provided by in-kernel KVM module
> >
> > To support above, we de-couple PLIC specific code from generic
> > RISC-V code (such as FDT generation) so that we can easily add
> > other types of irqchip.
> >
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> >  riscv/fdt.c                  | 14 ++++++--
> >  riscv/include/kvm/kvm-arch.h | 25 ++++++++++++---
> >  riscv/irq.c                  | 62 ++++++++++++++++++++++++++++++++++--
> >  riscv/kvm.c                  |  2 ++
> >  riscv/pci.c                  | 32 +++++++++++++------
> >  riscv/plic.c                 | 61 +++++++++++++++++------------------
> >  6 files changed, 147 insertions(+), 49 deletions(-)
> >
> > diff --git a/riscv/fdt.c b/riscv/fdt.c
> > index 2724c6e..9af71b5 100644
> > --- a/riscv/fdt.c
> > +++ b/riscv/fdt.c
> > @@ -209,19 +209,26 @@ static int setup_fdt(struct kvm *kvm)
> >       /* CPUs */
> >       generate_cpu_nodes(fdt, kvm);
> >
> > +     /* IRQCHIP */
> > +     if (!riscv_irqchip_generate_fdt_node)
> > +             die("No way to generate IRQCHIP FDT node\n");
> > +     riscv_irqchip_generate_fdt_node(fdt, kvm);
> > +
> >       /* Simple Bus */
> >       _FDT(fdt_begin_node(fdt, "smb"));
> >       _FDT(fdt_property_string(fdt, "compatible", "simple-bus"));
> >       _FDT(fdt_property_cell(fdt, "#address-cells", 0x2));
> >       _FDT(fdt_property_cell(fdt, "#size-cells", 0x2));
> > -     _FDT(fdt_property_cell(fdt, "interrupt-parent", PHANDLE_PLIC));
> > +     _FDT(fdt_property_cell(fdt, "interrupt-parent",
> > +                            riscv_irqchip_phandle));
> >       _FDT(fdt_property(fdt, "ranges", NULL, 0));
> >
> >       /* Virtio MMIO devices */
> >       dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
> >       while (dev_hdr) {
> >               generate_mmio_fdt_nodes = dev_hdr->data;
> > -             generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
> > +             generate_mmio_fdt_nodes(fdt, dev_hdr,
> > +                                     riscv__generate_irq_prop);
> >               dev_hdr = device__next_dev(dev_hdr);
> >       }
> >
> > @@ -229,7 +236,8 @@ static int setup_fdt(struct kvm *kvm)
> >       dev_hdr = device__first_dev(DEVICE_BUS_IOPORT);
> >       while (dev_hdr) {
> >               generate_mmio_fdt_nodes = dev_hdr->data;
> > -             generate_mmio_fdt_nodes(fdt, dev_hdr, plic__generate_irq_prop);
> > +             generate_mmio_fdt_nodes(fdt, dev_hdr,
> > +                                     riscv__generate_irq_prop);
> >               dev_hdr = device__next_dev(dev_hdr);
> >       }
>
> nit: I'd let the above lines run long, but I know you prefer wrapping
>      at 80.
>
> >
> > diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> > index 660355b..cd37fc6 100644
> > --- a/riscv/include/kvm/kvm-arch.h
> > +++ b/riscv/include/kvm/kvm-arch.h
> > @@ -10,8 +10,8 @@
> >
> >  #define RISCV_IOPORT         0x00000000ULL
> >  #define RISCV_IOPORT_SIZE    SZ_64K
> > -#define RISCV_PLIC           0x0c000000ULL
> > -#define RISCV_PLIC_SIZE              SZ_64M
> > +#define RISCV_IRQCHIP                0x08000000ULL
> > +#define RISCV_IRQCHIP_SIZE           SZ_128M
>
> I checked the applied patch and the SZ_128M is over indented.
>
> >  #define RISCV_MMIO           0x10000000ULL
> >  #define RISCV_MMIO_SIZE              SZ_512M
> >  #define RISCV_PCI            0x30000000ULL
> > @@ -84,10 +84,27 @@ static inline bool riscv_addr_in_ioport_region(u64 phys_addr)
> >
> >  enum irq_type;
> >
> > -void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
> > +enum irqchip_type {
> > +     IRQCHIP_UNKNOWN = 0,
> > +     IRQCHIP_PLIC,
> > +     IRQCHIP_AIA
> > +};
> > +
> > +extern enum irqchip_type riscv_irqchip;
> > +extern bool riscv_irqchip_inkernel;
> > +extern void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq,
> > +                                  int level, bool edge);
> > +extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
> > +extern u32 riscv_irqchip_phandle;
> > +extern u32 riscv_irqchip_msi_phandle;
> > +extern bool riscv_irqchip_line_sensing;
> >
> > -void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge);
> > +void plic__create(struct kvm *kvm);
> >
> >  void pci__generate_fdt_nodes(void *fdt);
> >
> > +void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
> > +
> > +void riscv__irqchip_create(struct kvm *kvm);
> > +
> >  #endif /* KVM__KVM_ARCH_H */
> > diff --git a/riscv/irq.c b/riscv/irq.c
> > index 78a582d..b608a2f 100644
> > --- a/riscv/irq.c
> > +++ b/riscv/irq.c
> > @@ -1,13 +1,71 @@
> >  #include "kvm/kvm.h"
> >  #include "kvm/kvm-cpu.h"
> >  #include "kvm/irq.h"
> > +#include "kvm/fdt.h"
> > +#include "kvm/virtio.h"
> > +
> > +enum irqchip_type riscv_irqchip = IRQCHIP_UNKNOWN;
> > +bool riscv_irqchip_inkernel = false;
> > +void (*riscv_irqchip_trigger)(struct kvm *kvm, int irq, int level, bool edge)
> > +                             = NULL;
> > +void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
> > +u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
> > +u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
> > +bool riscv_irqchip_line_sensing = false;
>
> nit: no need to init BSS symbols with zeros.

Okay, I will update.

>
> >
> >  void kvm__irq_line(struct kvm *kvm, int irq, int level)
> >  {
> > -     plic__irq_trig(kvm, irq, level, false);
> > +     struct kvm_irq_level irq_level;
> > +
> > +     if (riscv_irqchip_inkernel) {
> > +             irq_level.irq = irq;
> > +             irq_level.level = !!level;
> > +             if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> > +                     pr_warning("%s: Could not KVM_IRQ_LINE for irq %d\n",
> > +                                __func__, irq);
> > +     } else {
> > +             if (riscv_irqchip_trigger)
> > +                     riscv_irqchip_trigger(kvm, irq, level, false);
> > +             else
> > +                     pr_warning("%s: Can't change level for irq %d\n",
> > +                                __func__, irq);
> > +     }
> >  }
> >
> >  void kvm__irq_trigger(struct kvm *kvm, int irq)
> >  {
> > -     plic__irq_trig(kvm, irq, 1, true);
> > +     if (riscv_irqchip_inkernel) {
> > +             kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH);
> > +             kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW);
> > +     } else {
> > +             if (riscv_irqchip_trigger)
> > +                     riscv_irqchip_trigger(kvm, irq, 1, true);
> > +             else
> > +                     pr_warning("%s: Can't trigger irq %d\n",
> > +                                __func__, irq);
> > +     }
> > +}
> > +
> > +void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> > +{
> > +     u32 prop[2], size;
> > +
> > +     prop[0] = cpu_to_fdt32(irq);
> > +     size = sizeof(u32);
> > +     if (riscv_irqchip_line_sensing) {
> > +             prop[1] = cpu_to_fdt32(irq_type);
> > +             size += sizeof(u32);
> > +     }
> > +
> > +     _FDT(fdt_property(fdt, "interrupts", prop, size));
> > +}
> > +
> > +void riscv__irqchip_create(struct kvm *kvm)
> > +{
> > +     /* Try PLIC irqchip */
> > +     plic__create(kvm);
> > +
> > +     /* Fail if irqchip unknown */
> > +     if (riscv_irqchip == IRQCHIP_UNKNOWN)
> > +             die("No IRQCHIP found\n");
> >  }
> > diff --git a/riscv/kvm.c b/riscv/kvm.c
> > index 8daad94..1d49479 100644
> > --- a/riscv/kvm.c
> > +++ b/riscv/kvm.c
> > @@ -96,6 +96,8 @@ void kvm__arch_init(struct kvm *kvm)
> >
> >       madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> >               MADV_HUGEPAGE);
> > +
> > +     riscv__irqchip_create(kvm);
> >  }
> >
> >  #define FDT_ALIGN    SZ_4M
> > diff --git a/riscv/pci.c b/riscv/pci.c
> > index 604fd20..61dee06 100644
> > --- a/riscv/pci.c
> > +++ b/riscv/pci.c
> > @@ -7,20 +7,21 @@
> >
> >  /*
> >   * An entry in the interrupt-map table looks like:
> > - * <pci unit address> <pci interrupt pin> <plic phandle> <plic interrupt>
> > + * <pci unit address> <pci interrupt pin> <irqchip phandle> <irqchip line>
> >   */
> >
> >  struct of_interrupt_map_entry {
> >       struct of_pci_irq_mask          pci_irq_mask;
> > -     u32                             plic_phandle;
> > -     u32                             plic_irq;
> > +     u32                             irqchip_phandle;
> > +     u32                             irqchip_line;
> > +     u32                             irqchip_sense;
> >  } __attribute__((packed));
> >
> >  void pci__generate_fdt_nodes(void *fdt)
> >  {
> >       struct device_header *dev_hdr;
> >       struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
> > -     unsigned nentries = 0;
> > +     unsigned nentries = 0, nsize;
> >       /* Bus range */
> >       u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
> >       /* Configuration Space */
> > @@ -48,6 +49,11 @@ void pci__generate_fdt_nodes(void *fdt)
> >               },
> >       };
> >
> > +     /* Find size of each interrupt map entery */
> > +     nsize = sizeof(struct of_interrupt_map_entry);
> > +     if (!riscv_irqchip_line_sensing)
> > +             nsize -= sizeof(u32);
> > +
> >       /* Boilerplate PCI properties */
> >       _FDT(fdt_begin_node(fdt, "pci"));
> >       _FDT(fdt_property_string(fdt, "device_type", "pci"));
> > @@ -64,12 +70,13 @@ void pci__generate_fdt_nodes(void *fdt)
> >       /* Generate the interrupt map ... */
> >       dev_hdr = device__first_dev(DEVICE_BUS_PCI);
> >       while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
> > -             struct of_interrupt_map_entry *entry = &irq_map[nentries];
> > +             struct of_interrupt_map_entry *entry;
> >               struct pci_device_header *pci_hdr = dev_hdr->data;
> >               u8 dev_num = dev_hdr->dev_num;
> >               u8 pin = pci_hdr->irq_pin;
> >               u8 irq = pci_hdr->irq_line;
> >
> > +             entry = ((void *)irq_map) + (nsize * nentries);
>
> nit: The outer () of both terms are superfluous.

Okay, I will update.

>
> >               *entry = (struct of_interrupt_map_entry) {
> >                       .pci_irq_mask = {
> >                               .pci_addr = {
> > @@ -79,16 +86,18 @@ void pci__generate_fdt_nodes(void *fdt)
> >                               },
> >                               .pci_pin        = cpu_to_fdt32(pin),
> >                       },
> > -                     .plic_phandle   = cpu_to_fdt32(PHANDLE_PLIC),
> > -                     .plic_irq       = cpu_to_fdt32(irq),
> > +                     .irqchip_phandle        = cpu_to_fdt32(riscv_irqchip_phandle),
> > +                     .irqchip_line           = cpu_to_fdt32(irq),
> >               };
> >
> > +             if (riscv_irqchip_line_sensing)
> > +                     entry->irqchip_sense = cpu_to_fdt32(IRQ_TYPE_LEVEL_HIGH);
> > +
> >               nentries++;
> >               dev_hdr = device__next_dev(dev_hdr);
> >       }
> >
> > -     _FDT(fdt_property(fdt, "interrupt-map", irq_map,
> > -                       sizeof(struct of_interrupt_map_entry) * nentries));
> > +     _FDT(fdt_property(fdt, "interrupt-map", irq_map, nsize * nentries));
> >
> >       /* ... and the corresponding mask. */
> >       if (nentries) {
> > @@ -105,5 +114,10 @@ void pci__generate_fdt_nodes(void *fdt)
> >                                 sizeof(irq_mask)));
> >       }
> >
> > +     /* Set MSI parent if available */
> > +     if (riscv_irqchip_msi_phandle != PHANDLE_RESERVED)
> > +             _FDT(fdt_property_cell(fdt, "msi-parent",
> > +                                    riscv_irqchip_msi_phandle));
> > +
> >       _FDT(fdt_end_node(fdt));
> >  }
> > diff --git a/riscv/plic.c b/riscv/plic.c
> > index 6242286..ab7c574 100644
> > --- a/riscv/plic.c
> > +++ b/riscv/plic.c
> > @@ -118,7 +118,6 @@ struct plic_context {
> >  struct plic_state {
> >       bool ready;
> >       struct kvm *kvm;
> > -     struct device_header dev_hdr;
> >
> >       /* Static Configuration */
> >       u32 num_irq;
> > @@ -204,7 +203,7 @@ static u32 __plic_context_irq_claim(struct plic_state *s,
> >       return best_irq;
> >  }
> >
> > -void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
> > +static void plic__irq_trig(struct kvm *kvm, int irq, int level, bool edge)
> >  {
> >       bool irq_marked = false;
> >       u8 i, irq_prio, irq_word;
> > @@ -425,7 +424,7 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
> >               die("plic: invalid len=%d", len);
> >
> >       addr &= ~0x3;
> > -     addr -= RISCV_PLIC;
> > +     addr -= RISCV_IRQCHIP;
> >
> >       if (is_write) {
> >               if (PRIORITY_BASE <= addr && addr < ENABLE_BASE) {
> > @@ -464,34 +463,23 @@ static void plic__mmio_callback(struct kvm_cpu *vcpu,
> >       }
> >  }
> >
> > -void plic__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> > -{
> > -     u32 irq_prop[] = {
> > -             cpu_to_fdt32(irq)
> > -     };
> > -
> > -     _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
> > -}
> > -
> > -static void plic__generate_fdt_node(void *fdt,
> > -                                 struct device_header *dev_hdr,
> > -                                 void (*generate_irq_prop)(void *fdt,
> > -                                                           u8 irq,
> > -                                                           enum irq_type))
> > +static void plic__generate_fdt_node(void *fdt, struct kvm *kvm)
> >  {
> >       u32 i;
> > +     char name[64];
> >       u32 reg_cells[4], *irq_cells;
> >
> >       reg_cells[0] = 0;
> > -     reg_cells[1] = cpu_to_fdt32(RISCV_PLIC);
> > +     reg_cells[1] = cpu_to_fdt32(RISCV_IRQCHIP);
> >       reg_cells[2] = 0;
> > -     reg_cells[3] = cpu_to_fdt32(RISCV_PLIC_SIZE);
> > +     reg_cells[3] = cpu_to_fdt32(RISCV_IRQCHIP_SIZE);
> >
> >       irq_cells = calloc(plic.num_context * 2, sizeof(u32));
> >       if (!irq_cells)
> >               die("Failed to alloc irq_cells");
> >
> > -     _FDT(fdt_begin_node(fdt, "interrupt-controller@0c000000"));
> > +     sprintf(name, "interrupt-controller@%08x", (u32)RISCV_IRQCHIP);
> > +     _FDT(fdt_begin_node(fdt, name));
> >       _FDT(fdt_property_string(fdt, "compatible", "riscv,plic0"));
> >       _FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
> >       _FDT(fdt_property_cell(fdt, "#interrupt-cells", 1));
> > @@ -518,12 +506,10 @@ static int plic__init(struct kvm *kvm)
> >       int ret;
> >       struct plic_context *c;
> >
> > -     plic.kvm = kvm;
> > -     plic.dev_hdr = (struct device_header) {
> > -             .bus_type       = DEVICE_BUS_MMIO,
> > -             .data           = plic__generate_fdt_node,
> > -     };
> > +     if (riscv_irqchip != IRQCHIP_PLIC)
> > +             return 0;
> >
> > +     plic.kvm = kvm;
> >       plic.num_irq = MAX_DEVICES;
> >       plic.num_irq_word = plic.num_irq / 32;
> >       if ((plic.num_irq_word * 32) < plic.num_irq)
> > @@ -544,15 +530,11 @@ static int plic__init(struct kvm *kvm)
> >
> >       mutex_init(&plic.irq_lock);
> >
> > -     ret = kvm__register_mmio(kvm, RISCV_PLIC, RISCV_PLIC_SIZE,
> > +     ret = kvm__register_mmio(kvm, RISCV_IRQCHIP, RISCV_IRQCHIP_SIZE,
> >                                false, plic__mmio_callback, &plic);
> >       if (ret)
> >               return ret;
> >
> > -     ret = device__register(&plic.dev_hdr);
> > -     if (ret)
> > -             return ret;
> > -
>
> Dropping this device__register() made me scratch my head a bit. I think
> it's not necessary to enumerate the irqchip in the device list and its
> fdt node is now generated by riscv_irqchip_generate_fdt_node(), but it'd
> be a lot easier for me if the commit message explained why this is OK.

Okay, I will update the commit description.

>
> >       plic.ready = true;
> >
> >       return 0;
> > @@ -562,10 +544,27 @@ dev_init(plic__init);
> >
> >  static int plic__exit(struct kvm *kvm)
> >  {
> > +     if (riscv_irqchip != IRQCHIP_PLIC)
> > +             return 0;
> > +
> >       plic.ready = false;
> > -     kvm__deregister_mmio(kvm, RISCV_PLIC);
> > +     kvm__deregister_mmio(kvm, RISCV_IRQCHIP);
> >       free(plic.contexts);
> >
> >       return 0;
> >  }
> >  dev_exit(plic__exit);
> > +
> > +void plic__create(struct kvm *kvm)
> > +{
> > +     if (riscv_irqchip != IRQCHIP_UNKNOWN)
> > +             return;
> > +
> > +     riscv_irqchip = IRQCHIP_PLIC;
> > +     riscv_irqchip_inkernel = false;
> > +     riscv_irqchip_trigger = plic__irq_trig;
> > +     riscv_irqchip_generate_fdt_node = plic__generate_fdt_node;
> > +     riscv_irqchip_phandle = PHANDLE_PLIC;
> > +     riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
> > +     riscv_irqchip_line_sensing = false;
> > +}
> > --
> > 2.34.1
> >
>
> Besides the nits, the whitespace issue, and request for another sentence
> in the commit message,
>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>
> Thanks,
> drew

Regards,
Anup

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip
  2023-10-25 13:17   ` Andrew Jones
@ 2023-11-18 12:59     ` Anup Patel
  0 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2023-11-18 12:59 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Wed, Oct 25, 2023 at 6:47 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Mon, Sep 18, 2023 at 06:27:28PM +0530, Anup Patel wrote:
> > To use irqfd with in-kernel AIA irqchip, we add custom
> > irq__add_irqfd and irq__del_irqfd functions. This allows
> > us to defer actual KVM_IRQFD ioctl() until AIA irqchip
> > is initialized by KVMTOOL.
> >
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> >  riscv/include/kvm/kvm-arch.h | 11 ++++++
> >  riscv/irq.c                  | 73 ++++++++++++++++++++++++++++++++++++
> >  2 files changed, 84 insertions(+)
> >
> > diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> > index cd37fc6..1a8af6a 100644
> > --- a/riscv/include/kvm/kvm-arch.h
> > +++ b/riscv/include/kvm/kvm-arch.h
> > @@ -98,11 +98,22 @@ extern void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm);
> >  extern u32 riscv_irqchip_phandle;
> >  extern u32 riscv_irqchip_msi_phandle;
> >  extern bool riscv_irqchip_line_sensing;
> > +extern bool riscv_irqchip_irqfd_ready;
> >
> >  void plic__create(struct kvm *kvm);
> >
> >  void pci__generate_fdt_nodes(void *fdt);
> >
> > +int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
> > +                  int resample_fd);
> > +
> > +void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
> > +
> > +#define irq__add_irqfd riscv__add_irqfd
> > +#define irq__del_irqfd riscv__del_irqfd
> > +
> > +int riscv__setup_irqfd_lines(struct kvm *kvm);
> > +
> >  void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
> >
> >  void riscv__irqchip_create(struct kvm *kvm);
> > diff --git a/riscv/irq.c b/riscv/irq.c
> > index b608a2f..e6c0939 100644
> > --- a/riscv/irq.c
> > +++ b/riscv/irq.c
> > @@ -12,6 +12,7 @@ void (*riscv_irqchip_generate_fdt_node)(void *fdt, struct kvm *kvm) = NULL;
> >  u32 riscv_irqchip_phandle = PHANDLE_RESERVED;
> >  u32 riscv_irqchip_msi_phandle = PHANDLE_RESERVED;
> >  bool riscv_irqchip_line_sensing = false;
> > +bool riscv_irqchip_irqfd_ready = false;
> >
> >  void kvm__irq_line(struct kvm *kvm, int irq, int level)
> >  {
> > @@ -46,6 +47,78 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
> >       }
> >  }
> >
> > +struct riscv_irqfd_line {
> > +     unsigned int            gsi;
> > +     int                     trigger_fd;
> > +     int                     resample_fd;
> > +     struct list_head        list;
> > +};
> > +
> > +static LIST_HEAD(irqfd_lines);
> > +
> > +int riscv__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
> > +                  int resample_fd)
> > +{
> > +     struct riscv_irqfd_line *line;
> > +
> > +     if (riscv_irqchip_irqfd_ready)
> > +             return irq__common_add_irqfd(kvm, gsi, trigger_fd,
> > +                                          resample_fd);
> > +
> > +     /* Postpone the routing setup until we have a distributor */
>
> This comment comes from the Arm code. We probably want to replace
> distributor with "until the AIA is initialized" or something.

Okay, I will update.

>
> > +     line = malloc(sizeof(*line));
> > +     if (!line)
> > +             return -ENOMEM;
> > +
> > +     *line = (struct riscv_irqfd_line) {
> > +             .gsi            = gsi,
> > +             .trigger_fd     = trigger_fd,
> > +             .resample_fd    = resample_fd,
> > +     };
> > +     list_add(&line->list, &irqfd_lines);
> > +
> > +     return 0;
> > +}
> > +
> > +void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd)
> > +{
> > +     struct riscv_irqfd_line *line;
> > +
> > +     if (riscv_irqchip_irqfd_ready) {
> > +             irq__common_del_irqfd(kvm, gsi, trigger_fd);
> > +             return;
> > +     }
> > +
> > +     list_for_each_entry(line, &irqfd_lines, list) {
> > +             if (line->gsi != gsi)
> > +                     continue;
> > +
> > +             list_del(&line->list);
> > +             free(line);
> > +             break;
> > +     }
> > +}
> > +
> > +int riscv__setup_irqfd_lines(struct kvm *kvm)
> > +{
> > +     int ret;
> > +     struct riscv_irqfd_line *line, *tmp;
> > +
> > +     list_for_each_entry_safe(line, tmp, &irqfd_lines, list) {
> > +             ret = irq__common_add_irqfd(kvm, line->gsi, line->trigger_fd,
> > +                                         line->resample_fd);
> > +             if (ret < 0) {
> > +                     pr_err("Failed to register IRQFD");
> > +                     return ret;
> > +             }
> > +
> > +             list_del(&line->list);
> > +             free(line);
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> >  void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> >  {
> >       u32 prop[2], size;
> > --
> > 2.34.1
> >
>
> Other than the comment,
>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Regards,
Anup

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
  2023-10-25 13:39   ` Andrew Jones
@ 2023-11-18 13:01     ` Anup Patel
  0 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2023-11-18 13:01 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Will Deacon, julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Anup Patel, kvm, kvm-riscv

On Wed, Oct 25, 2023 at 7:09 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Mon, Sep 18, 2023 at 06:27:29PM +0530, Anup Patel wrote:
> > The KVM RISC-V kernel module supports AIA in-kernel irqchip when
> > underlying host has AIA support. We detect and use AIA in-kernel
> > irqchip whenever possible otherwise we fallback to PLIC emulated
> > in user-space.
> >
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> >  Makefile                     |   1 +
> >  riscv/aia.c                  | 227 +++++++++++++++++++++++++++++++++++
> >  riscv/include/kvm/fdt-arch.h |   8 +-
> >  riscv/include/kvm/kvm-arch.h |   2 +
> >  riscv/irq.c                  |   3 +
> >  5 files changed, 240 insertions(+), 1 deletion(-)
> >  create mode 100644 riscv/aia.c
> >
> > diff --git a/Makefile b/Makefile
> > index e711670..acd5ffd 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -220,6 +220,7 @@ ifeq ($(ARCH),riscv)
> >       OBJS            += riscv/kvm-cpu.o
> >       OBJS            += riscv/pci.o
> >       OBJS            += riscv/plic.o
> > +     OBJS            += riscv/aia.o
> >       ifeq ($(RISCV_XLEN),32)
> >               CFLAGS  += -mabi=ilp32d -march=rv32gc
> >       endif
> > diff --git a/riscv/aia.c b/riscv/aia.c
> > new file mode 100644
> > index 0000000..8c85b3f
> > --- /dev/null
> > +++ b/riscv/aia.c
> > @@ -0,0 +1,227 @@
> > +#include "kvm/devices.h"
> > +#include "kvm/fdt.h"
> > +#include "kvm/ioeventfd.h"
> > +#include "kvm/ioport.h"
> > +#include "kvm/kvm.h"
> > +#include "kvm/kvm-cpu.h"
> > +#include "kvm/irq.h"
> > +#include "kvm/util.h"
> > +
> > +static int aia_fd = -1;
> > +
> > +static u32 aia_mode = KVM_DEV_RISCV_AIA_MODE_EMUL;
> > +static struct kvm_device_attr aia_mode_attr = {
> > +     .group  = KVM_DEV_RISCV_AIA_GRP_CONFIG,
> > +     .attr   = KVM_DEV_RISCV_AIA_CONFIG_MODE,
> > +};
> > +
> > +static u32 aia_nr_ids = 0;
> > +static struct kvm_device_attr aia_nr_ids_attr = {
> > +     .group  = KVM_DEV_RISCV_AIA_GRP_CONFIG,
> > +     .attr   = KVM_DEV_RISCV_AIA_CONFIG_IDS,
> > +};
> > +
> > +static u32 aia_nr_sources = 0;
> > +static struct kvm_device_attr aia_nr_sources_attr = {
> > +     .group  = KVM_DEV_RISCV_AIA_GRP_CONFIG,
> > +     .attr   = KVM_DEV_RISCV_AIA_CONFIG_SRCS,
> > +};
> > +
> > +static u32 aia_hart_bits = 0;
> > +static struct kvm_device_attr aia_hart_bits_attr = {
> > +     .group  = KVM_DEV_RISCV_AIA_GRP_CONFIG,
> > +     .attr   = KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
> > +};
> > +
> > +static u32 aia_nr_harts = 0;
> > +
> > +#define IRQCHIP_AIA_NR                       0
> > +
> > +#define AIA_IMSIC_BASE                       RISCV_IRQCHIP
> > +#define AIA_IMSIC_ADDR(__hart)               \
> > +     (AIA_IMSIC_BASE + (__hart) * KVM_DEV_RISCV_IMSIC_SIZE)
> > +#define AIA_IMSIC_SIZE                       \
> > +     (aia_nr_harts * KVM_DEV_RISCV_IMSIC_SIZE)
> > +#define AIA_APLIC_ADDR(__nr_harts)   \
> > +     (AIA_IMSIC_BASE + (__nr_harts) * KVM_DEV_RISCV_IMSIC_SIZE)
>
> AIA_APLIC_ADDR() probably doesn't need to take nr_harts since it's
> always called with aia_nr_harts. So it could just be defined as
>
>  #define AIA_APLIC_ADDR (AIA_IMSIC_BASE + AIA_IMSIC_SIZE)

Okay, I will update.

>
> > +
> > +static void aia__generate_fdt_node(void *fdt, struct kvm *kvm)
> > +{
> > +     u32 i;
> > +     char name[64];
> > +     u32 reg_cells[4], *irq_cells;
> > +
> > +     irq_cells = calloc(aia_nr_harts * 2, sizeof(u32));
> > +     if (!irq_cells)
> > +             die("Failed to alloc irq_cells");
> > +
> > +     sprintf(name, "imsics@%08x", (u32)AIA_IMSIC_BASE);
> > +     _FDT(fdt_begin_node(fdt, name));
> > +     _FDT(fdt_property_string(fdt, "compatible", "riscv,imsics"));
> > +     reg_cells[0] = 0;
> > +     reg_cells[1] = cpu_to_fdt32(AIA_IMSIC_BASE);
> > +     reg_cells[2] = 0;
> > +     reg_cells[3] = cpu_to_fdt32(AIA_IMSIC_SIZE);
> > +     _FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
> > +     _FDT(fdt_property_cell(fdt, "#interrupt-cells", 0));
> > +     _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> > +     _FDT(fdt_property(fdt, "msi-controller", NULL, 0));
> > +     _FDT(fdt_property_cell(fdt, "riscv,num-ids", aia_nr_ids));
> > +     _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_IMSIC));
> > +     for (i = 0; i < aia_nr_harts; i++) {
> > +             irq_cells[2*i + 0] = cpu_to_fdt32(PHANDLE_CPU_INTC_BASE + i);
> > +             irq_cells[2*i + 1] = cpu_to_fdt32(9);
> > +     }
> > +     _FDT(fdt_property(fdt, "interrupts-extended", irq_cells,
> > +                       sizeof(u32) * aia_nr_harts * 2));
> > +     _FDT(fdt_end_node(fdt));
> > +
> > +     free(irq_cells);
> > +
> > +     /* Skip APLIC node if we have no interrupt sources */
> > +     if (!aia_nr_sources)
> > +             return;
> > +
> > +     sprintf(name, "aplic@%08x", (u32)AIA_APLIC_ADDR(aia_nr_harts));
> > +     _FDT(fdt_begin_node(fdt, name));
> > +     _FDT(fdt_property_string(fdt, "compatible", "riscv,aplic"));
> > +     reg_cells[0] = 0;
> > +     reg_cells[1] = cpu_to_fdt32(AIA_APLIC_ADDR(aia_nr_harts));
> > +     reg_cells[2] = 0;
> > +     reg_cells[3] = cpu_to_fdt32(KVM_DEV_RISCV_APLIC_SIZE);
> > +     _FDT(fdt_property(fdt, "reg", reg_cells, sizeof(reg_cells)));
> > +     _FDT(fdt_property_cell(fdt, "#interrupt-cells", 2));
> > +     _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
> > +     _FDT(fdt_property_cell(fdt, "riscv,num-sources", aia_nr_sources));
> > +     _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_AIA_APLIC));
> > +     _FDT(fdt_property_cell(fdt, "msi-parent", PHANDLE_AIA_IMSIC));
> > +     _FDT(fdt_end_node(fdt));
> > +}
> > +
> > +static int aia__irq_routing_init(struct kvm *kvm)
> > +{
> > +     int r;
> > +     int irqlines = aia_nr_sources + 1;
> > +
> > +     /* Skip this if we have no interrupt sources */
> > +     if (!aia_nr_sources)
> > +             return 0;
> > +
> > +     /*
> > +      * This describes the default routing that the kernel uses without
> > +      * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we
> > +      * don't need to commit these setting right now. The first actual
> > +      * user (MSI routing) will engage these mappings then.
> > +      */
> > +     for (next_gsi = 0; next_gsi < irqlines; next_gsi++) {
> > +             r = irq__allocate_routing_entry();
> > +             if (r)
> > +                     return r;
> > +
> > +             irq_routing->entries[irq_routing->nr++] =
> > +                     (struct kvm_irq_routing_entry) {
> > +                             .gsi = next_gsi,
> > +                             .type = KVM_IRQ_ROUTING_IRQCHIP,
> > +                             .u.irqchip.irqchip = IRQCHIP_AIA_NR,
> > +                             .u.irqchip.pin = next_gsi,
> > +             };
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int aia__init(struct kvm *kvm)
> > +{
> > +     int i, ret;
> > +     u64 aia_addr = 0;
> > +     struct kvm_device_attr aia_addr_attr = {
> > +             .group  = KVM_DEV_RISCV_AIA_GRP_ADDR,
> > +             .addr   = (u64)(unsigned long)&aia_addr,
> > +     };
> > +     struct kvm_device_attr aia_init_attr = {
> > +             .group  = KVM_DEV_RISCV_AIA_GRP_CTRL,
> > +             .attr   = KVM_DEV_RISCV_AIA_CTRL_INIT,
> > +     };
> > +
> > +     /* Setup global device attribute variables */
> > +     aia_mode_attr.addr = (u64)(unsigned long)&aia_mode;
> > +     aia_nr_ids_attr.addr = (u64)(unsigned long)&aia_nr_ids;
> > +     aia_nr_sources_attr.addr = (u64)(unsigned long)&aia_nr_sources;
> > +     aia_hart_bits_attr.addr = (u64)(unsigned long)&aia_hart_bits;
> > +
> > +     /* Do nothing if AIA device not created */
> > +     if (aia_fd < 0)
> > +             return 0;
> > +
> > +     /* Set/Get AIA device config parameters */
> > +     ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_mode_attr);
> > +     if (ret)
> > +             return ret;
> > +     ret = ioctl(aia_fd, KVM_GET_DEVICE_ATTR, &aia_nr_ids_attr);
> > +     if (ret)
> > +             return ret;
> > +     aia_nr_sources = irq__get_nr_allocated_lines();
> > +     ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_nr_sources_attr);
> > +     if (ret)
> > +             return ret;
> > +     aia_hart_bits = fls_long(kvm->nrcpus);
> > +     ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_hart_bits_attr);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Save number of HARTs for FDT generation */
> > +     aia_nr_harts = kvm->nrcpus;
> > +
> > +     /* Set AIA device addresses */
> > +     aia_addr = AIA_APLIC_ADDR(aia_nr_harts);
> > +     aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_APLIC;
> > +     ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
> > +     if (ret)
> > +             return ret;
> > +     for (i = 0; i < kvm->nrcpus; i++) {
> > +             aia_addr = AIA_IMSIC_ADDR(i);
> > +             aia_addr_attr.attr = KVM_DEV_RISCV_AIA_ADDR_IMSIC(i);
> > +             ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_addr_attr);
> > +             if (ret)
> > +                     return ret;
> > +     }
> > +
> > +     /* Setup default IRQ routing */
> > +     aia__irq_routing_init(kvm);
> > +
> > +     /* Initialize the AIA device */
> > +     ret = ioctl(aia_fd, KVM_SET_DEVICE_ATTR, &aia_init_attr);
> > +     if (ret)
> > +             return ret;
> > +
> > +     /* Mark IRQFD as ready */
> > +     riscv_irqchip_irqfd_ready = true;
> > +
> > +     return 0;
> > +}
> > +late_init(aia__init);
> > +
> > +void aia__create(struct kvm *kvm)
> > +{
> > +     int err;
> > +     struct kvm_create_device aia_device = {
> > +             .type = KVM_DEV_TYPE_RISCV_AIA,
> > +             .flags = 0,
> > +     };
> > +
> > +     if (kvm->cfg.arch.ext_disabled[KVM_RISCV_ISA_EXT_SSAIA])
> > +             return;
> > +
> > +     err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &aia_device);
> > +     if (err)
> > +             return;
> > +     aia_fd = aia_device.fd;
> > +
> > +     riscv_irqchip = IRQCHIP_AIA;
> > +     riscv_irqchip_inkernel = true;
> > +     riscv_irqchip_trigger = NULL;
> > +     riscv_irqchip_generate_fdt_node = aia__generate_fdt_node;
> > +     riscv_irqchip_phandle = PHANDLE_AIA_APLIC;
> > +     riscv_irqchip_msi_phandle = PHANDLE_AIA_IMSIC;
> > +     riscv_irqchip_line_sensing = true;
> > +}
> > diff --git a/riscv/include/kvm/fdt-arch.h b/riscv/include/kvm/fdt-arch.h
> > index f7548e8..d88b832 100644
> > --- a/riscv/include/kvm/fdt-arch.h
> > +++ b/riscv/include/kvm/fdt-arch.h
> > @@ -1,7 +1,13 @@
> >  #ifndef KVM__KVM_FDT_H
> >  #define KVM__KVM_FDT_H
> >
> > -enum phandles {PHANDLE_RESERVED = 0, PHANDLE_PLIC, PHANDLES_MAX};
> > +enum phandles {
> > +     PHANDLE_RESERVED = 0,
> > +     PHANDLE_PLIC,
> > +     PHANDLE_AIA_APLIC,
> > +     PHANDLE_AIA_IMSIC,
> > +     PHANDLES_MAX
> > +};
> >
> >  #define PHANDLE_CPU_INTC_BASE        PHANDLES_MAX
> >
> > diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
> > index 1a8af6a..9f2159f 100644
> > --- a/riscv/include/kvm/kvm-arch.h
> > +++ b/riscv/include/kvm/kvm-arch.h
> > @@ -100,6 +100,8 @@ extern u32 riscv_irqchip_msi_phandle;
> >  extern bool riscv_irqchip_line_sensing;
> >  extern bool riscv_irqchip_irqfd_ready;
> >
> > +void aia__create(struct kvm *kvm);
> > +
>
> nit: I'd remove the blank line between *__create functions.

Okay, I will update.

>
> >  void plic__create(struct kvm *kvm);
> >
> >  void pci__generate_fdt_nodes(void *fdt);
> > diff --git a/riscv/irq.c b/riscv/irq.c
> > index e6c0939..be3e7ac 100644
> > --- a/riscv/irq.c
> > +++ b/riscv/irq.c
> > @@ -135,6 +135,9 @@ void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
> >
> >  void riscv__irqchip_create(struct kvm *kvm)
> >  {
> > +     /* Try AIA in-kernel irqchip. */
> > +     aia__create(kvm);
> > +
> >       /* Try PLIC irqchip */
> >       plic__create(kvm);
>
> I realize plic__create() just returns if aia__create() successful set up
> the irqchip, but structuring this like
>
>  ret = aia__create(kvm);
>  if (!ret)
>     ret = plic__create(kvm);
>  if (!ret)
>     die(...);
>
> Might be a little easier to for future readers of the code to grok on
> first read.

Okay, I will update it so that it is obvious to readers that __create()
functions are tried one after another until one suceeds.

>
>
> Either way,
>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>
> Thanks,
> drew

Regards,
Anup

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support
  2023-11-07 11:11   ` Will Deacon
@ 2023-11-18 13:52     ` Anup Patel
  0 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2023-11-18 13:52 UTC (permalink / raw)
  To: Will Deacon
  Cc: julien.thierry.kdev, maz, Paolo Bonzini, Atish Patra,
	Andrew Jones, Anup Patel, kvm, kvm-riscv

On Tue, Nov 7, 2023 at 4:41 PM Will Deacon <will@kernel.org> wrote:
>
> On Thu, Oct 12, 2023 at 09:50:29AM +0530, Anup Patel wrote:
> > On Mon, Sep 18, 2023 at 6:27 PM Anup Patel <apatel@ventanamicro.com> wrote:
> > >
> > > The latest KVM in Linux-6.5 has support for:
> > > 1) Svnapot ISA extension support
> > > 2) AIA in-kernel irqchip support
> > >
> > > This series adds corresponding changes in KVMTOOL to use the above
> > > mentioned features for Guest/VM.
> > >
> > > These patches can also be found in the riscv_aia_v2 branch at:
> > > https://github.com/avpatel/kvmtool.git
> > >
> > > Changes since v1:
> > >  - Rebased on commit 9cb1b46cb765972326a46bdba867d441a842af56
> > >  - Updated PATCH1 to sync header with released Linux-6.5
> > >
> > > Anup Patel (6):
> > >   Sync-up header with Linux-6.5 for KVM RISC-V
> > >   riscv: Add Svnapot extension support
> > >   riscv: Make irqchip support pluggable
> > >   riscv: Add IRQFD support for in-kernel AIA irqchip
> > >   riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports
> > >   riscv: Fix guest/init linkage for multilib toolchain
> >
> > Friendly ping ?
>
> There are a bunch of open review comments from Drew that need to be
> addressed in a subsequent version.

I have sent-out v3 with Drew's comments addressed.

Thanks,
Anup

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2023-11-18 13:52 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-18 12:57 [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
2023-09-18 12:57 ` [kvmtool PATCH v2 1/6] Sync-up header with Linux-6.5 for KVM RISC-V Anup Patel
2023-09-18 12:57 ` [kvmtool PATCH v2 2/6] riscv: Add Svnapot extension support Anup Patel
2023-10-25 12:54   ` Andrew Jones
2023-09-18 12:57 ` [kvmtool PATCH v2 3/6] riscv: Make irqchip support pluggable Anup Patel
2023-10-25 13:10   ` Andrew Jones
2023-11-18 12:59     ` Anup Patel
2023-09-18 12:57 ` [kvmtool PATCH v2 4/6] riscv: Add IRQFD support for in-kernel AIA irqchip Anup Patel
2023-10-25 13:17   ` Andrew Jones
2023-11-18 12:59     ` Anup Patel
2023-09-18 12:57 ` [kvmtool PATCH v2 5/6] riscv: Use AIA in-kernel irqchip whenever KVM RISC-V supports Anup Patel
2023-10-25 13:39   ` Andrew Jones
2023-11-18 13:01     ` Anup Patel
2023-09-18 12:57 ` [kvmtool PATCH v2 6/6] riscv: Fix guest/init linkage for multilib toolchain Anup Patel
2023-10-25 13:42   ` Andrew Jones
2023-10-12  4:20 ` [kvmtool PATCH v2 0/6] RISC-V AIA irqchip and Svnapot support Anup Patel
2023-11-07 11:11   ` Will Deacon
2023-11-18 13:52     ` Anup Patel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox