diff mbox series

[PULL,44/48] hyperv: add support for KVM_HYPERV_EVENTFD

Message ID 1539894735-14232-45-git-send-email-pbonzini@redhat.com
State New
Headers show
Series [PULL,01/48] es1370: more fixes for ADC_FRAMEADR and ADC_FRAMECNT | expand

Commit Message

Paolo Bonzini Oct. 18, 2018, 8:32 p.m. UTC
From: Roman Kagan <rkagan@virtuozzo.com>

When setting up a notifier for Hyper-V event connection, try to use the
KVM-assisted one first, and fall back to userspace handling of the
hypercall if the kernel doesn't provide the requested feature.

Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
Message-Id: <20180921082217.29481-9-rkagan@virtuozzo.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/hyperv/hyperv.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index d745016..7a1c1bb 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -13,6 +13,7 @@ 
 #include "exec/address-spaces.h"
 #include "sysemu/kvm.h"
 #include "qemu/bitops.h"
+#include "qemu/error-report.h"
 #include "qemu/queue.h"
 #include "qemu/rcu.h"
 #include "qemu/rcu_queue.h"
@@ -470,7 +471,7 @@  static void __attribute__((constructor)) hv_init(void)
     qemu_mutex_init(&handlers_mutex);
 }
 
-int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier)
+static int set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier)
 {
     int ret;
     EventFlagHandler *handler;
@@ -503,6 +504,30 @@  unlock:
     return ret;
 }
 
+static bool process_event_flags_userspace;
+
+int hyperv_set_event_flag_handler(uint32_t conn_id, EventNotifier *notifier)
+{
+    if (!process_event_flags_userspace &&
+        !kvm_check_extension(kvm_state, KVM_CAP_HYPERV_EVENTFD)) {
+        process_event_flags_userspace = true;
+
+        warn_report("Hyper-V event signaling is not supported by this kernel; "
+                    "using slower userspace hypercall processing");
+    }
+
+    if (!process_event_flags_userspace) {
+        struct kvm_hyperv_eventfd hvevfd = {
+            .conn_id = conn_id,
+            .fd = notifier ? event_notifier_get_fd(notifier) : -1,
+            .flags = notifier ? 0 : KVM_HYPERV_EVENTFD_DEASSIGN,
+        };
+
+        return kvm_vm_ioctl(kvm_state, KVM_HYPERV_EVENTFD, &hvevfd);
+    }
+    return set_event_flag_handler(conn_id, notifier);
+}
+
 uint16_t hyperv_hcall_signal_event(uint64_t param, bool fast)
 {
     uint16_t ret;