Skip to content

Commit f848a5a

Browse files
mstsirkinmatosatti
authored andcommitted
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 <[email protected]> Signed-off-by: Marcelo Tosatti <[email protected]>
1 parent cd9ae5f commit f848a5a

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

arch/x86/kvm/x86.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,6 +2644,7 @@ int kvm_dev_ioctl_check_extension(long ext)
26442644
case KVM_CAP_IRQ_INJECT_STATUS:
26452645
case KVM_CAP_IRQFD:
26462646
case KVM_CAP_IOEVENTFD:
2647+
case KVM_CAP_IOEVENTFD_NO_LENGTH:
26472648
case KVM_CAP_PIT2:
26482649
case KVM_CAP_PIT_STATE2:
26492650
case KVM_CAP_SET_IDENTITY_MAP_ADDR:

include/uapi/linux/kvm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ enum {
529529
struct kvm_ioeventfd {
530530
__u64 datamatch;
531531
__u64 addr; /* legal pio/mmio address */
532-
__u32 len; /* 1, 2, 4, or 8 bytes */
532+
__u32 len; /* 1, 2, 4, or 8 bytes; or 0 to ignore length */
533533
__s32 fd;
534534
__u32 flags;
535535
__u8 pad[36];
@@ -743,6 +743,7 @@ struct kvm_ppc_smmu_info {
743743
#define KVM_CAP_IOAPIC_POLARITY_IGNORED 97
744744
#define KVM_CAP_ENABLE_CAP_VM 98
745745
#define KVM_CAP_S390_IRQCHIP 99
746+
#define KVM_CAP_IOEVENTFD_NO_LENGTH 100
746747

747748
#ifdef KVM_CAP_IRQ_ROUTING
748749

virt/kvm/eventfd.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,15 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
600600
{
601601
u64 _val;
602602

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)
604612
/* address-range must be precise for a hit */
605613
return false;
606614

@@ -671,9 +679,11 @@ ioeventfd_check_collision(struct kvm *kvm, struct _ioeventfd *p)
671679

672680
list_for_each_entry(_p, &kvm->ioeventfds, list)
673681
if (_p->bus_idx == p->bus_idx &&
674-
_p->addr == p->addr && _p->length == p->length &&
675-
(_p->wildcard || p->wildcard ||
676-
_p->datamatch == p->datamatch))
682+
_p->addr == p->addr &&
683+
(!_p->length || !p->length ||
684+
(_p->length == p->length &&
685+
(_p->wildcard || p->wildcard ||
686+
_p->datamatch == p->datamatch))))
677687
return true;
678688

679689
return false;
@@ -697,8 +707,9 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
697707
int ret;
698708

699709
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 */
701711
switch (args->len) {
712+
case 0:
702713
case 1:
703714
case 2:
704715
case 4:
@@ -716,6 +727,12 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
716727
if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
717728
return -EINVAL;
718729

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+
719736
eventfd = eventfd_ctx_fdget(args->fd);
720737
if (IS_ERR(eventfd))
721738
return PTR_ERR(eventfd);

0 commit comments

Comments
 (0)