kvm: fix MMIO/PIO collision misdetection
authorMichael S. Tsirkin <mst@redhat.com>
Thu, 4 Apr 2013 10:27:21 +0000 (13:27 +0300)
committerGleb Natapov <gleb@redhat.com>
Sun, 7 Apr 2013 11:53:47 +0000 (14:53 +0300)
PIO and MMIO are separate address spaces, but
ioeventfd registration code mistakenly detected
two eventfds as duplicate if they use the same address,
even if one is PIO and another one MMIO.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
virt/kvm/eventfd.c

index 020522ed90947ad8221f49520312647f2aea4ad9..48790989f8d2e8889db0bf553bb4f620f25113ba 100644 (file)
@@ -574,6 +574,7 @@ struct _ioeventfd {
        struct eventfd_ctx  *eventfd;
        u64                  datamatch;
        struct kvm_io_device dev;
+       u8                   bus_idx;
        bool                 wildcard;
 };
 
@@ -666,7 +667,8 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
        struct _ioeventfd *_p;
 
        list_for_each_entry(_p, &kvm->ioeventfds, list)
-               if (_p->addr == p->addr && _p->length == p->length &&
+               if (_p->bus_idx == p->bus_idx &&
+                   _p->addr == p->addr && _p->length == p->length &&
                    (_p->wildcard || p->wildcard ||
                     _p->datamatch == p->datamatch))
                        return true;
@@ -723,6 +725,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 
        INIT_LIST_HEAD(&p->list);
        p->addr    = args->addr;
+       p->bus_idx = bus_idx;
        p->length  = args->len;
        p->eventfd = eventfd;
 
@@ -781,7 +784,8 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
        list_for_each_entry_safe(p, tmp, &kvm->ioeventfds, list) {
                bool wildcard = !(args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH);
 
-               if (p->eventfd != eventfd  ||
+               if (p->bus_idx != bus_idx ||
+                   p->eventfd != eventfd  ||
                    p->addr != args->addr  ||
                    p->length != args->len ||
                    p->wildcard != wildcard)