|
@@ -600,7 +600,15 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
|
|
|
{
|
|
|
u64 _val;
|
|
|
|
|
|
- if (!(addr == p->addr && len == p->length))
|
|
|
+ if (addr != p->addr)
|
|
|
+ /* address must be precise for a hit */
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (!p->length)
|
|
|
+ /* length = 0 means only look at the address, so always a hit */
|
|
|
+ return true;
|
|
|
+
|
|
|
+ if (len != p->length)
|
|
|
/* address-range must be precise for a hit */
|
|
|
return false;
|
|
|
|
|
@@ -671,9 +679,11 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
|
|
|
|
|
|
list_for_each_entry(_p, &kvm->ioeventfds, list)
|
|
|
if (_p->bus_idx == p->bus_idx &&
|
|
|
- _p->addr == p->addr && _p->length == p->length &&
|
|
|
- (_p->wildcard || p->wildcard ||
|
|
|
- _p->datamatch == p->datamatch))
|
|
|
+ _p->addr == p->addr &&
|
|
|
+ (!_p->length || !p->length ||
|
|
|
+ (_p->length == p->length &&
|
|
|
+ (_p->wildcard || p->wildcard ||
|
|
|
+ _p->datamatch == p->datamatch))))
|
|
|
return true;
|
|
|
|
|
|
return false;
|
|
@@ -697,8 +707,9 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
|
|
|
int ret;
|
|
|
|
|
|
bus_idx = ioeventfd_bus_from_flags(args->flags);
|
|
|
- /* must be natural-word sized */
|
|
|
+ /* must be natural-word sized, or 0 to ignore length */
|
|
|
switch (args->len) {
|
|
|
+ case 0:
|
|
|
case 1:
|
|
|
case 2:
|
|
|
case 4:
|
|
@@ -716,6 +727,12 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
|
|
|
if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ /* ioeventfd with no length can't be combined with DATAMATCH */
|
|
|
+ if (!args->len &&
|
|
|
+ args->flags & (KVM_IOEVENTFD_FLAG_PIO |
|
|
|
+ KVM_IOEVENTFD_FLAG_DATAMATCH))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
eventfd = eventfd_ctx_fdget(args->fd);
|
|
|
if (IS_ERR(eventfd))
|
|
|
return PTR_ERR(eventfd);
|