Created
July 4, 2022 10:08
-
-
Save tmakatos/532afd092a8df2175120d3dbfcd719ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 4ac5c4ae86e818ffb6bb91dff82f3526b450d8aa Mon Sep 17 00:00:00 2001 | |
From: Thanos Makatos <thanos.makatos@nutanix.com> | |
Date: Wed, 25 May 2022 08:34:01 -0400 | |
Subject: [PATCH] FIXME hack to commit write on ioeventfd write | |
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com> | |
Change-Id: Id80dadd07b467e2298ce72c633734cb1535c8809 | |
--- | |
include/uapi/linux/kvm.h | 5 +++- | |
tools/include/uapi/linux/kvm.h | 2 ++ | |
virt/kvm/eventfd.c | 51 ++++++++++++++++++++++++++++++---- | |
3 files changed, 51 insertions(+), 7 deletions(-) | |
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h | |
index ca41220b40b8..a020c0d3548b 100644 | |
--- a/include/uapi/linux/kvm.h | |
+++ b/include/uapi/linux/kvm.h | |
@@ -712,6 +712,7 @@ enum { | |
kvm_ioeventfd_flag_nr_deassign, | |
kvm_ioeventfd_flag_nr_virtio_ccw_notify, | |
kvm_ioeventfd_flag_nr_fast_mmio, | |
+ kvm_ioevetnfd_flag_nr_commit_write, | |
kvm_ioeventfd_flag_nr_max, | |
}; | |
@@ -720,6 +721,7 @@ enum { | |
#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign) | |
#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \ | |
(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify) | |
+#define KVM_IOEVENTFD_FLAG_COMMIT_WRITE (1 << kvm_ioevetnfd_flag_nr_commit_write) | |
#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1) | |
@@ -729,7 +731,8 @@ struct kvm_ioeventfd { | |
__u32 len; /* 1, 2, 4, or 8 bytes; or 0 to ignore length */ | |
__s32 fd; | |
__u32 flags; | |
- __u8 pad[36]; | |
+ __u64 vaddr; | |
+ __u8 pad[28]; | |
}; | |
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0) | |
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h | |
index ca41220b40b8..cc78809872bb 100644 | |
--- a/tools/include/uapi/linux/kvm.h | |
+++ b/tools/include/uapi/linux/kvm.h | |
@@ -712,6 +712,7 @@ enum { | |
kvm_ioeventfd_flag_nr_deassign, | |
kvm_ioeventfd_flag_nr_virtio_ccw_notify, | |
kvm_ioeventfd_flag_nr_fast_mmio, | |
+ kvm_ioevetnfd_flag_nr_commit_write, | |
kvm_ioeventfd_flag_nr_max, | |
}; | |
@@ -720,6 +721,7 @@ enum { | |
#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign) | |
#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \ | |
(1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify) | |
+#define KVM_IOEVENTFD_FLAG_COMMIT_WRITE (1 << kvm_ioevetnfd_flag_nr_commit_write) | |
#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1) | |
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c | |
index 518cd8dc390e..9451dccda8b4 100644 | |
--- a/virt/kvm/eventfd.c | |
+++ b/virt/kvm/eventfd.c | |
@@ -663,6 +663,8 @@ struct _ioeventfd { | |
struct kvm_io_device dev; | |
u8 bus_idx; | |
bool wildcard; | |
+ bool commit_write; | |
+ void *vaddr; | |
}; | |
static inline struct _ioeventfd * | |
@@ -731,9 +733,27 @@ ioeventfd_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t addr, | |
{ | |
struct _ioeventfd *p = to_ioeventfd(this); | |
- if (!ioeventfd_in_range(p, addr, len, val)) | |
+ if (!ioeventfd_in_range(p, addr, len, val)) { | |
+ pr_alert("XXX bad range"); | |
return -EOPNOTSUPP; | |
+ } | |
+ if (p->commit_write) { | |
+ int ret; | |
+ uint64_t _val; | |
+ switch (len) { | |
+ case 1: _val = *(uint8_t*)val; break; | |
+ case 2: _val = *(uint16_t*)val; break; | |
+ case 4: _val = *(uint32_t*)val; break; | |
+ case 8: _val = *(uint64_t*)val; break; | |
+ default: | |
+ pr_err("XXX bad size"); | |
+ break; | |
+ } | |
+ WARN_ON(p->length != sizeof(uint32_t)); | |
+ ret = copy_to_user(p->vaddr + addr - p->addr, val, len); | |
+ WARN_ON(ret); | |
+ } | |
eventfd_signal(p->eventfd, 1); | |
return 0; | |
} | |
@@ -792,8 +812,10 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm, | |
int ret; | |
eventfd = eventfd_ctx_fdget(args->fd); | |
- if (IS_ERR(eventfd)) | |
+ if (IS_ERR(eventfd)) { | |
+ pr_err("XXX eventfd_ctx_fdget\n"); | |
return PTR_ERR(eventfd); | |
+ } | |
p = kzalloc(sizeof(*p), GFP_KERNEL_ACCOUNT); | |
if (!p) { | |
@@ -813,10 +835,14 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm, | |
else | |
p->wildcard = true; | |
+ p->commit_write = args->flags & KVM_IOEVENTFD_FLAG_COMMIT_WRITE; | |
+ p->vaddr = (void*)args->vaddr; | |
+ | |
mutex_lock(&kvm->slots_lock); | |
/* Verify that there isn't a match already */ | |
if (ioeventfd_check_collision(kvm, p)) { | |
+ pr_err(KERN_INFO "XXX collision\n"); | |
ret = -EEXIST; | |
goto unlock_fail; | |
} | |
@@ -825,14 +851,21 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm, | |
ret = kvm_io_bus_register_dev(kvm, bus_idx, p->addr, p->length, | |
&p->dev); | |
- if (ret < 0) | |
+ if (ret < 0) { | |
+ pr_err(KERN_INFO "XXX kvm_io_bus_register_dev\n"); | |
goto unlock_fail; | |
+ } | |
kvm_get_bus(kvm, bus_idx)->ioeventfd_count++; | |
list_add_tail(&p->list, &kvm->ioeventfds); | |
mutex_unlock(&kvm->slots_lock); | |
+ if (p->commit_write) { | |
+ pr_info("XXX config ioeventfd with COMMIT_WRITE %#llx-%#llx\n", | |
+ p->addr, p->addr + p->length); | |
+ } | |
+ | |
return 0; | |
unlock_fail: | |
@@ -922,16 +955,22 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) | |
} | |
/* check for range overflow */ | |
- if (args->addr + args->len < args->addr) | |
+ if (args->addr + args->len < args->addr) { | |
+ pr_alert("XXX bad range %#llx-%#llx\n", args->addr, args->addr + args->len); | |
return -EINVAL; | |
+ } | |
/* check for extra flags that we don't understand */ | |
- if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK) | |
+ if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK) { | |
+ pr_alert("XXX bad flags\n"); | |
return -EINVAL; | |
+ } | |
/* ioeventfd with no length can't be combined with DATAMATCH */ | |
- if (!args->len && (args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH)) | |
+ if (!args->len && (args->flags & KVM_IOEVENTFD_FLAG_DATAMATCH)) { | |
+ pr_alert("XXX bad datamatch\n"); | |
return -EINVAL; | |
+ } | |
ret = kvm_assign_ioeventfd_idx(kvm, bus_idx, args); | |
if (ret) | |
-- | |
2.22.3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment