diff options
author | Roman Kagan <rkagan@virtuozzo.com> | 2018-09-21 11:22:15 +0300 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2018-10-19 13:44:14 +0200 |
commit | 8d3bc0b75318dce70928b8bde1a49e632adf5137 (patch) | |
tree | 65a5aaa15d8b8493b6277b7f808ce1764d57a49b /hw/hyperv | |
parent | e6ea9f45b72fe83d49adda948ff397dafc00c68f (diff) | |
download | qemu-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.c | 27 |
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; |