162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * kvm eventfd support - use eventfd objects to signal various KVM events 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2009 Novell. All Rights Reserved. 662306a36Sopenharmony_ci * Copyright 2010 Red Hat, Inc. and/or its affiliates. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: 962306a36Sopenharmony_ci * Gregory Haskins <ghaskins@novell.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kvm_host.h> 1362306a36Sopenharmony_ci#include <linux/kvm.h> 1462306a36Sopenharmony_ci#include <linux/kvm_irqfd.h> 1562306a36Sopenharmony_ci#include <linux/workqueue.h> 1662306a36Sopenharmony_ci#include <linux/syscalls.h> 1762306a36Sopenharmony_ci#include <linux/wait.h> 1862306a36Sopenharmony_ci#include <linux/poll.h> 1962306a36Sopenharmony_ci#include <linux/file.h> 2062306a36Sopenharmony_ci#include <linux/list.h> 2162306a36Sopenharmony_ci#include <linux/eventfd.h> 2262306a36Sopenharmony_ci#include <linux/kernel.h> 2362306a36Sopenharmony_ci#include <linux/srcu.h> 2462306a36Sopenharmony_ci#include <linux/slab.h> 2562306a36Sopenharmony_ci#include <linux/seqlock.h> 2662306a36Sopenharmony_ci#include <linux/irqbypass.h> 2762306a36Sopenharmony_ci#include <trace/events/kvm.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <kvm/iodev.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQFD 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic struct workqueue_struct *irqfd_cleanup_wq; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cibool __attribute__((weak)) 3662306a36Sopenharmony_cikvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci return true; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic void 4262306a36Sopenharmony_ciirqfd_inject(struct work_struct *work) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 4562306a36Sopenharmony_ci container_of(work, struct kvm_kernel_irqfd, inject); 4662306a36Sopenharmony_ci struct kvm *kvm = irqfd->kvm; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci if (!irqfd->resampler) { 4962306a36Sopenharmony_ci kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 1, 5062306a36Sopenharmony_ci false); 5162306a36Sopenharmony_ci kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irqfd->gsi, 0, 5262306a36Sopenharmony_ci false); 5362306a36Sopenharmony_ci } else 5462306a36Sopenharmony_ci kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, 5562306a36Sopenharmony_ci irqfd->gsi, 1, false); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void irqfd_resampler_notify(struct kvm_kernel_irqfd_resampler *resampler) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link, 6362306a36Sopenharmony_ci srcu_read_lock_held(&resampler->kvm->irq_srcu)) 6462306a36Sopenharmony_ci eventfd_signal(irqfd->resamplefd, 1); 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci/* 6862306a36Sopenharmony_ci * Since resampler irqfds share an IRQ source ID, we de-assert once 6962306a36Sopenharmony_ci * then notify all of the resampler irqfds using this GSI. We can't 7062306a36Sopenharmony_ci * do multiple de-asserts or we risk racing with incoming re-asserts. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_cistatic void 7362306a36Sopenharmony_ciirqfd_resampler_ack(struct kvm_irq_ack_notifier *kian) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci struct kvm_kernel_irqfd_resampler *resampler; 7662306a36Sopenharmony_ci struct kvm *kvm; 7762306a36Sopenharmony_ci int idx; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci resampler = container_of(kian, 8062306a36Sopenharmony_ci struct kvm_kernel_irqfd_resampler, notifier); 8162306a36Sopenharmony_ci kvm = resampler->kvm; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, 8462306a36Sopenharmony_ci resampler->notifier.gsi, 0, false); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 8762306a36Sopenharmony_ci irqfd_resampler_notify(resampler); 8862306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic void 9262306a36Sopenharmony_ciirqfd_resampler_shutdown(struct kvm_kernel_irqfd *irqfd) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct kvm_kernel_irqfd_resampler *resampler = irqfd->resampler; 9562306a36Sopenharmony_ci struct kvm *kvm = resampler->kvm; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci mutex_lock(&kvm->irqfds.resampler_lock); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci list_del_rcu(&irqfd->resampler_link); 10062306a36Sopenharmony_ci synchronize_srcu(&kvm->irq_srcu); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (list_empty(&resampler->list)) { 10362306a36Sopenharmony_ci list_del_rcu(&resampler->link); 10462306a36Sopenharmony_ci kvm_unregister_irq_ack_notifier(kvm, &resampler->notifier); 10562306a36Sopenharmony_ci /* 10662306a36Sopenharmony_ci * synchronize_srcu(&kvm->irq_srcu) already called 10762306a36Sopenharmony_ci * in kvm_unregister_irq_ack_notifier(). 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ci kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID, 11062306a36Sopenharmony_ci resampler->notifier.gsi, 0, false); 11162306a36Sopenharmony_ci kfree(resampler); 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci mutex_unlock(&kvm->irqfds.resampler_lock); 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * Race-free decouple logic (ordering is critical) 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_cistatic void 12162306a36Sopenharmony_ciirqfd_shutdown(struct work_struct *work) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 12462306a36Sopenharmony_ci container_of(work, struct kvm_kernel_irqfd, shutdown); 12562306a36Sopenharmony_ci struct kvm *kvm = irqfd->kvm; 12662306a36Sopenharmony_ci u64 cnt; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Make sure irqfd has been initialized in assign path. */ 12962306a36Sopenharmony_ci synchronize_srcu(&kvm->irq_srcu); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * Synchronize with the wait-queue and unhook ourselves to prevent 13362306a36Sopenharmony_ci * further events. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* 13862306a36Sopenharmony_ci * We know no new events will be scheduled at this point, so block 13962306a36Sopenharmony_ci * until all previously outstanding events have completed 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_ci flush_work(&irqfd->inject); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci if (irqfd->resampler) { 14462306a36Sopenharmony_ci irqfd_resampler_shutdown(irqfd); 14562306a36Sopenharmony_ci eventfd_ctx_put(irqfd->resamplefd); 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * It is now safe to release the object's resources 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS 15262306a36Sopenharmony_ci irq_bypass_unregister_consumer(&irqfd->consumer); 15362306a36Sopenharmony_ci#endif 15462306a36Sopenharmony_ci eventfd_ctx_put(irqfd->eventfd); 15562306a36Sopenharmony_ci kfree(irqfd); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* assumes kvm->irqfds.lock is held */ 16062306a36Sopenharmony_cistatic bool 16162306a36Sopenharmony_ciirqfd_is_active(struct kvm_kernel_irqfd *irqfd) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci return list_empty(&irqfd->list) ? false : true; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci/* 16762306a36Sopenharmony_ci * Mark the irqfd as inactive and schedule it for removal 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * assumes kvm->irqfds.lock is held 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_cistatic void 17262306a36Sopenharmony_ciirqfd_deactivate(struct kvm_kernel_irqfd *irqfd) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci BUG_ON(!irqfd_is_active(irqfd)); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci list_del_init(&irqfd->list); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci queue_work(irqfd_cleanup_wq, &irqfd->shutdown); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciint __attribute__((weak)) kvm_arch_set_irq_inatomic( 18262306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry *irq, 18362306a36Sopenharmony_ci struct kvm *kvm, int irq_source_id, 18462306a36Sopenharmony_ci int level, 18562306a36Sopenharmony_ci bool line_status) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci return -EWOULDBLOCK; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/* 19162306a36Sopenharmony_ci * Called with wqh->lock held and interrupts disabled 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_cistatic int 19462306a36Sopenharmony_ciirqfd_wakeup(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 19762306a36Sopenharmony_ci container_of(wait, struct kvm_kernel_irqfd, wait); 19862306a36Sopenharmony_ci __poll_t flags = key_to_poll(key); 19962306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry irq; 20062306a36Sopenharmony_ci struct kvm *kvm = irqfd->kvm; 20162306a36Sopenharmony_ci unsigned seq; 20262306a36Sopenharmony_ci int idx; 20362306a36Sopenharmony_ci int ret = 0; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (flags & EPOLLIN) { 20662306a36Sopenharmony_ci u64 cnt; 20762306a36Sopenharmony_ci eventfd_ctx_do_read(irqfd->eventfd, &cnt); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 21062306a36Sopenharmony_ci do { 21162306a36Sopenharmony_ci seq = read_seqcount_begin(&irqfd->irq_entry_sc); 21262306a36Sopenharmony_ci irq = irqfd->irq_entry; 21362306a36Sopenharmony_ci } while (read_seqcount_retry(&irqfd->irq_entry_sc, seq)); 21462306a36Sopenharmony_ci /* An event has been signaled, inject an interrupt */ 21562306a36Sopenharmony_ci if (kvm_arch_set_irq_inatomic(&irq, kvm, 21662306a36Sopenharmony_ci KVM_USERSPACE_IRQ_SOURCE_ID, 1, 21762306a36Sopenharmony_ci false) == -EWOULDBLOCK) 21862306a36Sopenharmony_ci schedule_work(&irqfd->inject); 21962306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 22062306a36Sopenharmony_ci ret = 1; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (flags & EPOLLHUP) { 22462306a36Sopenharmony_ci /* The eventfd is closing, detach from KVM */ 22562306a36Sopenharmony_ci unsigned long iflags; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci spin_lock_irqsave(&kvm->irqfds.lock, iflags); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* 23062306a36Sopenharmony_ci * We must check if someone deactivated the irqfd before 23162306a36Sopenharmony_ci * we could acquire the irqfds.lock since the item is 23262306a36Sopenharmony_ci * deactivated from the KVM side before it is unhooked from 23362306a36Sopenharmony_ci * the wait-queue. If it is already deactivated, we can 23462306a36Sopenharmony_ci * simply return knowing the other side will cleanup for us. 23562306a36Sopenharmony_ci * We cannot race against the irqfd going away since the 23662306a36Sopenharmony_ci * other side is required to acquire wqh->lock, which we hold 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci if (irqfd_is_active(irqfd)) 23962306a36Sopenharmony_ci irqfd_deactivate(irqfd); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci spin_unlock_irqrestore(&kvm->irqfds.lock, iflags); 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return ret; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic void 24862306a36Sopenharmony_ciirqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, 24962306a36Sopenharmony_ci poll_table *pt) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd = 25262306a36Sopenharmony_ci container_of(pt, struct kvm_kernel_irqfd, pt); 25362306a36Sopenharmony_ci add_wait_queue_priority(wqh, &irqfd->wait); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/* Must be called under irqfds.lock */ 25762306a36Sopenharmony_cistatic void irqfd_update(struct kvm *kvm, struct kvm_kernel_irqfd *irqfd) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry *e; 26062306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; 26162306a36Sopenharmony_ci int n_entries; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci n_entries = kvm_irq_map_gsi(kvm, entries, irqfd->gsi); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci write_seqcount_begin(&irqfd->irq_entry_sc); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci e = entries; 26862306a36Sopenharmony_ci if (n_entries == 1) 26962306a36Sopenharmony_ci irqfd->irq_entry = *e; 27062306a36Sopenharmony_ci else 27162306a36Sopenharmony_ci irqfd->irq_entry.type = 0; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci write_seqcount_end(&irqfd->irq_entry_sc); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS 27762306a36Sopenharmony_civoid __attribute__((weak)) kvm_arch_irq_bypass_stop( 27862306a36Sopenharmony_ci struct irq_bypass_consumer *cons) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_civoid __attribute__((weak)) kvm_arch_irq_bypass_start( 28362306a36Sopenharmony_ci struct irq_bypass_consumer *cons) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciint __attribute__((weak)) kvm_arch_update_irqfd_routing( 28862306a36Sopenharmony_ci struct kvm *kvm, unsigned int host_irq, 28962306a36Sopenharmony_ci uint32_t guest_irq, bool set) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cibool __attribute__((weak)) kvm_arch_irqfd_route_changed( 29562306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry *old, 29662306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry *new) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci return true; 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci#endif 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic int 30362306a36Sopenharmony_cikvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd, *tmp; 30662306a36Sopenharmony_ci struct fd f; 30762306a36Sopenharmony_ci struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; 30862306a36Sopenharmony_ci int ret; 30962306a36Sopenharmony_ci __poll_t events; 31062306a36Sopenharmony_ci int idx; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (!kvm_arch_intc_initialized(kvm)) 31362306a36Sopenharmony_ci return -EAGAIN; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (!kvm_arch_irqfd_allowed(kvm, args)) 31662306a36Sopenharmony_ci return -EINVAL; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT); 31962306a36Sopenharmony_ci if (!irqfd) 32062306a36Sopenharmony_ci return -ENOMEM; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci irqfd->kvm = kvm; 32362306a36Sopenharmony_ci irqfd->gsi = args->gsi; 32462306a36Sopenharmony_ci INIT_LIST_HEAD(&irqfd->list); 32562306a36Sopenharmony_ci INIT_WORK(&irqfd->inject, irqfd_inject); 32662306a36Sopenharmony_ci INIT_WORK(&irqfd->shutdown, irqfd_shutdown); 32762306a36Sopenharmony_ci seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci f = fdget(args->fd); 33062306a36Sopenharmony_ci if (!f.file) { 33162306a36Sopenharmony_ci ret = -EBADF; 33262306a36Sopenharmony_ci goto out; 33362306a36Sopenharmony_ci } 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci eventfd = eventfd_ctx_fileget(f.file); 33662306a36Sopenharmony_ci if (IS_ERR(eventfd)) { 33762306a36Sopenharmony_ci ret = PTR_ERR(eventfd); 33862306a36Sopenharmony_ci goto fail; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci irqfd->eventfd = eventfd; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if (args->flags & KVM_IRQFD_FLAG_RESAMPLE) { 34462306a36Sopenharmony_ci struct kvm_kernel_irqfd_resampler *resampler; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci resamplefd = eventfd_ctx_fdget(args->resamplefd); 34762306a36Sopenharmony_ci if (IS_ERR(resamplefd)) { 34862306a36Sopenharmony_ci ret = PTR_ERR(resamplefd); 34962306a36Sopenharmony_ci goto fail; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci irqfd->resamplefd = resamplefd; 35362306a36Sopenharmony_ci INIT_LIST_HEAD(&irqfd->resampler_link); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci mutex_lock(&kvm->irqfds.resampler_lock); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci list_for_each_entry(resampler, 35862306a36Sopenharmony_ci &kvm->irqfds.resampler_list, link) { 35962306a36Sopenharmony_ci if (resampler->notifier.gsi == irqfd->gsi) { 36062306a36Sopenharmony_ci irqfd->resampler = resampler; 36162306a36Sopenharmony_ci break; 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci if (!irqfd->resampler) { 36662306a36Sopenharmony_ci resampler = kzalloc(sizeof(*resampler), 36762306a36Sopenharmony_ci GFP_KERNEL_ACCOUNT); 36862306a36Sopenharmony_ci if (!resampler) { 36962306a36Sopenharmony_ci ret = -ENOMEM; 37062306a36Sopenharmony_ci mutex_unlock(&kvm->irqfds.resampler_lock); 37162306a36Sopenharmony_ci goto fail; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci resampler->kvm = kvm; 37562306a36Sopenharmony_ci INIT_LIST_HEAD(&resampler->list); 37662306a36Sopenharmony_ci resampler->notifier.gsi = irqfd->gsi; 37762306a36Sopenharmony_ci resampler->notifier.irq_acked = irqfd_resampler_ack; 37862306a36Sopenharmony_ci INIT_LIST_HEAD(&resampler->link); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci list_add_rcu(&resampler->link, &kvm->irqfds.resampler_list); 38162306a36Sopenharmony_ci kvm_register_irq_ack_notifier(kvm, 38262306a36Sopenharmony_ci &resampler->notifier); 38362306a36Sopenharmony_ci irqfd->resampler = resampler; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci list_add_rcu(&irqfd->resampler_link, &irqfd->resampler->list); 38762306a36Sopenharmony_ci synchronize_srcu(&kvm->irq_srcu); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci mutex_unlock(&kvm->irqfds.resampler_lock); 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* 39362306a36Sopenharmony_ci * Install our own custom wake-up handling so we are notified via 39462306a36Sopenharmony_ci * a callback whenever someone signals the underlying eventfd 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ci init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup); 39762306a36Sopenharmony_ci init_poll_funcptr(&irqfd->pt, irqfd_ptable_queue_proc); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci spin_lock_irq(&kvm->irqfds.lock); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci ret = 0; 40262306a36Sopenharmony_ci list_for_each_entry(tmp, &kvm->irqfds.items, list) { 40362306a36Sopenharmony_ci if (irqfd->eventfd != tmp->eventfd) 40462306a36Sopenharmony_ci continue; 40562306a36Sopenharmony_ci /* This fd is used for another irq already. */ 40662306a36Sopenharmony_ci ret = -EBUSY; 40762306a36Sopenharmony_ci spin_unlock_irq(&kvm->irqfds.lock); 40862306a36Sopenharmony_ci goto fail; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 41262306a36Sopenharmony_ci irqfd_update(kvm, irqfd); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci list_add_tail(&irqfd->list, &kvm->irqfds.items); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci spin_unlock_irq(&kvm->irqfds.lock); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* 41962306a36Sopenharmony_ci * Check if there was an event already pending on the eventfd 42062306a36Sopenharmony_ci * before we registered, and trigger it as if we didn't miss it. 42162306a36Sopenharmony_ci */ 42262306a36Sopenharmony_ci events = vfs_poll(f.file, &irqfd->pt); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci if (events & EPOLLIN) 42562306a36Sopenharmony_ci schedule_work(&irqfd->inject); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS 42862306a36Sopenharmony_ci if (kvm_arch_has_irq_bypass()) { 42962306a36Sopenharmony_ci irqfd->consumer.token = (void *)irqfd->eventfd; 43062306a36Sopenharmony_ci irqfd->consumer.add_producer = kvm_arch_irq_bypass_add_producer; 43162306a36Sopenharmony_ci irqfd->consumer.del_producer = kvm_arch_irq_bypass_del_producer; 43262306a36Sopenharmony_ci irqfd->consumer.stop = kvm_arch_irq_bypass_stop; 43362306a36Sopenharmony_ci irqfd->consumer.start = kvm_arch_irq_bypass_start; 43462306a36Sopenharmony_ci ret = irq_bypass_register_consumer(&irqfd->consumer); 43562306a36Sopenharmony_ci if (ret) 43662306a36Sopenharmony_ci pr_info("irq bypass consumer (token %p) registration fails: %d\n", 43762306a36Sopenharmony_ci irqfd->consumer.token, ret); 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci#endif 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci /* 44462306a36Sopenharmony_ci * do not drop the file until the irqfd is fully initialized, otherwise 44562306a36Sopenharmony_ci * we might race against the EPOLLHUP 44662306a36Sopenharmony_ci */ 44762306a36Sopenharmony_ci fdput(f); 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cifail: 45162306a36Sopenharmony_ci if (irqfd->resampler) 45262306a36Sopenharmony_ci irqfd_resampler_shutdown(irqfd); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (resamplefd && !IS_ERR(resamplefd)) 45562306a36Sopenharmony_ci eventfd_ctx_put(resamplefd); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci if (eventfd && !IS_ERR(eventfd)) 45862306a36Sopenharmony_ci eventfd_ctx_put(eventfd); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci fdput(f); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ciout: 46362306a36Sopenharmony_ci kfree(irqfd); 46462306a36Sopenharmony_ci return ret; 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cibool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci struct kvm_irq_ack_notifier *kian; 47062306a36Sopenharmony_ci int gsi, idx; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 47362306a36Sopenharmony_ci gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); 47462306a36Sopenharmony_ci if (gsi != -1) 47562306a36Sopenharmony_ci hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, 47662306a36Sopenharmony_ci link, srcu_read_lock_held(&kvm->irq_srcu)) 47762306a36Sopenharmony_ci if (kian->gsi == gsi) { 47862306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 47962306a36Sopenharmony_ci return true; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci return false; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kvm_irq_has_notifier); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_civoid kvm_notify_acked_gsi(struct kvm *kvm, int gsi) 48962306a36Sopenharmony_ci{ 49062306a36Sopenharmony_ci struct kvm_irq_ack_notifier *kian; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, 49362306a36Sopenharmony_ci link, srcu_read_lock_held(&kvm->irq_srcu)) 49462306a36Sopenharmony_ci if (kian->gsi == gsi) 49562306a36Sopenharmony_ci kian->irq_acked(kian); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_civoid kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci int gsi, idx; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci trace_kvm_ack_irq(irqchip, pin); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 50562306a36Sopenharmony_ci gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); 50662306a36Sopenharmony_ci if (gsi != -1) 50762306a36Sopenharmony_ci kvm_notify_acked_gsi(kvm, gsi); 50862306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_civoid kvm_register_irq_ack_notifier(struct kvm *kvm, 51262306a36Sopenharmony_ci struct kvm_irq_ack_notifier *kian) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci mutex_lock(&kvm->irq_lock); 51562306a36Sopenharmony_ci hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list); 51662306a36Sopenharmony_ci mutex_unlock(&kvm->irq_lock); 51762306a36Sopenharmony_ci kvm_arch_post_irq_ack_notifier_list_update(kvm); 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_civoid kvm_unregister_irq_ack_notifier(struct kvm *kvm, 52162306a36Sopenharmony_ci struct kvm_irq_ack_notifier *kian) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci mutex_lock(&kvm->irq_lock); 52462306a36Sopenharmony_ci hlist_del_init_rcu(&kian->link); 52562306a36Sopenharmony_ci mutex_unlock(&kvm->irq_lock); 52662306a36Sopenharmony_ci synchronize_srcu(&kvm->irq_srcu); 52762306a36Sopenharmony_ci kvm_arch_post_irq_ack_notifier_list_update(kvm); 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci#endif 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_civoid 53262306a36Sopenharmony_cikvm_eventfd_init(struct kvm *kvm) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQFD 53562306a36Sopenharmony_ci spin_lock_init(&kvm->irqfds.lock); 53662306a36Sopenharmony_ci INIT_LIST_HEAD(&kvm->irqfds.items); 53762306a36Sopenharmony_ci INIT_LIST_HEAD(&kvm->irqfds.resampler_list); 53862306a36Sopenharmony_ci mutex_init(&kvm->irqfds.resampler_lock); 53962306a36Sopenharmony_ci#endif 54062306a36Sopenharmony_ci INIT_LIST_HEAD(&kvm->ioeventfds); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQFD 54462306a36Sopenharmony_ci/* 54562306a36Sopenharmony_ci * shutdown any irqfd's that match fd+gsi 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_cistatic int 54862306a36Sopenharmony_cikvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd, *tmp; 55162306a36Sopenharmony_ci struct eventfd_ctx *eventfd; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci eventfd = eventfd_ctx_fdget(args->fd); 55462306a36Sopenharmony_ci if (IS_ERR(eventfd)) 55562306a36Sopenharmony_ci return PTR_ERR(eventfd); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci spin_lock_irq(&kvm->irqfds.lock); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) { 56062306a36Sopenharmony_ci if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) { 56162306a36Sopenharmony_ci /* 56262306a36Sopenharmony_ci * This clearing of irq_entry.type is needed for when 56362306a36Sopenharmony_ci * another thread calls kvm_irq_routing_update before 56462306a36Sopenharmony_ci * we flush workqueue below (we synchronize with 56562306a36Sopenharmony_ci * kvm_irq_routing_update using irqfds.lock). 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci write_seqcount_begin(&irqfd->irq_entry_sc); 56862306a36Sopenharmony_ci irqfd->irq_entry.type = 0; 56962306a36Sopenharmony_ci write_seqcount_end(&irqfd->irq_entry_sc); 57062306a36Sopenharmony_ci irqfd_deactivate(irqfd); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci spin_unlock_irq(&kvm->irqfds.lock); 57562306a36Sopenharmony_ci eventfd_ctx_put(eventfd); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci /* 57862306a36Sopenharmony_ci * Block until we know all outstanding shutdown jobs have completed 57962306a36Sopenharmony_ci * so that we guarantee there will not be any more interrupts on this 58062306a36Sopenharmony_ci * gsi once this deassign function returns. 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci flush_workqueue(irqfd_cleanup_wq); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci return 0; 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ciint 58862306a36Sopenharmony_cikvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci if (args->flags & ~(KVM_IRQFD_FLAG_DEASSIGN | KVM_IRQFD_FLAG_RESAMPLE)) 59162306a36Sopenharmony_ci return -EINVAL; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (args->flags & KVM_IRQFD_FLAG_DEASSIGN) 59462306a36Sopenharmony_ci return kvm_irqfd_deassign(kvm, args); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return kvm_irqfd_assign(kvm, args); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci/* 60062306a36Sopenharmony_ci * This function is called as the kvm VM fd is being released. Shutdown all 60162306a36Sopenharmony_ci * irqfds that still remain open 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_civoid 60462306a36Sopenharmony_cikvm_irqfd_release(struct kvm *kvm) 60562306a36Sopenharmony_ci{ 60662306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd, *tmp; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci spin_lock_irq(&kvm->irqfds.lock); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) 61162306a36Sopenharmony_ci irqfd_deactivate(irqfd); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci spin_unlock_irq(&kvm->irqfds.lock); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* 61662306a36Sopenharmony_ci * Block until we know all outstanding shutdown jobs have completed 61762306a36Sopenharmony_ci * since we do not take a kvm* reference. 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ci flush_workqueue(irqfd_cleanup_wq); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci/* 62462306a36Sopenharmony_ci * Take note of a change in irq routing. 62562306a36Sopenharmony_ci * Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards. 62662306a36Sopenharmony_ci */ 62762306a36Sopenharmony_civoid kvm_irq_routing_update(struct kvm *kvm) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci struct kvm_kernel_irqfd *irqfd; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci spin_lock_irq(&kvm->irqfds.lock); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci list_for_each_entry(irqfd, &kvm->irqfds.items, list) { 63462306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS 63562306a36Sopenharmony_ci /* Under irqfds.lock, so can read irq_entry safely */ 63662306a36Sopenharmony_ci struct kvm_kernel_irq_routing_entry old = irqfd->irq_entry; 63762306a36Sopenharmony_ci#endif 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci irqfd_update(kvm, irqfd); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci#ifdef CONFIG_HAVE_KVM_IRQ_BYPASS 64262306a36Sopenharmony_ci if (irqfd->producer && 64362306a36Sopenharmony_ci kvm_arch_irqfd_route_changed(&old, &irqfd->irq_entry)) { 64462306a36Sopenharmony_ci int ret = kvm_arch_update_irqfd_routing( 64562306a36Sopenharmony_ci irqfd->kvm, irqfd->producer->irq, 64662306a36Sopenharmony_ci irqfd->gsi, 1); 64762306a36Sopenharmony_ci WARN_ON(ret); 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci#endif 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci spin_unlock_irq(&kvm->irqfds.lock); 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cibool kvm_notify_irqfd_resampler(struct kvm *kvm, 65662306a36Sopenharmony_ci unsigned int irqchip, 65762306a36Sopenharmony_ci unsigned int pin) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci struct kvm_kernel_irqfd_resampler *resampler; 66062306a36Sopenharmony_ci int gsi, idx; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci idx = srcu_read_lock(&kvm->irq_srcu); 66362306a36Sopenharmony_ci gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); 66462306a36Sopenharmony_ci if (gsi != -1) { 66562306a36Sopenharmony_ci list_for_each_entry_srcu(resampler, 66662306a36Sopenharmony_ci &kvm->irqfds.resampler_list, link, 66762306a36Sopenharmony_ci srcu_read_lock_held(&kvm->irq_srcu)) { 66862306a36Sopenharmony_ci if (resampler->notifier.gsi == gsi) { 66962306a36Sopenharmony_ci irqfd_resampler_notify(resampler); 67062306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 67162306a36Sopenharmony_ci return true; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci srcu_read_unlock(&kvm->irq_srcu, idx); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci return false; 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci/* 68162306a36Sopenharmony_ci * create a host-wide workqueue for issuing deferred shutdown requests 68262306a36Sopenharmony_ci * aggregated from all vm* instances. We need our own isolated 68362306a36Sopenharmony_ci * queue to ease flushing work items when a VM exits. 68462306a36Sopenharmony_ci */ 68562306a36Sopenharmony_ciint kvm_irqfd_init(void) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci irqfd_cleanup_wq = alloc_workqueue("kvm-irqfd-cleanup", 0, 0); 68862306a36Sopenharmony_ci if (!irqfd_cleanup_wq) 68962306a36Sopenharmony_ci return -ENOMEM; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci return 0; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_civoid kvm_irqfd_exit(void) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci destroy_workqueue(irqfd_cleanup_wq); 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci#endif 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci/* 70162306a36Sopenharmony_ci * -------------------------------------------------------------------- 70262306a36Sopenharmony_ci * ioeventfd: translate a PIO/MMIO memory write to an eventfd signal. 70362306a36Sopenharmony_ci * 70462306a36Sopenharmony_ci * userspace can register a PIO/MMIO address with an eventfd for receiving 70562306a36Sopenharmony_ci * notification when the memory has been touched. 70662306a36Sopenharmony_ci * -------------------------------------------------------------------- 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_cistruct _ioeventfd { 71062306a36Sopenharmony_ci struct list_head list; 71162306a36Sopenharmony_ci u64 addr; 71262306a36Sopenharmony_ci int length; 71362306a36Sopenharmony_ci struct eventfd_ctx *eventfd; 71462306a36Sopenharmony_ci u64 datamatch; 71562306a36Sopenharmony_ci struct kvm_io_device dev; 71662306a36Sopenharmony_ci u8 bus_idx; 71762306a36Sopenharmony_ci bool wildcard; 71862306a36Sopenharmony_ci}; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_cistatic inline struct _ioeventfd * 72162306a36Sopenharmony_cito_ioeventfd(struct kvm_io_device *dev) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci return container_of(dev, struct _ioeventfd, dev); 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic void 72762306a36Sopenharmony_ciioeventfd_release(struct _ioeventfd *p) 72862306a36Sopenharmony_ci{ 72962306a36Sopenharmony_ci eventfd_ctx_put(p->eventfd); 73062306a36Sopenharmony_ci list_del(&p->list); 73162306a36Sopenharmony_ci kfree(p); 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_cistatic bool 73562306a36Sopenharmony_ciioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val) 73662306a36Sopenharmony_ci{ 73762306a36Sopenharmony_ci u64 _val; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (addr != p->addr) 74062306a36Sopenharmony_ci /* address must be precise for a hit */ 74162306a36Sopenharmony_ci return false; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci if (!p->length) 74462306a36Sopenharmony_ci /* length = 0 means only look at the address, so always a hit */ 74562306a36Sopenharmony_ci return true; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (len != p->length) 74862306a36Sopenharmony_ci /* address-range must be precise for a hit */ 74962306a36Sopenharmony_ci return false; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (p->wildcard) 75262306a36Sopenharmony_ci /* all else equal, wildcard is always a hit */ 75362306a36Sopenharmony_ci return true; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci /* otherwise, we have to actually compare the data */ 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci BUG_ON(!IS_ALIGNED((unsigned long)val, len)); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci switch (len) { 76062306a36Sopenharmony_ci case 1: 76162306a36Sopenharmony_ci _val = *(u8 *)val; 76262306a36Sopenharmony_ci break; 76362306a36Sopenharmony_ci case 2: 76462306a36Sopenharmony_ci _val = *(u16 *)val; 76562306a36Sopenharmony_ci break; 76662306a36Sopenharmony_ci case 4: 76762306a36Sopenharmony_ci _val = *(u32 *)val; 76862306a36Sopenharmony_ci break; 76962306a36Sopenharmony_ci case 8: 77062306a36Sopenharmony_ci _val = *(u64 *)val; 77162306a36Sopenharmony_ci break; 77262306a36Sopenharmony_ci default: 77362306a36Sopenharmony_ci return false; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci return _val == p->datamatch; 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci/* MMIO/PIO writes trigger an event if the addr/val match */ 78062306a36Sopenharmony_cistatic int 78162306a36Sopenharmony_ciioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr, 78262306a36Sopenharmony_ci int len, const void *val) 78362306a36Sopenharmony_ci{ 78462306a36Sopenharmony_ci struct _ioeventfd *p = to_ioeventfd(this); 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci if (!ioeventfd_in_range(p, addr, len, val)) 78762306a36Sopenharmony_ci return -EOPNOTSUPP; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci eventfd_signal(p->eventfd, 1); 79062306a36Sopenharmony_ci return 0; 79162306a36Sopenharmony_ci} 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci/* 79462306a36Sopenharmony_ci * This function is called as KVM is completely shutting down. We do not 79562306a36Sopenharmony_ci * need to worry about locking just nuke anything we have as quickly as possible 79662306a36Sopenharmony_ci */ 79762306a36Sopenharmony_cistatic void 79862306a36Sopenharmony_ciioeventfd_destructor(struct kvm_io_device *this) 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci struct _ioeventfd *p = to_ioeventfd(this); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci ioeventfd_release(p); 80362306a36Sopenharmony_ci} 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_cistatic const struct kvm_io_device_ops ioeventfd_ops = { 80662306a36Sopenharmony_ci .write = ioeventfd_write, 80762306a36Sopenharmony_ci .destructor = ioeventfd_destructor, 80862306a36Sopenharmony_ci}; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci/* assumes kvm->slots_lock held */ 81162306a36Sopenharmony_cistatic bool 81262306a36Sopenharmony_ciioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci struct _ioeventfd *_p; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci list_for_each_entry(_p, &kvm->ioeventfds, list) 81762306a36Sopenharmony_ci if (_p->bus_idx == p->bus_idx && 81862306a36Sopenharmony_ci _p->addr == p->addr && 81962306a36Sopenharmony_ci (!_p->length || !p->length || 82062306a36Sopenharmony_ci (_p->length == p->length && 82162306a36Sopenharmony_ci (_p->wildcard || p->wildcard || 82262306a36Sopenharmony_ci _p->datamatch == p->datamatch)))) 82362306a36Sopenharmony_ci return true; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci return false; 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistatic enum kvm_bus ioeventfd_bus_from_flags(__u32 flags) 82962306a36Sopenharmony_ci{ 83062306a36Sopenharmony_ci if (flags & KVM_IOEVENTFD_FLAG_PIO) 83162306a36Sopenharmony_ci return KVM_PIO_BUS; 83262306a36Sopenharmony_ci if (flags & KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY) 83362306a36Sopenharmony_ci return KVM_VIRTIO_CCW_NOTIFY_BUS; 83462306a36Sopenharmony_ci return KVM_MMIO_BUS; 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_cistatic int kvm_assign_ioeventfd_idx(struct kvm *kvm, 83862306a36Sopenharmony_ci enum kvm_bus bus_idx, 83962306a36Sopenharmony_ci struct kvm_ioeventfd *args) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci struct eventfd_ctx *eventfd; 84362306a36Sopenharmony_ci struct _ioeventfd *p; 84462306a36Sopenharmony_ci int ret; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci eventfd = eventfd_ctx_fdget(args->fd); 84762306a36Sopenharmony_ci if (IS_ERR(eventfd)) 84862306a36Sopenharmony_ci return PTR_ERR(eventfd); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci p = kzalloc(sizeof(*p), GFP_KERNEL_ACCOUNT); 85162306a36Sopenharmony_ci if (!p) { 85262306a36Sopenharmony_ci ret = -ENOMEM; 85362306a36Sopenharmony_ci goto fail; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci INIT_LIST_HEAD(&p->list); 85762306a36Sopenharmony_ci p->addr = args->addr; 85862306a36Sopenharmony_ci p->bus_idx = bus_idx; 85962306a36Sopenharmony_ci p->length = args->len; 86062306a36Sopenharmony_ci p->eventfd = eventfd; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci /* The datamatch feature is optional, otherwise this is a wildcard */ 86362306a36Sopenharmony_ci if (args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH) 86462306a36Sopenharmony_ci p->datamatch = args->datamatch; 86562306a36Sopenharmony_ci else 86662306a36Sopenharmony_ci p->wildcard = true; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci mutex_lock(&kvm->slots_lock); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci /* Verify that there isn't a match already */ 87162306a36Sopenharmony_ci if (ioeventfd_check_collision(kvm, p)) { 87262306a36Sopenharmony_ci ret = -EEXIST; 87362306a36Sopenharmony_ci goto unlock_fail; 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci kvm_iodevice_init(&p->dev, &ioeventfd_ops); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci ret = kvm_io_bus_register_dev(kvm, bus_idx, p->addr, p->length, 87962306a36Sopenharmony_ci &p->dev); 88062306a36Sopenharmony_ci if (ret < 0) 88162306a36Sopenharmony_ci goto unlock_fail; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci kvm_get_bus(kvm, bus_idx)->ioeventfd_count++; 88462306a36Sopenharmony_ci list_add_tail(&p->list, &kvm->ioeventfds); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci return 0; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ciunlock_fail: 89162306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 89262306a36Sopenharmony_ci kfree(p); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cifail: 89562306a36Sopenharmony_ci eventfd_ctx_put(eventfd); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci return ret; 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic int 90162306a36Sopenharmony_cikvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx, 90262306a36Sopenharmony_ci struct kvm_ioeventfd *args) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci struct _ioeventfd *p; 90562306a36Sopenharmony_ci struct eventfd_ctx *eventfd; 90662306a36Sopenharmony_ci struct kvm_io_bus *bus; 90762306a36Sopenharmony_ci int ret = -ENOENT; 90862306a36Sopenharmony_ci bool wildcard; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci eventfd = eventfd_ctx_fdget(args->fd); 91162306a36Sopenharmony_ci if (IS_ERR(eventfd)) 91262306a36Sopenharmony_ci return PTR_ERR(eventfd); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci mutex_lock(&kvm->slots_lock); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci list_for_each_entry(p, &kvm->ioeventfds, list) { 91962306a36Sopenharmony_ci if (p->bus_idx != bus_idx || 92062306a36Sopenharmony_ci p->eventfd != eventfd || 92162306a36Sopenharmony_ci p->addr != args->addr || 92262306a36Sopenharmony_ci p->length != args->len || 92362306a36Sopenharmony_ci p->wildcard != wildcard) 92462306a36Sopenharmony_ci continue; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci if (!p->wildcard && p->datamatch != args->datamatch) 92762306a36Sopenharmony_ci continue; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev); 93062306a36Sopenharmony_ci bus = kvm_get_bus(kvm, bus_idx); 93162306a36Sopenharmony_ci if (bus) 93262306a36Sopenharmony_ci bus->ioeventfd_count--; 93362306a36Sopenharmony_ci ret = 0; 93462306a36Sopenharmony_ci break; 93562306a36Sopenharmony_ci } 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci mutex_unlock(&kvm->slots_lock); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci eventfd_ctx_put(eventfd); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci return ret; 94262306a36Sopenharmony_ci} 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_cistatic int kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci enum kvm_bus bus_idx = ioeventfd_bus_from_flags(args->flags); 94762306a36Sopenharmony_ci int ret = kvm_deassign_ioeventfd_idx(kvm, bus_idx, args); 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if (!args->len && bus_idx == KVM_MMIO_BUS) 95062306a36Sopenharmony_ci kvm_deassign_ioeventfd_idx(kvm, KVM_FAST_MMIO_BUS, args); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci return ret; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_cistatic int 95662306a36Sopenharmony_cikvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) 95762306a36Sopenharmony_ci{ 95862306a36Sopenharmony_ci enum kvm_bus bus_idx; 95962306a36Sopenharmony_ci int ret; 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci bus_idx = ioeventfd_bus_from_flags(args->flags); 96262306a36Sopenharmony_ci /* must be natural-word sized, or 0 to ignore length */ 96362306a36Sopenharmony_ci switch (args->len) { 96462306a36Sopenharmony_ci case 0: 96562306a36Sopenharmony_ci case 1: 96662306a36Sopenharmony_ci case 2: 96762306a36Sopenharmony_ci case 4: 96862306a36Sopenharmony_ci case 8: 96962306a36Sopenharmony_ci break; 97062306a36Sopenharmony_ci default: 97162306a36Sopenharmony_ci return -EINVAL; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci /* check for range overflow */ 97562306a36Sopenharmony_ci if (args->addr + args->len < args->addr) 97662306a36Sopenharmony_ci return -EINVAL; 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci /* check for extra flags that we don't understand */ 97962306a36Sopenharmony_ci if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK) 98062306a36Sopenharmony_ci return -EINVAL; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* ioeventfd with no length can't be combined with DATAMATCH */ 98362306a36Sopenharmony_ci if (!args->len && (args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH)) 98462306a36Sopenharmony_ci return -EINVAL; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci ret = kvm_assign_ioeventfd_idx(kvm, bus_idx, args); 98762306a36Sopenharmony_ci if (ret) 98862306a36Sopenharmony_ci goto fail; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci /* When length is ignored, MMIO is also put on a separate bus, for 99162306a36Sopenharmony_ci * faster lookups. 99262306a36Sopenharmony_ci */ 99362306a36Sopenharmony_ci if (!args->len && bus_idx == KVM_MMIO_BUS) { 99462306a36Sopenharmony_ci ret = kvm_assign_ioeventfd_idx(kvm, KVM_FAST_MMIO_BUS, args); 99562306a36Sopenharmony_ci if (ret < 0) 99662306a36Sopenharmony_ci goto fast_fail; 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci return 0; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_cifast_fail: 100262306a36Sopenharmony_ci kvm_deassign_ioeventfd_idx(kvm, bus_idx, args); 100362306a36Sopenharmony_cifail: 100462306a36Sopenharmony_ci return ret; 100562306a36Sopenharmony_ci} 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ciint 100862306a36Sopenharmony_cikvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci if (args->flags & KVM_IOEVENTFD_FLAG_DEASSIGN) 101162306a36Sopenharmony_ci return kvm_deassign_ioeventfd(kvm, args); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci return kvm_assign_ioeventfd(kvm, args); 101462306a36Sopenharmony_ci} 1015