* [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support
@ 2015-11-10 12:52 Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 1/5] headers: Linux kernel Hyper-V SynIC defines Andrey Smetanin
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
Hyper-V SynIC (synthetic interrupt controller) support:
* msr's support
* irq routing setup
* irq injection
* irq ack's callbacks
* event/message pages changes tracking at Hyper-V exit
* Hyper-V test device to test SynIC by kvm-unit-tests
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
Changes v2:
* linux headers update by scripts moved into separate patche
* activate Hyper-V SynIC by enabling corresponding vcpu cap
* reject cpu initialization if user requested Hyper-V SynIC
but kernel does not support Hyper-V SynIC
Andrey Smetanin (5):
headers: Linux kernel Hyper-V SynIC defines
target-i386/kvm: Hyper-V SynIC MSR's support
kvm: Hyper-V SynIC irq routing support
target-i386/hyperv: Hyper-V SynIC SINT routing and vcpu exit
hw/misc: Hyper-V test device 'hyperv-testdev'
default-configs/i386-softmmu.mak | 1 +
default-configs/x86_64-softmmu.mak | 1 +
hw/misc/Makefile.objs | 1 +
hw/misc/hyperv_testdev.c | 164 ++++++++++++++++++++++++++++++
include/standard-headers/asm-x86/hyperv.h | 12 +++
include/sysemu/kvm.h | 1 +
kvm-all.c | 33 ++++++
linux-headers/linux/kvm.h | 25 +++++
target-i386/Makefile.objs | 2 +-
target-i386/cpu-qom.h | 1 +
target-i386/cpu.c | 1 +
target-i386/cpu.h | 5 +
target-i386/hyperv.c | 127 +++++++++++++++++++++++
target-i386/hyperv.h | 42 ++++++++
target-i386/kvm.c | 73 ++++++++++++-
target-i386/machine.c | 39 +++++++
16 files changed, 526 insertions(+), 2 deletions(-)
create mode 100644 hw/misc/hyperv_testdev.c
create mode 100644 target-i386/hyperv.c
create mode 100644 target-i386/hyperv.h
--
2.4.3
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 1/5] headers: Linux kernel Hyper-V SynIC defines
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
@ 2015-11-10 12:52 ` Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support Andrey Smetanin
` (3 subsequent siblings)
4 siblings, 0 replies; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
This patch brings in the necessary changes from the corresponding kernel
patchset. It's included only for completeness; ideally these changes
should arrive via the standard kernel header pull.
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
include/standard-headers/asm-x86/hyperv.h | 12 ++++++++++++
| 25 +++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h
index c37c14e..f9780f1 100644
--- a/include/standard-headers/asm-x86/hyperv.h
+++ b/include/standard-headers/asm-x86/hyperv.h
@@ -257,4 +257,16 @@ typedef struct _HV_REFERENCE_TSC_PAGE {
int64_t tsc_offset;
} HV_REFERENCE_TSC_PAGE, *PHV_REFERENCE_TSC_PAGE;
+/* Define the number of synthetic interrupt sources. */
+#define HV_SYNIC_SINT_COUNT (16)
+/* Define the expected SynIC version. */
+#define HV_SYNIC_VERSION_1 (0x1)
+
+#define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
+#define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
+#define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
+#define HV_SYNIC_SINT_MASKED (1ULL << 16)
+#define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17)
+#define HV_SYNIC_SINT_VECTOR_MASK (0xFF)
+
#endif
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index dcc410e..4e20262 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -154,6 +154,20 @@ struct kvm_s390_skeys {
__u32 flags;
__u32 reserved[9];
};
+
+struct kvm_hyperv_exit {
+#define KVM_EXIT_HYPERV_SYNIC 1
+ __u32 type;
+ union {
+ struct {
+ __u32 msr;
+ __u64 control;
+ __u64 evt_page;
+ __u64 msg_page;
+ } synic;
+ } u;
+};
+
#define KVM_S390_GET_SKEYS_NONE 1
#define KVM_S390_SKEYS_MAX 1048576
@@ -184,6 +198,7 @@ struct kvm_s390_skeys {
#define KVM_EXIT_SYSTEM_EVENT 24
#define KVM_EXIT_S390_STSI 25
#define KVM_EXIT_IOAPIC_EOI 26
+#define KVM_EXIT_HYPERV 27
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -338,6 +353,8 @@ struct kvm_run {
struct {
__u8 vector;
} eoi;
+ /* KVM_EXIT_HYPERV */
+ struct kvm_hyperv_exit hyperv;
/* Fix the size of the union. */
char padding[256];
};
@@ -831,6 +848,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_GUEST_DEBUG_HW_WPS 120
#define KVM_CAP_SPLIT_IRQCHIP 121
#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
+#define KVM_CAP_HYPERV_SYNIC 123
#ifdef KVM_CAP_IRQ_ROUTING
@@ -854,10 +872,16 @@ struct kvm_irq_routing_s390_adapter {
__u32 adapter_id;
};
+struct kvm_irq_routing_hv_sint {
+ __u32 vcpu;
+ __u32 sint;
+};
+
/* gsi routing entry types */
#define KVM_IRQ_ROUTING_IRQCHIP 1
#define KVM_IRQ_ROUTING_MSI 2
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
+#define KVM_IRQ_ROUTING_HV_SINT 4
struct kvm_irq_routing_entry {
__u32 gsi;
@@ -868,6 +892,7 @@ struct kvm_irq_routing_entry {
struct kvm_irq_routing_irqchip irqchip;
struct kvm_irq_routing_msi msi;
struct kvm_irq_routing_s390_adapter adapter;
+ struct kvm_irq_routing_hv_sint hv_sint;
__u32 pad[8];
} u;
};
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 1/5] headers: Linux kernel Hyper-V SynIC defines Andrey Smetanin
@ 2015-11-10 12:52 ` Andrey Smetanin
2015-11-10 13:14 ` Paolo Bonzini
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 3/5] kvm: Hyper-V SynIC irq routing support Andrey Smetanin
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
This patch does Hyper-V Synthetic interrupt
controller(Hyper-V SynIC) MSR's support and
migration. Hyper-V SynIC is enabled by cpu's
'hv-synic' option.
This patch does not allow cpu creation if
'hv-synic' option specified but kernel
doesn't support Hyper-V SynIC.
Changes v2:
* activate Hyper-V SynIC by enabling corresponding vcpu cap
* reject cpu initialization if user requested Hyper-V SynIC
but kernel does not support Hyper-V SynIC
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
target-i386/cpu-qom.h | 1 +
target-i386/cpu.c | 1 +
target-i386/cpu.h | 5 ++++
target-i386/kvm.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
target-i386/machine.c | 39 ++++++++++++++++++++++++++++++
5 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index e3bfe9d..7ea5b34 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -94,6 +94,7 @@ typedef struct X86CPU {
bool hyperv_reset;
bool hyperv_vpindex;
bool hyperv_runtime;
+ bool hyperv_synic;
bool check_cpuid;
bool enforce_cpuid;
bool expose_kvm;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e5f1c5b..1462e19 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -3142,6 +3142,7 @@ static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
+ DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index fc4a605..8cf33df 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -918,6 +918,11 @@ typedef struct CPUX86State {
uint64_t msr_hv_tsc;
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
uint64_t msr_hv_runtime;
+ uint64_t msr_hv_synic_control;
+ uint64_t msr_hv_synic_version;
+ uint64_t msr_hv_synic_evt_page;
+ uint64_t msr_hv_synic_msg_page;
+ uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
/* exception/interrupt handling */
int error_code;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 2a9953b..cfcd01d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -86,6 +86,7 @@ static bool has_msr_hv_crash;
static bool has_msr_hv_reset;
static bool has_msr_hv_vpindex;
static bool has_msr_hv_runtime;
+static bool has_msr_hv_synic;
static bool has_msr_mtrr;
static bool has_msr_xss;
@@ -521,7 +522,8 @@ static bool hyperv_enabled(X86CPU *cpu)
cpu->hyperv_crash ||
cpu->hyperv_reset ||
cpu->hyperv_vpindex ||
- cpu->hyperv_runtime);
+ cpu->hyperv_runtime ||
+ cpu->hyperv_synic);
}
static Error *invtsc_mig_blocker;
@@ -610,6 +612,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (cpu->hyperv_runtime && has_msr_hv_runtime) {
c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
}
+ if (cpu->hyperv_synic) {
+ if (!has_msr_hv_synic ||
+ kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
+ fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
+ return -ENOSYS;
+ }
+ c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
+ }
c = &cpuid_data.entries[cpuid_i++];
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
if (cpu->hyperv_relaxed_timing) {
@@ -950,6 +960,10 @@ static int kvm_get_supported_msrs(KVMState *s)
has_msr_hv_runtime = true;
continue;
}
+ if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
+ has_msr_hv_synic = true;
+ continue;
+ }
}
}
@@ -1511,6 +1525,31 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
env->msr_hv_runtime);
}
+ if (cpu->hyperv_synic) {
+ int j;
+
+ if (!env->msr_hv_synic_version) {
+ /* First time initialization */
+ env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
+ for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
+ env->msr_hv_synic_sint[j] = HV_SYNIC_SINT_MASKED;
+ }
+ }
+
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL,
+ env->msr_hv_synic_control);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION,
+ env->msr_hv_synic_version);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP,
+ env->msr_hv_synic_evt_page);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP,
+ env->msr_hv_synic_msg_page);
+
+ for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j,
+ env->msr_hv_synic_sint[j]);
+ }
+ }
if (has_msr_mtrr) {
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
kvm_msr_entry_set(&msrs[n++],
@@ -1879,6 +1918,17 @@ static int kvm_get_msrs(X86CPU *cpu)
if (has_msr_hv_runtime) {
msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
}
+ if (cpu->hyperv_synic) {
+ uint32_t msr;
+
+ msrs[n++].index = HV_X64_MSR_SCONTROL;
+ msrs[n++].index = HV_X64_MSR_SVERSION;
+ msrs[n++].index = HV_X64_MSR_SIEFP;
+ msrs[n++].index = HV_X64_MSR_SIMP;
+ for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
+ msrs[n++].index = msr;
+ }
+ }
if (has_msr_mtrr) {
msrs[n++].index = MSR_MTRRdefType;
msrs[n++].index = MSR_MTRRfix64K_00000;
@@ -2035,6 +2085,21 @@ static int kvm_get_msrs(X86CPU *cpu)
case HV_X64_MSR_VP_RUNTIME:
env->msr_hv_runtime = msrs[i].data;
break;
+ case HV_X64_MSR_SCONTROL:
+ env->msr_hv_synic_control = msrs[i].data;
+ break;
+ case HV_X64_MSR_SVERSION:
+ env->msr_hv_synic_version = msrs[i].data;
+ break;
+ case HV_X64_MSR_SIEFP:
+ env->msr_hv_synic_evt_page = msrs[i].data;
+ break;
+ case HV_X64_MSR_SIMP:
+ env->msr_hv_synic_msg_page = msrs[i].data;
+ break;
+ case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
+ env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
+ break;
case MSR_MTRRdefType:
env->mtrr_deftype = msrs[i].data;
break;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index a18e16e..bdb2997 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -710,6 +710,44 @@ static const VMStateDescription vmstate_msr_hyperv_runtime = {
}
};
+static bool hyperv_synic_enable_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ if (env->msr_hv_synic_control != 0 ||
+ env->msr_hv_synic_version != 0 ||
+ env->msr_hv_synic_evt_page != 0 ||
+ env->msr_hv_synic_msg_page != 0) {
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
+ if (env->msr_hv_synic_sint[i] != 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static const VMStateDescription vmstate_msr_hyperv_synic = {
+ .name = "cpu/msr_hyperv_synic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = hyperv_synic_enable_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
+ VMSTATE_UINT64(env.msr_hv_synic_version, X86CPU),
+ VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
+ VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
+ VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
+ HV_SYNIC_SINT_COUNT),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool avx512_needed(void *opaque)
{
X86CPU *cpu = opaque;
@@ -893,6 +931,7 @@ VMStateDescription vmstate_x86_cpu = {
&vmstate_msr_hyperv_time,
&vmstate_msr_hyperv_crash,
&vmstate_msr_hyperv_runtime,
+ &vmstate_msr_hyperv_synic,
&vmstate_avx512,
&vmstate_xss,
NULL
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 3/5] kvm: Hyper-V SynIC irq routing support
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 1/5] headers: Linux kernel Hyper-V SynIC defines Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support Andrey Smetanin
@ 2015-11-10 12:52 ` Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 4/5] target-i386/hyperv: Hyper-V SynIC SINT routing and vcpu exit Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 5/5] hw/misc: Hyper-V test device 'hyperv-testdev' Andrey Smetanin
4 siblings, 0 replies; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
include/sysemu/kvm.h | 1 +
kvm-all.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 4ac6176..92ccb35 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -447,6 +447,7 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
void kvm_irqchip_release_virq(KVMState *s, int virq);
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
+int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint);
int kvm_irqchip_add_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
EventNotifier *rn, int virq);
diff --git a/kvm-all.c b/kvm-all.c
index 1bc1273..d36b494 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1297,6 +1297,34 @@ int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
return virq;
}
+int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint)
+{
+ struct kvm_irq_routing_entry kroute = {};
+ int virq;
+
+ if (!kvm_gsi_routing_enabled()) {
+ return -ENOSYS;
+ }
+ if (!kvm_check_extension(s, KVM_CAP_HYPERV_SYNIC)) {
+ return -ENOSYS;
+ }
+ virq = kvm_irqchip_get_virq(s);
+ if (virq < 0) {
+ return virq;
+ }
+
+ kroute.gsi = virq;
+ kroute.type = KVM_IRQ_ROUTING_HV_SINT;
+ kroute.flags = 0;
+ kroute.u.hv_sint.vcpu = vcpu;
+ kroute.u.hv_sint.sint = sint;
+
+ kvm_add_routing_entry(s, &kroute);
+ kvm_irqchip_commit_routes(s);
+
+ return virq;
+}
+
#else /* !KVM_CAP_IRQ_ROUTING */
void kvm_init_irq_routing(KVMState *s)
@@ -1322,6 +1350,11 @@ int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter)
return -ENOSYS;
}
+int kvm_irqchip_add_hv_sint_route(KVMState *s, uint32_t vcpu, uint32_t sint)
+{
+ return -ENOSYS;
+}
+
static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign)
{
abort();
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 4/5] target-i386/hyperv: Hyper-V SynIC SINT routing and vcpu exit
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
` (2 preceding siblings ...)
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 3/5] kvm: Hyper-V SynIC irq routing support Andrey Smetanin
@ 2015-11-10 12:52 ` Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 5/5] hw/misc: Hyper-V test device 'hyperv-testdev' Andrey Smetanin
4 siblings, 0 replies; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
Hyper-V SynIC(synthetic interrupt controller) helpers for
Hyper-V SynIC irq routing setup, irq injection, irq ack
notifications event/message pages changes tracking for future use.
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
target-i386/Makefile.objs | 2 +-
target-i386/hyperv.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++
target-i386/hyperv.h | 42 +++++++++++++++
target-i386/kvm.c | 6 +++
4 files changed, 176 insertions(+), 1 deletion(-)
create mode 100644 target-i386/hyperv.c
create mode 100644 target-i386/hyperv.h
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index 437d997..2255f46 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -3,5 +3,5 @@ obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o monitor.o
-obj-$(CONFIG_KVM) += kvm.o
+obj-$(CONFIG_KVM) += kvm.o hyperv.o
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c
new file mode 100644
index 0000000..e79b173
--- /dev/null
+++ b/target-i386/hyperv.c
@@ -0,0 +1,127 @@
+/*
+ * QEMU KVM Hyper-V support
+ *
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ * Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * 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 "hyperv.h"
+#include "standard-headers/asm-x86/hyperv.h"
+
+int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
+{
+ 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;
+ default:
+ 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);
+ if (sint_route->sint_ack_clb) {
+ sint_route->sint_ack_clb(sint_route);
+ }
+}
+
+HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
+ HvSintAckClb sint_ack_clb)
+{
+ HvSintRoute *sint_route;
+ int r, gsi;
+
+ sint_route = g_malloc0(sizeof(*sint_route));
+ r = event_notifier_init(&sint_route->sint_set_notifier, false);
+ if (r) {
+ goto err;
+ }
+
+ r = event_notifier_init(&sint_route->sint_ack_notifier, false);
+ if (r) {
+ goto err_sint_set_notifier;
+ }
+
+ event_notifier_set_handler(&sint_route->sint_ack_notifier,
+ kvm_hv_sint_ack_handler);
+
+ gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
+ if (gsi < 0) {
+ goto err_gsi;
+ }
+
+ r = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state,
+ &sint_route->sint_set_notifier,
+ &sint_route->sint_ack_notifier, gsi);
+ if (r) {
+ goto err_irqfd;
+ }
+ sint_route->gsi = gsi;
+ sint_route->sint_ack_clb = sint_ack_clb;
+ sint_route->vcpu_id = vcpu_id;
+ sint_route->sint = sint;
+
+ return sint_route;
+
+err_irqfd:
+ kvm_irqchip_release_virq(kvm_state, gsi);
+err_gsi:
+ event_notifier_set_handler(&sint_route->sint_ack_notifier, NULL);
+ event_notifier_cleanup(&sint_route->sint_ack_notifier);
+err_sint_set_notifier:
+ event_notifier_cleanup(&sint_route->sint_set_notifier);
+err:
+ g_free(sint_route);
+
+ return NULL;
+}
+
+void kvm_hv_sint_route_destroy(HvSintRoute *sint_route)
+{
+ 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);
+ 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 kvm_hv_sint_route_set_sint(HvSintRoute *sint_route)
+{
+ return event_notifier_set(&sint_route->sint_set_notifier);
+}
diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h
new file mode 100644
index 0000000..b26201f
--- /dev/null
+++ b/target-i386/hyperv.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU KVM Hyper-V support
+ *
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ * Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * 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 HYPERV_I386_H
+#define HYPERV_I386_H
+
+#include "cpu.h"
+#include "sysemu/kvm.h"
+#include "qemu/event_notifier.h"
+
+typedef struct HvSintRoute HvSintRoute;
+typedef void (*HvSintAckClb)(HvSintRoute *sint_route);
+
+struct HvSintRoute {
+ uint32_t sint;
+ uint32_t vcpu_id;
+ int gsi;
+ EventNotifier sint_set_notifier;
+ EventNotifier sint_ack_notifier;
+ HvSintAckClb sint_ack_clb;
+};
+
+int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit);
+
+HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
+ HvSintAckClb sint_ack_clb);
+
+void kvm_hv_sint_route_destroy(HvSintRoute *sint_route);
+
+int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route);
+
+#endif
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index cfcd01d..3870e56 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -25,6 +25,8 @@
#include "sysemu/kvm_int.h"
#include "kvm_i386.h"
#include "cpu.h"
+#include "hyperv.h"
+
#include "exec/gdbstub.h"
#include "qemu/host-utils.h"
#include "qemu/config-file.h"
@@ -33,6 +35,7 @@
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
#include "hw/i386/apic-msidef.h"
+
#include "exec/ioport.h"
#include "standard-headers/asm-x86/hyperv.h"
#include "hw/pci/pci.h"
@@ -2958,6 +2961,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
ret = kvm_handle_debug(cpu, &run->debug.arch);
qemu_mutex_unlock_iothread();
break;
+ case KVM_EXIT_HYPERV:
+ ret = kvm_hv_handle_exit(cpu, &run->hyperv);
+ break;
default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
ret = -1;
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 5/5] hw/misc: Hyper-V test device 'hyperv-testdev'
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
` (3 preceding siblings ...)
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 4/5] target-i386/hyperv: Hyper-V SynIC SINT routing and vcpu exit Andrey Smetanin
@ 2015-11-10 12:52 ` Andrey Smetanin
4 siblings, 0 replies; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-10 12:52 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
'hyperv-testdev' will be used by kvm-unit-tests
to setup Hyper-V SynIC SINT's routing and to inject
Hyper-V SynIC SINT's.
Hyper-V test device is ISA type device that creates 0x3000
IO memory region and catches write access into it. Every
write operation data decoded into ctl code and parameters
for Hyper-V test device.
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
default-configs/i386-softmmu.mak | 1 +
default-configs/x86_64-softmmu.mak | 1 +
hw/misc/Makefile.objs | 1 +
hw/misc/hyperv_testdev.c | 164 +++++++++++++++++++++++++++++++++++++
4 files changed, 167 insertions(+)
create mode 100644 hw/misc/hyperv_testdev.c
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 43c96d1..7f3c850 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -50,3 +50,4 @@ CONFIG_XIO3130=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_SMBIOS=y
+CONFIG_HYPERV_TESTDEV=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index dfb8095..e494d79 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -50,3 +50,4 @@ CONFIG_XIO3130=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_SMBIOS=y
+CONFIG_HYPERV_TESTDEV=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4aa76ff..fafc80a 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -40,3 +40,4 @@ obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
obj-$(CONFIG_PVPANIC) += pvpanic.o
obj-$(CONFIG_EDU) += edu.o
+obj-$(CONFIG_HYPERV_TESTDEV) += hyperv_testdev.o
diff --git a/hw/misc/hyperv_testdev.c b/hw/misc/hyperv_testdev.c
new file mode 100644
index 0000000..f0e4e35
--- /dev/null
+++ b/hw/misc/hyperv_testdev.c
@@ -0,0 +1,164 @@
+/*
+ * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests
+ *
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ * Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * 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 "hw/hw.h"
+#include "hw/qdev.h"
+#include "hw/isa/isa.h"
+#include "target-i386/hyperv.h"
+
+#define HV_TEST_DEV_MAX_SINT_ROUTES 64
+
+struct HypervTestDev {
+ ISADevice parent_obj;
+ MemoryRegion sint_control;
+ HvSintRoute *sint_route[HV_TEST_DEV_MAX_SINT_ROUTES];
+};
+typedef struct HypervTestDev HypervTestDev;
+
+#define TYPE_HYPERV_TEST_DEV "hyperv-testdev"
+#define HYPERV_TEST_DEV(obj) \
+ OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV)
+
+enum {
+ HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
+ HV_TEST_DEV_SINT_ROUTE_DESTROY,
+ HV_TEST_DEV_SINT_ROUTE_SET_SINT
+};
+
+static int alloc_sint_route_index(HypervTestDev *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) {
+ if (dev->sint_route[i] == NULL) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void free_sint_route_index(HypervTestDev *dev, int i)
+{
+ assert(i >= 0 && i < ARRAY_SIZE(dev->sint_route));
+ dev->sint_route[i] = NULL;
+}
+
+static int find_sint_route_index(HypervTestDev *dev, uint32_t vcpu_id,
+ uint32_t sint)
+{
+ HvSintRoute *sint_route;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) {
+ sint_route = dev->sint_route[i];
+ if (sint_route && sint_route->vcpu_id == vcpu_id &&
+ sint_route->sint == sint) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl,
+ uint32_t vcpu_id, uint32_t sint)
+{
+ int i;
+ HvSintRoute *sint_route;
+
+ switch (ctl) {
+ case HV_TEST_DEV_SINT_ROUTE_CREATE:
+ i = alloc_sint_route_index(dev);
+ assert(i >= 0);
+ sint_route = kvm_hv_sint_route_create(vcpu_id, sint, NULL);
+ assert(sint_route);
+ dev->sint_route[i] = sint_route;
+ break;
+ case HV_TEST_DEV_SINT_ROUTE_DESTROY:
+ i = find_sint_route_index(dev, vcpu_id, sint);
+ assert(i >= 0);
+ sint_route = dev->sint_route[i];
+ kvm_hv_sint_route_destroy(sint_route);
+ free_sint_route_index(dev, i);
+ break;
+ case HV_TEST_DEV_SINT_ROUTE_SET_SINT:
+ i = find_sint_route_index(dev, vcpu_id, sint);
+ assert(i >= 0);
+ sint_route = dev->sint_route[i];
+ kvm_hv_sint_route_set_sint(sint_route);
+ break;
+ default:
+ break;
+ }
+}
+
+static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data,
+ uint32_t len)
+{
+ HypervTestDev *dev = HYPERV_TEST_DEV(opaque);
+ uint8_t ctl;
+
+ ctl = (data >> 16ULL) & 0xFF;
+ switch (ctl) {
+ case HV_TEST_DEV_SINT_ROUTE_CREATE:
+ case HV_TEST_DEV_SINT_ROUTE_DESTROY:
+ case HV_TEST_DEV_SINT_ROUTE_SET_SINT: {
+ uint8_t sint = data & 0xFF;
+ uint8_t vcpu_id = (data >> 8ULL) & 0xFF;
+ hv_synic_test_dev_control(dev, ctl, vcpu_id, sint);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static const MemoryRegionOps synic_test_sint_ops = {
+ .write = hv_test_dev_control,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void hv_test_dev_realizefn(DeviceState *d, Error **errp)
+{
+ ISADevice *isa = ISA_DEVICE(d);
+ HypervTestDev *dev = HYPERV_TEST_DEV(d);
+ MemoryRegion *io = isa_address_space_io(isa);
+
+ memset(dev->sint_route, 0, sizeof(dev->sint_route));
+ memory_region_init_io(&dev->sint_control, OBJECT(dev),
+ &synic_test_sint_ops, dev,
+ "hyperv-testdev-ctl", 4);
+ memory_region_add_subregion(io, 0x3000, &dev->sint_control);
+}
+
+static void hv_test_dev_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->realize = hv_test_dev_realizefn;
+}
+
+static const TypeInfo hv_test_dev_info = {
+ .name = TYPE_HYPERV_TEST_DEV,
+ .parent = TYPE_ISA_DEVICE,
+ .instance_size = sizeof(HypervTestDev),
+ .class_init = hv_test_dev_class_init,
+};
+
+static void hv_test_dev_register_types(void)
+{
+ type_register_static(&hv_test_dev_info);
+}
+type_init(hv_test_dev_register_types);
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support Andrey Smetanin
@ 2015-11-10 13:14 ` Paolo Bonzini
2015-11-11 9:09 ` Andrey Smetanin
2015-11-11 10:18 ` [Qemu-devel] [PATCH v3 " Andrey Smetanin
0 siblings, 2 replies; 13+ messages in thread
From: Paolo Bonzini @ 2015-11-10 13:14 UTC (permalink / raw)
To: Andrey Smetanin, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 10/11/2015 13:52, Andrey Smetanin wrote:
> This patch does Hyper-V Synthetic interrupt
> controller(Hyper-V SynIC) MSR's support and
> migration. Hyper-V SynIC is enabled by cpu's
> 'hv-synic' option.
>
> This patch does not allow cpu creation if
> 'hv-synic' option specified but kernel
> doesn't support Hyper-V SynIC.
>
> Changes v2:
> * activate Hyper-V SynIC by enabling corresponding vcpu cap
> * reject cpu initialization if user requested Hyper-V SynIC
> but kernel does not support Hyper-V SynIC
>
> Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Paolo Bonzini <pbonzini@redhat.com>
> CC: Richard Henderson <rth@twiddle.net>
> CC: Eduardo Habkost <ehabkost@redhat.com>
> CC: "Andreas Färber" <afaerber@suse.de>
> CC: Marcelo Tosatti <mtosatti@redhat.com>
> CC: Roman Kagan <rkagan@virtuozzo.com>
> CC: Denis V. Lunev <den@openvz.org>
> CC: kvm@vger.kernel.org
>
> ---
> target-i386/cpu-qom.h | 1 +
> target-i386/cpu.c | 1 +
> target-i386/cpu.h | 5 ++++
> target-i386/kvm.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> target-i386/machine.c | 39 ++++++++++++++++++++++++++++++
> 5 files changed, 112 insertions(+), 1 deletion(-)
>
> diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
> index e3bfe9d..7ea5b34 100644
> --- a/target-i386/cpu-qom.h
> +++ b/target-i386/cpu-qom.h
> @@ -94,6 +94,7 @@ typedef struct X86CPU {
> bool hyperv_reset;
> bool hyperv_vpindex;
> bool hyperv_runtime;
> + bool hyperv_synic;
> bool check_cpuid;
> bool enforce_cpuid;
> bool expose_kvm;
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index e5f1c5b..1462e19 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -3142,6 +3142,7 @@ static Property x86_cpu_properties[] = {
> DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
> DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
> DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
> + DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
> DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
> DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
> DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index fc4a605..8cf33df 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -918,6 +918,11 @@ typedef struct CPUX86State {
> uint64_t msr_hv_tsc;
> uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
> uint64_t msr_hv_runtime;
> + uint64_t msr_hv_synic_control;
> + uint64_t msr_hv_synic_version;
> + uint64_t msr_hv_synic_evt_page;
> + uint64_t msr_hv_synic_msg_page;
> + uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
>
> /* exception/interrupt handling */
> int error_code;
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index 2a9953b..cfcd01d 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -86,6 +86,7 @@ static bool has_msr_hv_crash;
> static bool has_msr_hv_reset;
> static bool has_msr_hv_vpindex;
> static bool has_msr_hv_runtime;
> +static bool has_msr_hv_synic;
> static bool has_msr_mtrr;
> static bool has_msr_xss;
>
> @@ -521,7 +522,8 @@ static bool hyperv_enabled(X86CPU *cpu)
> cpu->hyperv_crash ||
> cpu->hyperv_reset ||
> cpu->hyperv_vpindex ||
> - cpu->hyperv_runtime);
> + cpu->hyperv_runtime ||
> + cpu->hyperv_synic);
> }
>
> static Error *invtsc_mig_blocker;
> @@ -610,6 +612,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
> if (cpu->hyperv_runtime && has_msr_hv_runtime) {
> c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
> }
> + if (cpu->hyperv_synic) {
> + if (!has_msr_hv_synic ||
> + kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
> + fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
> + return -ENOSYS;
> + }
> + c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
> + }
> c = &cpuid_data.entries[cpuid_i++];
> c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
> if (cpu->hyperv_relaxed_timing) {
> @@ -950,6 +960,10 @@ static int kvm_get_supported_msrs(KVMState *s)
> has_msr_hv_runtime = true;
> continue;
> }
> + if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
> + has_msr_hv_synic = true;
> + continue;
> + }
> }
> }
>
> @@ -1511,6 +1525,31 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
> kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
> env->msr_hv_runtime);
> }
> + if (cpu->hyperv_synic) {
> + int j;
> +
> + if (!env->msr_hv_synic_version) {
> + /* First time initialization */
> + env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
> + for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
> + env->msr_hv_synic_sint[j] = HV_SYNIC_SINT_MASKED;
> + }
> + }
I would prefer to put this in kvm_arch_init_vcpu, if possible.
> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL,
> + env->msr_hv_synic_control);
> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION,
> + env->msr_hv_synic_version);
> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP,
> + env->msr_hv_synic_evt_page);
> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP,
> + env->msr_hv_synic_msg_page);
> +
> + for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j,
> + env->msr_hv_synic_sint[j]);
> + }
> + }
> if (has_msr_mtrr) {
> kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
> kvm_msr_entry_set(&msrs[n++],
> @@ -1879,6 +1918,17 @@ static int kvm_get_msrs(X86CPU *cpu)
> if (has_msr_hv_runtime) {
> msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
> }
> + if (cpu->hyperv_synic) {
> + uint32_t msr;
> +
> + msrs[n++].index = HV_X64_MSR_SCONTROL;
> + msrs[n++].index = HV_X64_MSR_SVERSION;
> + msrs[n++].index = HV_X64_MSR_SIEFP;
> + msrs[n++].index = HV_X64_MSR_SIMP;
> + for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
> + msrs[n++].index = msr;
> + }
> + }
> if (has_msr_mtrr) {
> msrs[n++].index = MSR_MTRRdefType;
> msrs[n++].index = MSR_MTRRfix64K_00000;
> @@ -2035,6 +2085,21 @@ static int kvm_get_msrs(X86CPU *cpu)
> case HV_X64_MSR_VP_RUNTIME:
> env->msr_hv_runtime = msrs[i].data;
> break;
> + case HV_X64_MSR_SCONTROL:
> + env->msr_hv_synic_control = msrs[i].data;
> + break;
> + case HV_X64_MSR_SVERSION:
> + env->msr_hv_synic_version = msrs[i].data;
> + break;
> + case HV_X64_MSR_SIEFP:
> + env->msr_hv_synic_evt_page = msrs[i].data;
> + break;
> + case HV_X64_MSR_SIMP:
> + env->msr_hv_synic_msg_page = msrs[i].data;
> + break;
> + case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
> + env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
> + break;
> case MSR_MTRRdefType:
> env->mtrr_deftype = msrs[i].data;
> break;
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index a18e16e..bdb2997 100644
> --- a/target-i386/machine.c
> +++ b/target-i386/machine.c
> @@ -710,6 +710,44 @@ static const VMStateDescription vmstate_msr_hyperv_runtime = {
> }
> };
>
> +static bool hyperv_synic_enable_needed(void *opaque)
> +{
> + X86CPU *cpu = opaque;
> + CPUX86State *env = &cpu->env;
> + int i;
> +
> + if (env->msr_hv_synic_control != 0 ||
> + env->msr_hv_synic_version != 0 ||
> + env->msr_hv_synic_evt_page != 0 ||
> + env->msr_hv_synic_msg_page != 0) {
> + return true;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
> + if (env->msr_hv_synic_sint[i] != 0) {
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> +static const VMStateDescription vmstate_msr_hyperv_synic = {
> + .name = "cpu/msr_hyperv_synic",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = hyperv_synic_enable_needed,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
> + VMSTATE_UINT64(env.msr_hv_synic_version, X86CPU),
This one need not be migrated, since it's always the same value.
Paolo
> + VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
> + VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
> + VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
> + HV_SYNIC_SINT_COUNT),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static bool avx512_needed(void *opaque)
> {
> X86CPU *cpu = opaque;
> @@ -893,6 +931,7 @@ VMStateDescription vmstate_x86_cpu = {
> &vmstate_msr_hyperv_time,
> &vmstate_msr_hyperv_crash,
> &vmstate_msr_hyperv_runtime,
> + &vmstate_msr_hyperv_synic,
> &vmstate_avx512,
> &vmstate_xss,
> NULL
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-10 13:14 ` Paolo Bonzini
@ 2015-11-11 9:09 ` Andrey Smetanin
2015-11-11 9:17 ` Paolo Bonzini
2015-11-11 10:18 ` [Qemu-devel] [PATCH v3 " Andrey Smetanin
1 sibling, 1 reply; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-11 9:09 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 11/10/2015 04:14 PM, Paolo Bonzini wrote:
>
>
> On 10/11/2015 13:52, Andrey Smetanin wrote:
>> This patch does Hyper-V Synthetic interrupt
>> controller(Hyper-V SynIC) MSR's support and
>> migration. Hyper-V SynIC is enabled by cpu's
>> 'hv-synic' option.
>>
>> This patch does not allow cpu creation if
>> 'hv-synic' option specified but kernel
>> doesn't support Hyper-V SynIC.
>>
>> Changes v2:
>> * activate Hyper-V SynIC by enabling corresponding vcpu cap
>> * reject cpu initialization if user requested Hyper-V SynIC
>> but kernel does not support Hyper-V SynIC
>>
>> Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
>> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
>> Signed-off-by: Denis V. Lunev <den@openvz.org>
>> CC: Paolo Bonzini <pbonzini@redhat.com>
>> CC: Richard Henderson <rth@twiddle.net>
>> CC: Eduardo Habkost <ehabkost@redhat.com>
>> CC: "Andreas Färber" <afaerber@suse.de>
>> CC: Marcelo Tosatti <mtosatti@redhat.com>
>> CC: Roman Kagan <rkagan@virtuozzo.com>
>> CC: Denis V. Lunev <den@openvz.org>
>> CC: kvm@vger.kernel.org
>>
>> ---
>> target-i386/cpu-qom.h | 1 +
>> target-i386/cpu.c | 1 +
>> target-i386/cpu.h | 5 ++++
>> target-i386/kvm.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++-
>> target-i386/machine.c | 39 ++++++++++++++++++++++++++++++
>> 5 files changed, 112 insertions(+), 1 deletion(-)
>>
>> diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
>> index e3bfe9d..7ea5b34 100644
>> --- a/target-i386/cpu-qom.h
>> +++ b/target-i386/cpu-qom.h
>> @@ -94,6 +94,7 @@ typedef struct X86CPU {
>> bool hyperv_reset;
>> bool hyperv_vpindex;
>> bool hyperv_runtime;
>> + bool hyperv_synic;
>> bool check_cpuid;
>> bool enforce_cpuid;
>> bool expose_kvm;
>> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
>> index e5f1c5b..1462e19 100644
>> --- a/target-i386/cpu.c
>> +++ b/target-i386/cpu.c
>> @@ -3142,6 +3142,7 @@ static Property x86_cpu_properties[] = {
>> DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
>> DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
>> DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
>> + DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
>> DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
>> DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
>> DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
>> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
>> index fc4a605..8cf33df 100644
>> --- a/target-i386/cpu.h
>> +++ b/target-i386/cpu.h
>> @@ -918,6 +918,11 @@ typedef struct CPUX86State {
>> uint64_t msr_hv_tsc;
>> uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
>> uint64_t msr_hv_runtime;
>> + uint64_t msr_hv_synic_control;
>> + uint64_t msr_hv_synic_version;
>> + uint64_t msr_hv_synic_evt_page;
>> + uint64_t msr_hv_synic_msg_page;
>> + uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
>>
>> /* exception/interrupt handling */
>> int error_code;
>> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
>> index 2a9953b..cfcd01d 100644
>> --- a/target-i386/kvm.c
>> +++ b/target-i386/kvm.c
>> @@ -86,6 +86,7 @@ static bool has_msr_hv_crash;
>> static bool has_msr_hv_reset;
>> static bool has_msr_hv_vpindex;
>> static bool has_msr_hv_runtime;
>> +static bool has_msr_hv_synic;
>> static bool has_msr_mtrr;
>> static bool has_msr_xss;
>>
>> @@ -521,7 +522,8 @@ static bool hyperv_enabled(X86CPU *cpu)
>> cpu->hyperv_crash ||
>> cpu->hyperv_reset ||
>> cpu->hyperv_vpindex ||
>> - cpu->hyperv_runtime);
>> + cpu->hyperv_runtime ||
>> + cpu->hyperv_synic);
>> }
>>
>> static Error *invtsc_mig_blocker;
>> @@ -610,6 +612,14 @@ int kvm_arch_init_vcpu(CPUState *cs)
>> if (cpu->hyperv_runtime && has_msr_hv_runtime) {
>> c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
>> }
>> + if (cpu->hyperv_synic) {
>> + if (!has_msr_hv_synic ||
>> + kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
>> + fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
>> + return -ENOSYS;
>> + }
>> + c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
>> + }
>> c = &cpuid_data.entries[cpuid_i++];
>> c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
>> if (cpu->hyperv_relaxed_timing) {
>> @@ -950,6 +960,10 @@ static int kvm_get_supported_msrs(KVMState *s)
>> has_msr_hv_runtime = true;
>> continue;
>> }
>> + if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
>> + has_msr_hv_synic = true;
>> + continue;
>> + }
>> }
>> }
>>
>> @@ -1511,6 +1525,31 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
>> kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
>> env->msr_hv_runtime);
>> }
>> + if (cpu->hyperv_synic) {
>> + int j;
>> +
>> + if (!env->msr_hv_synic_version) {
>> + /* First time initialization */
>> + env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
>> + for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
>> + env->msr_hv_synic_sint[j] = HV_SYNIC_SINT_MASKED;
>> + }
>> + }
>
> I would prefer to put this in kvm_arch_init_vcpu, if possible.
>
Ok. I think the kvm_arch_init_vcpu() is called after migration restores
cpu->env->msr_hv_synic_* values, so unconditional initialization of
cpu->env->msr_hv_synic_* values can overwrite migrated values. The check
"if (!env->msr_hv_synic_version) {" is neccessary for first time
initialization to protect against such overwriting. This is why this
code migrates 'msr_hv_synic_version' value.
>> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL,
>> + env->msr_hv_synic_control);
>> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION,
>> + env->msr_hv_synic_version);
>> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP,
>> + env->msr_hv_synic_evt_page);
>> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP,
>> + env->msr_hv_synic_msg_page);
>> +
>> + for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
>> + kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j,
>> + env->msr_hv_synic_sint[j]);
>> + }
>> + }
>> if (has_msr_mtrr) {
>> kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
>> kvm_msr_entry_set(&msrs[n++],
>> @@ -1879,6 +1918,17 @@ static int kvm_get_msrs(X86CPU *cpu)
>> if (has_msr_hv_runtime) {
>> msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
>> }
>> + if (cpu->hyperv_synic) {
>> + uint32_t msr;
>> +
>> + msrs[n++].index = HV_X64_MSR_SCONTROL;
>> + msrs[n++].index = HV_X64_MSR_SVERSION;
>> + msrs[n++].index = HV_X64_MSR_SIEFP;
>> + msrs[n++].index = HV_X64_MSR_SIMP;
>> + for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
>> + msrs[n++].index = msr;
>> + }
>> + }
>> if (has_msr_mtrr) {
>> msrs[n++].index = MSR_MTRRdefType;
>> msrs[n++].index = MSR_MTRRfix64K_00000;
>> @@ -2035,6 +2085,21 @@ static int kvm_get_msrs(X86CPU *cpu)
>> case HV_X64_MSR_VP_RUNTIME:
>> env->msr_hv_runtime = msrs[i].data;
>> break;
>> + case HV_X64_MSR_SCONTROL:
>> + env->msr_hv_synic_control = msrs[i].data;
>> + break;
>> + case HV_X64_MSR_SVERSION:
>> + env->msr_hv_synic_version = msrs[i].data;
>> + break;
>> + case HV_X64_MSR_SIEFP:
>> + env->msr_hv_synic_evt_page = msrs[i].data;
>> + break;
>> + case HV_X64_MSR_SIMP:
>> + env->msr_hv_synic_msg_page = msrs[i].data;
>> + break;
>> + case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
>> + env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
>> + break;
>> case MSR_MTRRdefType:
>> env->mtrr_deftype = msrs[i].data;
>> break;
>> diff --git a/target-i386/machine.c b/target-i386/machine.c
>> index a18e16e..bdb2997 100644
>> --- a/target-i386/machine.c
>> +++ b/target-i386/machine.c
>> @@ -710,6 +710,44 @@ static const VMStateDescription vmstate_msr_hyperv_runtime = {
>> }
>> };
>>
>> +static bool hyperv_synic_enable_needed(void *opaque)
>> +{
>> + X86CPU *cpu = opaque;
>> + CPUX86State *env = &cpu->env;
>> + int i;
>> +
>> + if (env->msr_hv_synic_control != 0 ||
>> + env->msr_hv_synic_version != 0 ||
>> + env->msr_hv_synic_evt_page != 0 ||
>> + env->msr_hv_synic_msg_page != 0) {
>> + return true;
>> + }
>> +
>> + for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
>> + if (env->msr_hv_synic_sint[i] != 0) {
>> + return true;
>> + }
>> + }
>> +
>> + return false;
>> +}
>> +
>> +static const VMStateDescription vmstate_msr_hyperv_synic = {
>> + .name = "cpu/msr_hyperv_synic",
>> + .version_id = 1,
>> + .minimum_version_id = 1,
>> + .needed = hyperv_synic_enable_needed,
>> + .fields = (VMStateField[]) {
>> + VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
>> + VMSTATE_UINT64(env.msr_hv_synic_version, X86CPU),
>
> This one need not be migrated, since it's always the same value.
>
see my comment above
> Paolo
>
>> + VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
>> + VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
>> + VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
>> + HV_SYNIC_SINT_COUNT),
>> + VMSTATE_END_OF_LIST()
>> + }
>> +};
>> +
>> static bool avx512_needed(void *opaque)
>> {
>> X86CPU *cpu = opaque;
>> @@ -893,6 +931,7 @@ VMStateDescription vmstate_x86_cpu = {
>> &vmstate_msr_hyperv_time,
>> &vmstate_msr_hyperv_crash,
>> &vmstate_msr_hyperv_runtime,
>> + &vmstate_msr_hyperv_synic,
>> &vmstate_avx512,
>> &vmstate_xss,
>> NULL
>>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-11 9:09 ` Andrey Smetanin
@ 2015-11-11 9:17 ` Paolo Bonzini
2015-11-11 9:25 ` Andrey Smetanin
0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2015-11-11 9:17 UTC (permalink / raw)
To: asmetanin, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 11/11/2015 10:09, Andrey Smetanin wrote:
>>
>> I would prefer to put this in kvm_arch_init_vcpu, if possible.
>>
> Ok. I think the kvm_arch_init_vcpu() is called after migration restores
> cpu->env->msr_hv_synic_* values, so unconditional initialization of
> cpu->env->msr_hv_synic_* values can overwrite migrated values. The check
> "if (!env->msr_hv_synic_version) {" is neccessary for first time
> initialization to protect against such overwriting. This is why this
> code migrates 'msr_hv_synic_version' value.
No, kvm_arch_init_vcpu is called at the very beginning, when the VCPU
thread is created.
main
-> machine_class->init
-> pc_init1
-> pc_cpus_init
-> pc_new_cpu
-> cpu_x86_create
-> object_property_set_bool
-> x86_cpu_realizefn
-> qemu_init_vcpu
-> qemu_kvm_start_vcpu
-> qemu_kvm_cpu_thread_fn (in new thread)
-> kvm_init_vcpu
-> kvm_arch_init_vcpu
This is long before qemu_start_incoming_migration, which is among the
last things done before calling main_loop
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-11 9:17 ` Paolo Bonzini
@ 2015-11-11 9:25 ` Andrey Smetanin
2015-11-11 10:05 ` Paolo Bonzini
0 siblings, 1 reply; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-11 9:25 UTC (permalink / raw)
To: Paolo Bonzini, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 11/11/2015 12:17 PM, Paolo Bonzini wrote:
>
>
> On 11/11/2015 10:09, Andrey Smetanin wrote:
>>>
>>> I would prefer to put this in kvm_arch_init_vcpu, if possible.
>>>
>> Ok. I think the kvm_arch_init_vcpu() is called after migration restores
>> cpu->env->msr_hv_synic_* values, so unconditional initialization of
>> cpu->env->msr_hv_synic_* values can overwrite migrated values. The check
>> "if (!env->msr_hv_synic_version) {" is neccessary for first time
>> initialization to protect against such overwriting. This is why this
>> code migrates 'msr_hv_synic_version' value.
>
> No, kvm_arch_init_vcpu is called at the very beginning, when the VCPU
> thread is created.
>
> main
> -> machine_class->init
> -> pc_init1
> -> pc_cpus_init
> -> pc_new_cpu
> -> cpu_x86_create
> -> object_property_set_bool
> -> x86_cpu_realizefn
> -> qemu_init_vcpu
> -> qemu_kvm_start_vcpu
> -> qemu_kvm_cpu_thread_fn (in new thread)
> -> kvm_init_vcpu
> -> kvm_arch_init_vcpu
>
> This is long before qemu_start_incoming_migration, which is among the
> last things done before calling main_loop
In this case I'll remove migration of msr_hv_synic_version and make
first time initialization inside kvm_arch_init_vcpu() - inside section
where SynIC availability cpuid bit is set.
Thank you for clarification.
>
> Paolo
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-11 9:25 ` Andrey Smetanin
@ 2015-11-11 10:05 ` Paolo Bonzini
0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2015-11-11 10:05 UTC (permalink / raw)
To: asmetanin, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 11/11/2015 10:25, Andrey Smetanin wrote:
> In this case I'll remove migration of msr_hv_synic_version and make
> first time initialization inside kvm_arch_init_vcpu() - inside section
> where SynIC availability cpuid bit is set.
Thanks!
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v3 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-10 13:14 ` Paolo Bonzini
2015-11-11 9:09 ` Andrey Smetanin
@ 2015-11-11 10:18 ` Andrey Smetanin
2015-11-11 11:17 ` Paolo Bonzini
1 sibling, 1 reply; 13+ messages in thread
From: Andrey Smetanin @ 2015-11-11 10:18 UTC (permalink / raw)
To: qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan, Paolo Bonzini,
Denis V. Lunev, Andreas Färber, Richard Henderson
This patch does Hyper-V Synthetic interrupt
controller(Hyper-V SynIC) MSR's support and
migration. Hyper-V SynIC is enabled by cpu's
'hv-synic' option.
This patch does not allow cpu creation if
'hv-synic' option specified but kernel
doesn't support Hyper-V SynIC.
Changes v3:
* removed 'msr_hv_synic_version' migration because
it's value always the same
* moved SynIC msr's initialization into kvm_arch_init_vcpu
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Richard Henderson <rth@twiddle.net>
CC: Eduardo Habkost <ehabkost@redhat.com>
CC: "Andreas Färber" <afaerber@suse.de>
CC: Marcelo Tosatti <mtosatti@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: kvm@vger.kernel.org
---
target-i386/cpu-qom.h | 1 +
target-i386/cpu.c | 1 +
target-i386/cpu.h | 5 ++++
target-i386/kvm.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++-
target-i386/machine.c | 37 +++++++++++++++++++++++++++++
5 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index e3bfe9d..7ea5b34 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -94,6 +94,7 @@ typedef struct X86CPU {
bool hyperv_reset;
bool hyperv_vpindex;
bool hyperv_runtime;
+ bool hyperv_synic;
bool check_cpuid;
bool enforce_cpuid;
bool expose_kvm;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index e5f1c5b..1462e19 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -3142,6 +3142,7 @@ static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
+ DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index fc4a605..8cf33df 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -918,6 +918,11 @@ typedef struct CPUX86State {
uint64_t msr_hv_tsc;
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
uint64_t msr_hv_runtime;
+ uint64_t msr_hv_synic_control;
+ uint64_t msr_hv_synic_version;
+ uint64_t msr_hv_synic_evt_page;
+ uint64_t msr_hv_synic_msg_page;
+ uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
/* exception/interrupt handling */
int error_code;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 2a9953b..3f2ea90 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -86,6 +86,7 @@ static bool has_msr_hv_crash;
static bool has_msr_hv_reset;
static bool has_msr_hv_vpindex;
static bool has_msr_hv_runtime;
+static bool has_msr_hv_synic;
static bool has_msr_mtrr;
static bool has_msr_xss;
@@ -521,7 +522,8 @@ static bool hyperv_enabled(X86CPU *cpu)
cpu->hyperv_crash ||
cpu->hyperv_reset ||
cpu->hyperv_vpindex ||
- cpu->hyperv_runtime);
+ cpu->hyperv_runtime ||
+ cpu->hyperv_synic);
}
static Error *invtsc_mig_blocker;
@@ -610,6 +612,21 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (cpu->hyperv_runtime && has_msr_hv_runtime) {
c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
}
+ if (cpu->hyperv_synic) {
+ int sint;
+
+ if (!has_msr_hv_synic ||
+ kvm_vcpu_enable_cap(cs, KVM_CAP_HYPERV_SYNIC, 0)) {
+ fprintf(stderr, "Hyper-V SynIC is not supported by kernel\n");
+ return -ENOSYS;
+ }
+
+ c->eax |= HV_X64_MSR_SYNIC_AVAILABLE;
+ env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
+ for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
+ env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
+ }
+ }
c = &cpuid_data.entries[cpuid_i++];
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
if (cpu->hyperv_relaxed_timing) {
@@ -950,6 +967,10 @@ static int kvm_get_supported_msrs(KVMState *s)
has_msr_hv_runtime = true;
continue;
}
+ if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
+ has_msr_hv_synic = true;
+ continue;
+ }
}
}
@@ -1511,6 +1532,23 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
env->msr_hv_runtime);
}
+ if (cpu->hyperv_synic) {
+ int j;
+
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SCONTROL,
+ env->msr_hv_synic_control);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SVERSION,
+ env->msr_hv_synic_version);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIEFP,
+ env->msr_hv_synic_evt_page);
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SIMP,
+ env->msr_hv_synic_msg_page);
+
+ for (j = 0; j < ARRAY_SIZE(env->msr_hv_synic_sint); j++) {
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_SINT0 + j,
+ env->msr_hv_synic_sint[j]);
+ }
+ }
if (has_msr_mtrr) {
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
kvm_msr_entry_set(&msrs[n++],
@@ -1879,6 +1917,17 @@ static int kvm_get_msrs(X86CPU *cpu)
if (has_msr_hv_runtime) {
msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
}
+ if (cpu->hyperv_synic) {
+ uint32_t msr;
+
+ msrs[n++].index = HV_X64_MSR_SCONTROL;
+ msrs[n++].index = HV_X64_MSR_SVERSION;
+ msrs[n++].index = HV_X64_MSR_SIEFP;
+ msrs[n++].index = HV_X64_MSR_SIMP;
+ for (msr = HV_X64_MSR_SINT0; msr <= HV_X64_MSR_SINT15; msr++) {
+ msrs[n++].index = msr;
+ }
+ }
if (has_msr_mtrr) {
msrs[n++].index = MSR_MTRRdefType;
msrs[n++].index = MSR_MTRRfix64K_00000;
@@ -2035,6 +2084,21 @@ static int kvm_get_msrs(X86CPU *cpu)
case HV_X64_MSR_VP_RUNTIME:
env->msr_hv_runtime = msrs[i].data;
break;
+ case HV_X64_MSR_SCONTROL:
+ env->msr_hv_synic_control = msrs[i].data;
+ break;
+ case HV_X64_MSR_SVERSION:
+ env->msr_hv_synic_version = msrs[i].data;
+ break;
+ case HV_X64_MSR_SIEFP:
+ env->msr_hv_synic_evt_page = msrs[i].data;
+ break;
+ case HV_X64_MSR_SIMP:
+ env->msr_hv_synic_msg_page = msrs[i].data;
+ break;
+ case HV_X64_MSR_SINT0 ... HV_X64_MSR_SINT15:
+ env->msr_hv_synic_sint[index - HV_X64_MSR_SINT0] = msrs[i].data;
+ break;
case MSR_MTRRdefType:
env->mtrr_deftype = msrs[i].data;
break;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index a18e16e..d41e286 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -710,6 +710,42 @@ static const VMStateDescription vmstate_msr_hyperv_runtime = {
}
};
+static bool hyperv_synic_enable_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ if (env->msr_hv_synic_control != 0 ||
+ env->msr_hv_synic_evt_page != 0 ||
+ env->msr_hv_synic_msg_page != 0) {
+ return true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
+ if (env->msr_hv_synic_sint[i] != 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static const VMStateDescription vmstate_msr_hyperv_synic = {
+ .name = "cpu/msr_hyperv_synic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = hyperv_synic_enable_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
+ VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
+ VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
+ VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
+ HV_SYNIC_SINT_COUNT),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool avx512_needed(void *opaque)
{
X86CPU *cpu = opaque;
@@ -893,6 +929,7 @@ VMStateDescription vmstate_x86_cpu = {
&vmstate_msr_hyperv_time,
&vmstate_msr_hyperv_crash,
&vmstate_msr_hyperv_runtime,
+ &vmstate_msr_hyperv_synic,
&vmstate_avx512,
&vmstate_xss,
NULL
--
2.4.3
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v3 2/5] target-i386/kvm: Hyper-V SynIC MSR's support
2015-11-11 10:18 ` [Qemu-devel] [PATCH v3 " Andrey Smetanin
@ 2015-11-11 11:17 ` Paolo Bonzini
0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2015-11-11 11:17 UTC (permalink / raw)
To: Andrey Smetanin, qemu-devel
Cc: Eduardo Habkost, kvm, Marcelo Tosatti, Roman Kagan,
Denis V. Lunev, Andreas Färber, Richard Henderson
On 11/11/2015 11:18, Andrey Smetanin wrote:
> This patch does Hyper-V Synthetic interrupt
> controller(Hyper-V SynIC) MSR's support and
> migration. Hyper-V SynIC is enabled by cpu's
> 'hv-synic' option.
>
> This patch does not allow cpu creation if
> 'hv-synic' option specified but kernel
> doesn't support Hyper-V SynIC.
>
> Changes v3:
> * removed 'msr_hv_synic_version' migration because
> it's value always the same
> * moved SynIC msr's initialization into kvm_arch_init_vcpu
>
> Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> CC: Paolo Bonzini <pbonzini@redhat.com>
> CC: Richard Henderson <rth@twiddle.net>
> CC: Eduardo Habkost <ehabkost@redhat.com>
> CC: "Andreas Färber" <afaerber@suse.de>
> CC: Marcelo Tosatti <mtosatti@redhat.com>
> CC: Roman Kagan <rkagan@virtuozzo.com>
> CC: Denis V. Lunev <den@openvz.org>
> CC: kvm@vger.kernel.org
Thanks, pushed to uq/hyperv. The new kernel patches work with APICv,
and I'll push them as soon as the merge window ends to kvm/queue.
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-11-11 11:17 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-10 12:52 [Qemu-devel] [PATCH v2 0/5] QEMU: Hyper-V SynIC support Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 1/5] headers: Linux kernel Hyper-V SynIC defines Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 2/5] target-i386/kvm: Hyper-V SynIC MSR's support Andrey Smetanin
2015-11-10 13:14 ` Paolo Bonzini
2015-11-11 9:09 ` Andrey Smetanin
2015-11-11 9:17 ` Paolo Bonzini
2015-11-11 9:25 ` Andrey Smetanin
2015-11-11 10:05 ` Paolo Bonzini
2015-11-11 10:18 ` [Qemu-devel] [PATCH v3 " Andrey Smetanin
2015-11-11 11:17 ` Paolo Bonzini
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 3/5] kvm: Hyper-V SynIC irq routing support Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 4/5] target-i386/hyperv: Hyper-V SynIC SINT routing and vcpu exit Andrey Smetanin
2015-11-10 12:52 ` [Qemu-devel] [PATCH v2 5/5] hw/misc: Hyper-V test device 'hyperv-testdev' Andrey Smetanin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).