similarity index 59%
copy from target/i386/hyperv.h
copy to include/hw/hyperv/hyperv.h
@@ -1,27 +1,20 @@
/*
- * QEMU KVM Hyper-V support
+ * Hyper-V guest/hypervisor interaction
*
- * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * Authors:
- * Andrey Smetanin <asmetanin@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
@@ -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
similarity index 65%
copy from target/i386/hyperv.c
copy to hw/hyperv/hyperv.c
@@ -1,24 +1,20 @@
/*
- * QEMU KVM Hyper-V support
+ * Hyper-V guest/hypervisor interaction
*
- * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
- *
- * Authors:
- * Andrey Smetanin <asmetanin@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;
@@ -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;
@@ -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);
-}
@@ -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;
@@ -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/
new file mode 100644
@@ -0,0 +1 @@
+obj-$(CONFIG_HYPERV) += hyperv.o
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 <rkagan@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