aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-03-31 14:50:38 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2014-04-17 13:01:42 -0400
commitf848a5a8dcb655553423f77cc98909a04e64173d (patch)
tree02e212c8eeeb52e74876408bb5e7e5d2febae379 /virt/kvm
parentcd9ae5fe47dfb9820976c3c38c70f4b07a5a1c36 (diff)
KVM: support any-length wildcard ioeventfd
It is sometimes benefitial to ignore IO size, and only match on address. In hindsight this would have been a better default than matching length when KVM_IOEVENTFD_FLAG_DATAMATCH is not set, In particular, this kind of access can be optimized on VMX: there no need to do page lookups. This can currently be done with many ioeventfds but in a suboptimal way. However we can't change kernel/userspace ABI without risk of breaking some applications. Use len = 0 to mean "ignore length for matching" in a more optimal way. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt/kvm')
-rw-r--r--virt/kvm/eventfd.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 29c2a04e036e..2721996bb9c2 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -600,7 +600,15 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
600{ 600{
601 u64 _val; 601 u64 _val;
602 602
603 if (!(addr == p->addr && len == p->length)) 603 if (addr != p->addr)
604 /* address must be precise for a hit */
605 return false;
606
607 if (!p->length)
608 /* length = 0 means only look at the address, so always a hit */
609 return true;
610
611 if (len != p->length)
604 /* address-range must be precise for a hit */ 612 /* address-range must be precise for a hit */
605 return false; 613 return false;
606 614
@@ -671,9 +679,11 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
671 679
672 list_for_each_entry(_p, &kvm->ioeventfds, list) 680 list_for_each_entry(_p, &kvm->ioeventfds, list)
673 if (_p->bus_idx == p->bus_idx && 681 if (_p->bus_idx == p->bus_idx &&
674 _p->addr == p->addr && _p->length == p->length && 682 _p->addr == p->addr &&
675 (_p->wildcard || p->wildcard || 683 (!_p->length || !p->length ||
676 _p->datamatch == p->datamatch)) 684 (_p->length == p->length &&
685 (_p->wildcard || p->wildcard ||
686 _p->datamatch == p->datamatch))))
677 return true; 687 return true;
678 688
679 return false; 689 return false;
@@ -697,8 +707,9 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
697 int ret; 707 int ret;
698 708
699 bus_idx = ioeventfd_bus_from_flags(args->flags); 709 bus_idx = ioeventfd_bus_from_flags(args->flags);
700 /* must be natural-word sized */ 710 /* must be natural-word sized, or 0 to ignore length */
701 switch (args->len) { 711 switch (args->len) {
712 case 0:
702 case 1: 713 case 1:
703 case 2: 714 case 2:
704 case 4: 715 case 4:
@@ -716,6 +727,12 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
716 if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK) 727 if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
717 return -EINVAL; 728 return -EINVAL;
718 729
730 /* ioeventfd with no length can't be combined with DATAMATCH */
731 if (!args->len &&
732 args->flags & (KVM_IOEVENTFD_FLAG_PIO |
733 KVM_IOEVENTFD_FLAG_DATAMATCH))
734 return -EINVAL;
735
719 eventfd = eventfd_ctx_fdget(args->fd); 736 eventfd = eventfd_ctx_fdget(args->fd);
720 if (IS_ERR(eventfd)) 737 if (IS_ERR(eventfd))
721 return PTR_ERR(eventfd); 738 return PTR_ERR(eventfd);