summaryrefslogtreecommitdiff
path: root/hw/hyperv
diff options
context:
space:
mode:
authorRoman Kagan <rkagan@virtuozzo.com>2018-09-21 11:22:15 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2018-10-19 13:44:14 +0200
commit8d3bc0b75318dce70928b8bde1a49e632adf5137 (patch)
tree65a5aaa15d8b8493b6277b7f808ce1764d57a49b /hw/hyperv
parente6ea9f45b72fe83d49adda948ff397dafc00c68f (diff)
downloadqemu-8d3bc0b75318dce70928b8bde1a49e632adf5137.zip
hyperv: add support for KVM_HYPERV_EVENTFD
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>
Diffstat (limited to 'hw/hyperv')
-rw-r--r--hw/hyperv/hyperv.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index d745016c17..7a1c1bbee4 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;