Some KVM backends, such as Gunyah, require irqfd structures to carry platform-specific state or setup logic. To support these use cases, introduce three weakly-defined functions: - kvm_arch_irqfd_alloc() - kvm_arch_irqfd_free() - kvm_arch_irqfd_init() These allow KVM backends to override irqfd allocation, teardown, and initialization logic. The default implementations simply allocate/finalize a standard `struct kvm_kernel_irqfd`, maintaining existing behaviour. This change is required by the Gunyah backend, which uses these hooks to associate irqfd objects with Gunyah-specific bell resource handles for IRQ injection via hypercalls. Signed-off-by: Karim Manaouil <karim.manaouil@xxxxxxxxxx> --- include/linux/kvm_irqfd.h | 4 ++++ virt/kvm/eventfd.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/linux/kvm_irqfd.h b/include/linux/kvm_irqfd.h index 8ad43692e3bb..e8d21d443c58 100644 --- a/include/linux/kvm_irqfd.h +++ b/include/linux/kvm_irqfd.h @@ -61,4 +61,8 @@ struct kvm_kernel_irqfd { struct irq_bypass_producer *producer; }; +struct kvm_kernel_irqfd *kvm_arch_irqfd_alloc(void); +void kvm_arch_irqfd_free(struct kvm_kernel_irqfd *irqfd); +int kvm_arch_irqfd_init(struct kvm_kernel_irqfd *irqfd); + #endif /* __LINUX_KVM_IRQFD_H */ diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 11e5d1e3f12e..5f3776a1b960 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -32,6 +32,24 @@ static struct workqueue_struct *irqfd_cleanup_wq; +struct kvm_kernel_irqfd __attribute__((weak)) +*kvm_arch_irqfd_alloc(void) +{ + return kzalloc(sizeof(struct kvm_kernel_irqfd), GFP_KERNEL_ACCOUNT); +} + +void __attribute__((weak)) +kvm_arch_irqfd_free(struct kvm_kernel_irqfd *irqfd) +{ + kfree(irqfd); +} + +int __attribute__((weak)) +kvm_arch_irqfd_init(struct kvm_kernel_irqfd *irqfd) +{ + return 0; +} + bool __attribute__((weak)) kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args) { @@ -153,7 +171,7 @@ irqfd_shutdown(struct work_struct *work) irq_bypass_unregister_consumer(&irqfd->consumer); #endif eventfd_ctx_put(irqfd->eventfd); - kfree(irqfd); + kvm_arch_irqfd_free(irqfd); } @@ -315,7 +333,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) if (!kvm_arch_irqfd_allowed(kvm, args)) return -EINVAL; - irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT); + irqfd = kvm_arch_irqfd_alloc(); if (!irqfd) return -ENOMEM; @@ -396,6 +414,13 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup); init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc); + /* + * Give a chance to archiectures to finish initilization. + * E.g. Gunyah needs to register a resource ticket for this irq. + */ + if (kvm_arch_irqfd_init(irqfd)) + goto fail; + spin_lock_irq(&kvm->irqfds.lock); ret = 0; @@ -452,7 +477,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) eventfd_ctx_put(eventfd); out: - kfree(irqfd); + kvm_arch_irqfd_free(irqfd); return ret; } -- 2.39.5