Skip to content

Instantly share code, notes, and snippets.

@tmakatos
Created July 4, 2022 10:08
Show Gist options
  • Save tmakatos/532afd092a8df2175120d3dbfcd719ef to your computer and use it in GitHub Desktop.
Save tmakatos/532afd092a8df2175120d3dbfcd719ef to your computer and use it in GitHub Desktop.
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