Commit 8d3bc0b7 authored by Roman Kagan's avatar Roman Kagan Committed by Paolo Bonzini
Browse files

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: default avatarRoman Kagan <rkagan@virtuozzo.com>
Message-Id: <20180921082217.29481-9-rkagan@virtuozzo.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent e6ea9f45
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -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;