| From 8f4216c7d28976f7ec1b2bcbfa0a9f787133c45e Mon Sep 17 00:00:00 2001 |
| From: Jason Wang <jasowang@redhat.com> |
| Date: Tue, 15 Sep 2015 14:41:57 +0800 |
| Subject: kvm: fix zero length mmio searching |
| |
| From: Jason Wang <jasowang@redhat.com> |
| |
| commit 8f4216c7d28976f7ec1b2bcbfa0a9f787133c45e upstream. |
| |
| Currently, if we had a zero length mmio eventfd assigned on |
| KVM_MMIO_BUS. It will never be found by kvm_io_bus_cmp() since it |
| always compares the kvm_io_range() with the length that guest |
| wrote. This will cause e.g for vhost, kick will be trapped by qemu |
| userspace instead of vhost. Fixing this by using zero length if an |
| iodevice is zero length. |
| |
| Cc: Gleb Natapov <gleb@kernel.org> |
| Cc: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Jason Wang <jasowang@redhat.com> |
| Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| virt/kvm/kvm_main.c | 19 +++++++++++++++++-- |
| 1 file changed, 17 insertions(+), 2 deletions(-) |
| |
| --- a/virt/kvm/kvm_main.c |
| +++ b/virt/kvm/kvm_main.c |
| @@ -2797,10 +2797,25 @@ static void kvm_io_bus_destroy(struct kv |
| static inline int kvm_io_bus_cmp(const struct kvm_io_range *r1, |
| const struct kvm_io_range *r2) |
| { |
| - if (r1->addr < r2->addr) |
| + gpa_t addr1 = r1->addr; |
| + gpa_t addr2 = r2->addr; |
| + |
| + if (addr1 < addr2) |
| return -1; |
| - if (r1->addr + r1->len > r2->addr + r2->len) |
| + |
| + /* If r2->len == 0, match the exact address. If r2->len != 0, |
| + * accept any overlapping write. Any order is acceptable for |
| + * overlapping ranges, because kvm_io_bus_get_first_dev ensures |
| + * we process all of them. |
| + */ |
| + if (r2->len) { |
| + addr1 += r1->len; |
| + addr2 += r2->len; |
| + } |
| + |
| + if (addr1 > addr2) |
| return 1; |
| + |
| return 0; |
| } |
| |