| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * kvm eventfd support - use eventfd objects to signal various KVM events |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Author: |
|---|
| 8 | 9 | * Gregory Haskins <ghaskins@novell.com> |
|---|
| 9 | | - * |
|---|
| 10 | | - * This file is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of version 2 of the GNU General Public License |
|---|
| 12 | | - * as published by the Free Software Foundation. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 15 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 17 | | - * GNU General Public License for more details. |
|---|
| 18 | | - * |
|---|
| 19 | | - * You should have received a copy of the GNU General Public License |
|---|
| 20 | | - * along with this program; if not, write to the Free Software Foundation, |
|---|
| 21 | | - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
|---|
| 22 | 10 | */ |
|---|
| 23 | 11 | |
|---|
| 24 | 12 | #include <linux/kvm_host.h> |
|---|
| .. | .. |
|---|
| 128 | 116 | struct kvm *kvm = irqfd->kvm; |
|---|
| 129 | 117 | u64 cnt; |
|---|
| 130 | 118 | |
|---|
| 131 | | - /* Make sure irqfd has been initalized in assign path. */ |
|---|
| 119 | + /* Make sure irqfd has been initialized in assign path. */ |
|---|
| 132 | 120 | synchronize_srcu(&kvm->irq_srcu); |
|---|
| 133 | 121 | |
|---|
| 134 | 122 | /* |
|---|
| .. | .. |
|---|
| 220 | 208 | |
|---|
| 221 | 209 | if (flags & EPOLLHUP) { |
|---|
| 222 | 210 | /* The eventfd is closing, detach from KVM */ |
|---|
| 223 | | - unsigned long flags; |
|---|
| 211 | + unsigned long iflags; |
|---|
| 224 | 212 | |
|---|
| 225 | | - spin_lock_irqsave(&kvm->irqfds.lock, flags); |
|---|
| 213 | + spin_lock_irqsave(&kvm->irqfds.lock, iflags); |
|---|
| 226 | 214 | |
|---|
| 227 | 215 | /* |
|---|
| 228 | 216 | * We must check if someone deactivated the irqfd before |
|---|
| .. | .. |
|---|
| 236 | 224 | if (irqfd_is_active(irqfd)) |
|---|
| 237 | 225 | irqfd_deactivate(irqfd); |
|---|
| 238 | 226 | |
|---|
| 239 | | - spin_unlock_irqrestore(&kvm->irqfds.lock, flags); |
|---|
| 227 | + spin_unlock_irqrestore(&kvm->irqfds.lock, iflags); |
|---|
| 240 | 228 | } |
|---|
| 241 | 229 | |
|---|
| 242 | 230 | return 0; |
|---|
| .. | .. |
|---|
| 306 | 294 | if (!kvm_arch_irqfd_allowed(kvm, args)) |
|---|
| 307 | 295 | return -EINVAL; |
|---|
| 308 | 296 | |
|---|
| 309 | | - irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL); |
|---|
| 297 | + irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL_ACCOUNT); |
|---|
| 310 | 298 | if (!irqfd) |
|---|
| 311 | 299 | return -ENOMEM; |
|---|
| 312 | 300 | |
|---|
| .. | .. |
|---|
| 315 | 303 | INIT_LIST_HEAD(&irqfd->list); |
|---|
| 316 | 304 | INIT_WORK(&irqfd->inject, irqfd_inject); |
|---|
| 317 | 305 | INIT_WORK(&irqfd->shutdown, irqfd_shutdown); |
|---|
| 318 | | - seqcount_init(&irqfd->irq_entry_sc); |
|---|
| 306 | + seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock); |
|---|
| 319 | 307 | |
|---|
| 320 | 308 | f = fdget(args->fd); |
|---|
| 321 | 309 | if (!f.file) { |
|---|
| .. | .. |
|---|
| 354 | 342 | } |
|---|
| 355 | 343 | |
|---|
| 356 | 344 | if (!irqfd->resampler) { |
|---|
| 357 | | - resampler = kzalloc(sizeof(*resampler), GFP_KERNEL); |
|---|
| 345 | + resampler = kzalloc(sizeof(*resampler), |
|---|
| 346 | + GFP_KERNEL_ACCOUNT); |
|---|
| 358 | 347 | if (!resampler) { |
|---|
| 359 | 348 | ret = -ENOMEM; |
|---|
| 360 | 349 | mutex_unlock(&kvm->irqfds.resampler_lock); |
|---|
| .. | .. |
|---|
| 462 | 451 | idx = srcu_read_lock(&kvm->irq_srcu); |
|---|
| 463 | 452 | gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); |
|---|
| 464 | 453 | if (gsi != -1) |
|---|
| 465 | | - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, |
|---|
| 466 | | - link) |
|---|
| 454 | + hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, |
|---|
| 455 | + link, srcu_read_lock_held(&kvm->irq_srcu)) |
|---|
| 467 | 456 | if (kian->gsi == gsi) { |
|---|
| 468 | 457 | srcu_read_unlock(&kvm->irq_srcu, idx); |
|---|
| 469 | 458 | return true; |
|---|
| .. | .. |
|---|
| 479 | 468 | { |
|---|
| 480 | 469 | struct kvm_irq_ack_notifier *kian; |
|---|
| 481 | 470 | |
|---|
| 482 | | - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, |
|---|
| 483 | | - link) |
|---|
| 471 | + hlist_for_each_entry_srcu(kian, &kvm->irq_ack_notifier_list, |
|---|
| 472 | + link, srcu_read_lock_held(&kvm->irq_srcu)) |
|---|
| 484 | 473 | if (kian->gsi == gsi) |
|---|
| 485 | 474 | kian->irq_acked(kian); |
|---|
| 486 | 475 | } |
|---|
| .. | .. |
|---|
| 732 | 721 | return false; |
|---|
| 733 | 722 | } |
|---|
| 734 | 723 | |
|---|
| 735 | | - return _val == p->datamatch ? true : false; |
|---|
| 724 | + return _val == p->datamatch; |
|---|
| 736 | 725 | } |
|---|
| 737 | 726 | |
|---|
| 738 | 727 | /* MMIO/PIO writes trigger an event if the addr/val match */ |
|---|
| .. | .. |
|---|
| 806 | 795 | if (IS_ERR(eventfd)) |
|---|
| 807 | 796 | return PTR_ERR(eventfd); |
|---|
| 808 | 797 | |
|---|
| 809 | | - p = kzalloc(sizeof(*p), GFP_KERNEL); |
|---|
| 798 | + p = kzalloc(sizeof(*p), GFP_KERNEL_ACCOUNT); |
|---|
| 810 | 799 | if (!p) { |
|---|
| 811 | 800 | ret = -ENOMEM; |
|---|
| 812 | 801 | goto fail; |
|---|
| .. | .. |
|---|
| 864 | 853 | struct eventfd_ctx *eventfd; |
|---|
| 865 | 854 | struct kvm_io_bus *bus; |
|---|
| 866 | 855 | int ret = -ENOENT; |
|---|
| 856 | + bool wildcard; |
|---|
| 867 | 857 | |
|---|
| 868 | 858 | eventfd = eventfd_ctx_fdget(args->fd); |
|---|
| 869 | 859 | if (IS_ERR(eventfd)) |
|---|
| 870 | 860 | return PTR_ERR(eventfd); |
|---|
| 871 | 861 | |
|---|
| 862 | + wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH); |
|---|
| 863 | + |
|---|
| 872 | 864 | mutex_lock(&kvm->slots_lock); |
|---|
| 873 | 865 | |
|---|
| 874 | 866 | list_for_each_entry_safe(p, tmp, &kvm->ioeventfds, list) { |
|---|
| 875 | | - bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH); |
|---|
| 876 | 867 | |
|---|
| 877 | 868 | if (p->bus_idx != bus_idx || |
|---|
| 878 | 869 | p->eventfd != eventfd || |
|---|