aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnup Patel <apatel@ventanamicro.com>2023-11-18 18:58:45 +0530
committerWill Deacon <will@kernel.org>2023-11-21 15:33:08 +0000
commit17aab306ad146d051646953e24ff044d830617e7 (patch)
tree1f248991c2b63773a19442711d6a48dcaa1d8d95
parent0dff350174f8da2b65dd43a3e569e5377f4ee906 (diff)
downloadkvmtool-17aab306ad146d051646953e24ff044d830617e7.tar.gz
riscv: Add IRQFD support for in-kernel AIA irqchip
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> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Link: https://lore.kernel.org/r/20231118132847.758785-5-apatel@ventanamicro.com Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--riscv/include/kvm/kvm-arch.h11
-rw-r--r--riscv/irq.c73
2 files changed, 84 insertions, 0 deletions
diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
index 2c954ca6..edff1efc 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 043b681d..b99a0552 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;
+bool riscv_irqchip_irqfd_ready;
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 irqchip is initialized */
+ 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;