A significant part of hyperv.c is not actually tied to x86, and can be moved to hw/.
This will allow to maintain most of Hyper-V and VMBus target-independent, and to avoid conflicts with inclusion of arch-specific headers down the road in VMBus implementation. Also this stuff can now be opt-out with CONFIG_HYPERV. Signed-off-by: Roman Kagan <rka...@virtuozzo.com> --- {target/i386 => include/hw/hyperv}/hyperv.h | 21 ++-- target/i386/hyperv.h | 17 +-- {target/i386 => hw/hyperv}/hyperv.c | 76 ++---------- hw/misc/hyperv_testdev.c | 2 +- target/i386/hyperv.c | 127 +------------------- target/i386/kvm.c | 5 +- hw/Makefile.objs | 1 + hw/hyperv/Makefile.objs | 1 + 8 files changed, 28 insertions(+), 222 deletions(-) copy {target/i386 => include/hw/hyperv}/hyperv.h (59%) copy {target/i386 => hw/hyperv}/hyperv.c (65%) create mode 100644 hw/hyperv/Makefile.objs diff --git a/target/i386/hyperv.h b/include/hw/hyperv/hyperv.h similarity index 59% copy from target/i386/hyperv.h copy to include/hw/hyperv/hyperv.h index 8d4619c078..d6c8d78353 100644 --- a/target/i386/hyperv.h +++ b/include/hw/hyperv/hyperv.h @@ -1,27 +1,20 @@ /* - * QEMU KVM Hyper-V support + * Hyper-V guest/hypervisor interaction * - * Copyright (C) 2015 Andrey Smetanin <asmeta...@virtuozzo.com> - * - * Authors: - * Andrey Smetanin <asmeta...@virtuozzo.com> + * Copyright (c) 2015-2018 Virtuozzo International GmbH. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. - * */ -#ifndef TARGET_I386_HYPERV_H -#define TARGET_I386_HYPERV_H +#ifndef HW_HYPERV_HYPERV_H +#define HW_HYPERV_HYPERV_H -#include "cpu.h" -#include "sysemu/kvm.h" +#include "cpu-qom.h" typedef struct HvSintRoute HvSintRoute; typedef void (*HvSintAckClb)(void *data); -int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit); - HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, HvSintAckClb sint_ack_clb, void *sint_ack_clb_data); @@ -30,9 +23,9 @@ void hyperv_sint_route_unref(HvSintRoute *sint_route); int hyperv_sint_route_set_sint(HvSintRoute *sint_route); -static inline uint32_t hyperv_vp_index(X86CPU *cpu) +static inline uint32_t hyperv_vp_index(CPUState *cs) { - return CPU(cpu)->cpu_index; + return cs->cpu_index; } #endif diff --git a/target/i386/hyperv.h b/target/i386/hyperv.h index 8d4619c078..5c49251ecb 100644 --- a/target/i386/hyperv.h +++ b/target/i386/hyperv.h @@ -16,23 +16,8 @@ #include "cpu.h" #include "sysemu/kvm.h" - -typedef struct HvSintRoute HvSintRoute; -typedef void (*HvSintAckClb)(void *data); +#include "hw/hyperv/hyperv.h" int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit); -HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, - HvSintAckClb sint_ack_clb, - void *sint_ack_clb_data); -void hyperv_sint_route_ref(HvSintRoute *sint_route); -void hyperv_sint_route_unref(HvSintRoute *sint_route); - -int hyperv_sint_route_set_sint(HvSintRoute *sint_route); - -static inline uint32_t hyperv_vp_index(X86CPU *cpu) -{ - return CPU(cpu)->cpu_index; -} - #endif diff --git a/target/i386/hyperv.c b/hw/hyperv/hyperv.c similarity index 65% copy from target/i386/hyperv.c copy to hw/hyperv/hyperv.c index 68816642c9..97db87561e 100644 --- a/target/i386/hyperv.c +++ b/hw/hyperv/hyperv.c @@ -1,24 +1,20 @@ /* - * QEMU KVM Hyper-V support + * Hyper-V guest/hypervisor interaction * - * Copyright (C) 2015 Andrey Smetanin <asmeta...@virtuozzo.com> - * - * Authors: - * Andrey Smetanin <asmeta...@virtuozzo.com> + * Copyright (c) 2015-2018 Virtuozzo International GmbH. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. - * */ #include "qemu/osdep.h" #include "qemu/main-loop.h" -#include "hyperv.h" -#include "hyperv-proto.h" +#include "sysemu/kvm.h" +#include "hw/hyperv/hyperv.h" struct HvSintRoute { uint32_t sint; - X86CPU *cpu; + CPUState *cs; int gsi; EventNotifier sint_set_notifier; EventNotifier sint_ack_notifier; @@ -27,57 +23,11 @@ struct HvSintRoute { unsigned refcount; }; -static X86CPU *hyperv_find_vcpu(uint32_t vp_index) -{ - X86CPU *cpu = X86_CPU(qemu_get_cpu(vp_index)); - assert(hyperv_vp_index(cpu) == vp_index); - return cpu; -} - -int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) +static CPUState *hyperv_find_vcpu(uint32_t vp_index) { - CPUX86State *env = &cpu->env; - - switch (exit->type) { - case KVM_EXIT_HYPERV_SYNIC: - if (!cpu->hyperv_synic) { - return -1; - } - - /* - * For now just track changes in SynIC control and msg/evt pages msr's. - * When SynIC messaging/events processing will be added in future - * here we will do messages queues flushing and pages remapping. - */ - switch (exit->u.synic.msr) { - case HV_X64_MSR_SCONTROL: - env->msr_hv_synic_control = exit->u.synic.control; - break; - case HV_X64_MSR_SIMP: - env->msr_hv_synic_msg_page = exit->u.synic.msg_page; - break; - case HV_X64_MSR_SIEFP: - env->msr_hv_synic_evt_page = exit->u.synic.evt_page; - break; - default: - return -1; - } - return 0; - case KVM_EXIT_HYPERV_HCALL: { - uint16_t code; - - code = exit->u.hcall.input & 0xffff; - switch (code) { - case HV_POST_MESSAGE: - case HV_SIGNAL_EVENT: - default: - exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE; - return 0; - } - } - default: - return -1; - } + CPUState *cs = qemu_get_cpu(vp_index); + assert(hyperv_vp_index(cs) == vp_index); + return cs; } static void kvm_hv_sint_ack_handler(EventNotifier *notifier) @@ -95,10 +45,10 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, HvSintRoute *sint_route; EventNotifier *ack_notifier; int r, gsi; - X86CPU *cpu; + CPUState *cs; - cpu = hyperv_find_vcpu(vp_index); - if (!cpu) { + cs = hyperv_find_vcpu(vp_index); + if (!cs) { return NULL; } @@ -132,7 +82,7 @@ HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, sint_route->gsi = gsi; sint_route->sint_ack_clb = sint_ack_clb; sint_route->sint_ack_clb_data = sint_ack_clb_data; - sint_route->cpu = cpu; + sint_route->cs = cs; sint_route->sint = sint; sint_route->refcount = 1; diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c index 8654b13d76..02ef606469 100644 --- a/hw/misc/hyperv_testdev.c +++ b/hw/misc/hyperv_testdev.c @@ -15,7 +15,7 @@ #include "qemu/queue.h" #include "hw/qdev.h" #include "hw/isa/isa.h" -#include "target/i386/hyperv.h" +#include "hw/hyperv/hyperv.h" typedef struct TestSintRoute { QLIST_ENTRY(TestSintRoute) le; diff --git a/target/i386/hyperv.c b/target/i386/hyperv.c index 68816642c9..1eac727774 100644 --- a/target/i386/hyperv.c +++ b/target/i386/hyperv.c @@ -12,28 +12,10 @@ */ #include "qemu/osdep.h" -#include "qemu/main-loop.h" #include "hyperv.h" +#include "hw/hyperv/hyperv.h" #include "hyperv-proto.h" -struct HvSintRoute { - uint32_t sint; - X86CPU *cpu; - int gsi; - EventNotifier sint_set_notifier; - EventNotifier sint_ack_notifier; - HvSintAckClb sint_ack_clb; - void *sint_ack_clb_data; - unsigned refcount; -}; - -static X86CPU *hyperv_find_vcpu(uint32_t vp_index) -{ - X86CPU *cpu = X86_CPU(qemu_get_cpu(vp_index)); - assert(hyperv_vp_index(cpu) == vp_index); - return cpu; -} - int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) { CPUX86State *env = &cpu->env; @@ -79,110 +61,3 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit) return -1; } } - -static void kvm_hv_sint_ack_handler(EventNotifier *notifier) -{ - HvSintRoute *sint_route = container_of(notifier, HvSintRoute, - sint_ack_notifier); - event_notifier_test_and_clear(notifier); - sint_route->sint_ack_clb(sint_route->sint_ack_clb_data); -} - -HvSintRoute *hyperv_sint_route_new(uint32_t vp_index, uint32_t sint, - HvSintAckClb sint_ack_clb, - void *sint_ack_clb_data) -{ - HvSintRoute *sint_route; - EventNotifier *ack_notifier; - int r, gsi; - X86CPU *cpu; - - cpu = hyperv_find_vcpu(vp_index); - if (!cpu) { - return NULL; - } - - sint_route = g_new0(HvSintRoute, 1); - r = event_notifier_init(&sint_route->sint_set_notifier, false); - if (r) { - goto err; - } - - ack_notifier = sint_ack_clb ? &sint_route->sint_ack_notifier : NULL; - if (ack_notifier) { - r = event_notifier_init(ack_notifier, false); - if (r) { - goto err_sint_set_notifier; - } - - event_notifier_set_handler(ack_notifier, kvm_hv_sint_ack_handler); - } - - gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vp_index, sint); - if (gsi < 0) { - goto err_gsi; - } - - r = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, - &sint_route->sint_set_notifier, - ack_notifier, gsi); - if (r) { - goto err_irqfd; - } - sint_route->gsi = gsi; - sint_route->sint_ack_clb = sint_ack_clb; - sint_route->sint_ack_clb_data = sint_ack_clb_data; - sint_route->cpu = cpu; - sint_route->sint = sint; - sint_route->refcount = 1; - - return sint_route; - -err_irqfd: - kvm_irqchip_release_virq(kvm_state, gsi); -err_gsi: - if (ack_notifier) { - event_notifier_set_handler(ack_notifier, NULL); - event_notifier_cleanup(ack_notifier); - } -err_sint_set_notifier: - event_notifier_cleanup(&sint_route->sint_set_notifier); -err: - g_free(sint_route); - - return NULL; -} - -void hyperv_sint_route_ref(HvSintRoute *sint_route) -{ - sint_route->refcount++; -} - -void hyperv_sint_route_unref(HvSintRoute *sint_route) -{ - if (!sint_route) { - return; - } - - assert(sint_route->refcount > 0); - - if (--sint_route->refcount) { - return; - } - - kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, - &sint_route->sint_set_notifier, - sint_route->gsi); - kvm_irqchip_release_virq(kvm_state, sint_route->gsi); - if (sint_route->sint_ack_clb) { - event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL); - event_notifier_cleanup(&sint_route->sint_ack_notifier); - } - event_notifier_cleanup(&sint_route->sint_set_notifier); - g_free(sint_route); -} - -int hyperv_sint_route_set_sint(HvSintRoute *sint_route) -{ - return event_notifier_set(&sint_route->sint_set_notifier); -} diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 0b2a07d3a4..892d4f46c1 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -773,7 +773,7 @@ static int hyperv_init_vcpu(X86CPU *cpu) } assert(ret == 1); - if (msr_data.entries[0].data != hyperv_vp_index(cpu)) { + if (msr_data.entries[0].data != hyperv_vp_index(CPU(cpu))) { error_report("kernel's vp_index != QEMU's vp_index"); return -ENXIO; } @@ -1937,7 +1937,8 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime); } if (cpu->hyperv_vpindex && hv_vpindex_settable) { - kvm_msr_entry_add(cpu, HV_X64_MSR_VP_INDEX, hyperv_vp_index(cpu)); + kvm_msr_entry_add(cpu, HV_X64_MSR_VP_INDEX, + hyperv_vp_index(CPU(cpu))); } if (cpu->hyperv_synic) { int j; diff --git a/hw/Makefile.objs b/hw/Makefile.objs index a19c1417ed..b8f4675219 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -9,6 +9,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += cpu/ devices-dirs-$(CONFIG_SOFTMMU) += display/ devices-dirs-$(CONFIG_SOFTMMU) += dma/ devices-dirs-$(CONFIG_SOFTMMU) += gpio/ +devices-dirs-$(CONFIG_SOFTMMU) += hyperv/ devices-dirs-$(CONFIG_SOFTMMU) += i2c/ devices-dirs-$(CONFIG_SOFTMMU) += ide/ devices-dirs-$(CONFIG_SOFTMMU) += input/ diff --git a/hw/hyperv/Makefile.objs b/hw/hyperv/Makefile.objs new file mode 100644 index 0000000000..19928b726e --- /dev/null +++ b/hw/hyperv/Makefile.objs @@ -0,0 +1 @@ +obj-$(CONFIG_HYPERV) += hyperv.o -- 2.17.1