* [PATCH kvm-unit-tests 1/5] hyperv: move test dev control codes to C file
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
@ 2017-06-06 19:19 ` Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 2/5] hyperv: don't take vcpu where inappropriate Roman Kagan
` (4 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Roman Kagan @ 2017-06-06 19:19 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, Evgeny Yakovlev,
Denis V . Lunev
hyperv_testdev control codes aren't used outside hyperv.c so move them
there. While at this, adjust the types to avoid surprizes with left
shifts.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
x86/hyperv.h | 6 ------
x86/hyperv.c | 9 ++++++++-
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/x86/hyperv.h b/x86/hyperv.h
index bef0317..553c588 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -155,12 +155,6 @@ struct hv_message_page {
struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
};
-enum {
- HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
- HV_TEST_DEV_SINT_ROUTE_DESTROY,
- HV_TEST_DEV_SINT_ROUTE_SET_SINT
-};
-
static inline bool synic_supported(void)
{
return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
diff --git a/x86/hyperv.c b/x86/hyperv.c
index 2511aa2..aa55614 100644
--- a/x86/hyperv.c
+++ b/x86/hyperv.c
@@ -1,7 +1,14 @@
#include "hyperv.h"
#include "asm/io.h"
+#include "smp.h"
-static void synic_ctl(u8 ctl, u8 vcpu_id, u8 sint)
+enum {
+ HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
+ HV_TEST_DEV_SINT_ROUTE_DESTROY,
+ HV_TEST_DEV_SINT_ROUTE_SET_SINT,
+};
+
+static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint)
{
outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000);
}
--
2.9.4
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH kvm-unit-tests 2/5] hyperv: don't take vcpu where inappropriate
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 1/5] hyperv: move test dev control codes to C file Roman Kagan
@ 2017-06-06 19:19 ` Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 3/5] hyperv: add more test control codes Roman Kagan
` (3 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Roman Kagan @ 2017-06-06 19:19 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, Evgeny Yakovlev,
Denis V . Lunev
MSRs can not be written on a forein cpu, so the functions to create /
destroy sint routes, which also enable / disable the respective SINTs,
can only run on the current cpu. To avoid confusion, stop taking vcpu
argument and use smp_id() internally.
While chaning the function signatures, also adjust them to be explicit
about the width of input values.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
x86/hyperv.h | 6 +++---
x86/hyperv.c | 24 +++++++++++++++++-------
x86/hyperv_stimer.c | 12 ++++--------
x86/hyperv_synic.c | 6 ++----
4 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/x86/hyperv.h b/x86/hyperv.h
index 553c588..2331325 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -170,9 +170,9 @@ static inline bool hv_time_ref_counter_supported(void)
return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
}
-void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi);
-void synic_sint_set(int vcpu, int sint);
-void synic_sint_destroy(int vcpu, int sint);
+void synic_sint_create(u8 sint, u8 vec, bool auto_eoi);
+void synic_sint_set(u8 vcpu, u8 sint);
+void synic_sint_destroy(u8 sint);
struct hv_reference_tsc_page {
uint32_t tsc_sequence;
diff --git a/x86/hyperv.c b/x86/hyperv.c
index aa55614..78f5fb5 100644
--- a/x86/hyperv.c
+++ b/x86/hyperv.c
@@ -13,20 +13,30 @@ static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint)
outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000);
}
-void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi)
+static void sint_enable(u8 sint, u8 vec, bool auto_eoi)
{
wrmsr(HV_X64_MSR_SINT0 + sint,
- (u64)vec | ((auto_eoi) ? HV_SYNIC_SINT_AUTO_EOI : 0));
- synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, vcpu, sint);
+ (u64)vec | (auto_eoi ? HV_SYNIC_SINT_AUTO_EOI : 0));
}
-void synic_sint_set(int vcpu, int sint)
+static void sint_disable(u8 sint)
+{
+ wrmsr(HV_X64_MSR_SINT0 + sint, 0xff | HV_SYNIC_SINT_MASKED);
+}
+
+void synic_sint_create(u8 sint, u8 vec, bool auto_eoi)
+{
+ synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, smp_id(), sint);
+ sint_enable(sint, vec, auto_eoi);
+}
+
+void synic_sint_set(u8 vcpu, u8 sint)
{
synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint);
}
-void synic_sint_destroy(int vcpu, int sint)
+void synic_sint_destroy(u8 sint)
{
- wrmsr(HV_X64_MSR_SINT0 + sint, 0xFF|HV_SYNIC_SINT_MASKED);
- synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, vcpu, sint);
+ sint_disable(sint);
+ synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, smp_id(), sint);
}
diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index 5292523..2ec3842 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -223,12 +223,10 @@ static void cpu_comp(void)
static void stimer_test_prepare(void *ctx)
{
- int vcpu = smp_id();
-
write_cr3((ulong)ctx);
synic_enable();
- synic_sint_create(vcpu, SINT1_NUM, SINT1_VEC, false);
- synic_sint_create(vcpu, SINT2_NUM, SINT2_VEC, true);
+ synic_sint_create(SINT1_NUM, SINT1_VEC, false);
+ synic_sint_create(SINT2_NUM, SINT2_VEC, true);
cpu_comp();
}
@@ -302,11 +300,9 @@ static void stimer_test(void *ctx)
static void stimer_test_cleanup(void *ctx)
{
- int vcpu = smp_id();
-
stimers_shutdown();
- synic_sint_destroy(vcpu, SINT1_NUM);
- synic_sint_destroy(vcpu, SINT2_NUM);
+ synic_sint_destroy(SINT1_NUM);
+ synic_sint_destroy(SINT2_NUM);
synic_disable();
cpu_comp();
}
diff --git a/x86/hyperv_synic.c b/x86/hyperv_synic.c
index a08e69f..e0fb6e8 100644
--- a/x86/hyperv_synic.c
+++ b/x86/hyperv_synic.c
@@ -69,7 +69,7 @@ static void synic_sints_prepare(int vcpu)
for (i = 0; i < HV_SYNIC_SINT_COUNT; i++) {
vec = sint_vecs[i].vec;
auto_eoi = sint_vecs[i].auto_eoi;
- synic_sint_create(vcpu, i, vec, auto_eoi);
+ synic_sint_create(i, vec, auto_eoi);
}
}
@@ -130,13 +130,11 @@ static void synic_test(void *ctx)
static void synic_test_cleanup(void *ctx)
{
- int vcpu = smp_id();
int i;
irq_enable();
for (i = 0; i < HV_SYNIC_SINT_COUNT; i++) {
- synic_sint_destroy(vcpu, i);
- wrmsr(HV_X64_MSR_SINT0 + i, 0xFF|HV_SYNIC_SINT_MASKED);
+ synic_sint_destroy(i);
}
wrmsr(HV_X64_MSR_SCONTROL, 0);
--
2.9.4
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH kvm-unit-tests 3/5] hyperv: add more test control codes
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 1/5] hyperv: move test dev control codes to C file Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 2/5] hyperv: don't take vcpu where inappropriate Roman Kagan
@ 2017-06-06 19:19 ` Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 4/5] hyperv: add more hyperv definitions Roman Kagan
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Roman Kagan @ 2017-06-06 19:19 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, Evgeny Yakovlev,
Denis V . Lunev
Add helpers for the recently added message and event connection test
modes.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
x86/hyperv.h | 4 ++++
x86/hyperv.c | 38 +++++++++++++++++++++++++++++++++-----
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/x86/hyperv.h b/x86/hyperv.h
index 2331325..76a569a 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -173,6 +173,10 @@ static inline bool hv_time_ref_counter_supported(void)
void synic_sint_create(u8 sint, u8 vec, bool auto_eoi);
void synic_sint_set(u8 vcpu, u8 sint);
void synic_sint_destroy(u8 sint);
+void msg_conn_create(u8 sint, u8 vec, u8 conn_id);
+void msg_conn_destroy(u8 sint, u8 conn_id);
+void evt_conn_create(u8 sint, u8 vec, u8 conn_id);
+void evt_conn_destroy(u8 sint, u8 conn_id);
struct hv_reference_tsc_page {
uint32_t tsc_sequence;
diff --git a/x86/hyperv.c b/x86/hyperv.c
index 78f5fb5..60f7645 100644
--- a/x86/hyperv.c
+++ b/x86/hyperv.c
@@ -6,11 +6,15 @@ enum {
HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
HV_TEST_DEV_SINT_ROUTE_DESTROY,
HV_TEST_DEV_SINT_ROUTE_SET_SINT,
+ HV_TEST_DEV_MSG_CONN_CREATE,
+ HV_TEST_DEV_MSG_CONN_DESTROY,
+ HV_TEST_DEV_EVT_CONN_CREATE,
+ HV_TEST_DEV_EVT_CONN_DESTROY,
};
-static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint)
+static void synic_ctl(u32 ctl, u32 vcpu_id, u32 sint, u32 conn_id)
{
- outl((ctl << 16)|((vcpu_id) << 8)|sint, 0x3000);
+ outl((conn_id << 24) | (ctl << 16) | (vcpu_id << 8) | sint, 0x3000);
}
static void sint_enable(u8 sint, u8 vec, bool auto_eoi)
@@ -26,17 +30,41 @@ static void sint_disable(u8 sint)
void synic_sint_create(u8 sint, u8 vec, bool auto_eoi)
{
- synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, smp_id(), sint);
+ synic_ctl(HV_TEST_DEV_SINT_ROUTE_CREATE, smp_id(), sint, 0);
sint_enable(sint, vec, auto_eoi);
}
void synic_sint_set(u8 vcpu, u8 sint)
{
- synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint);
+ synic_ctl(HV_TEST_DEV_SINT_ROUTE_SET_SINT, vcpu, sint, 0);
}
void synic_sint_destroy(u8 sint)
{
sint_disable(sint);
- synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, smp_id(), sint);
+ synic_ctl(HV_TEST_DEV_SINT_ROUTE_DESTROY, smp_id(), sint, 0);
+}
+
+void msg_conn_create(u8 sint, u8 vec, u8 conn_id)
+{
+ synic_ctl(HV_TEST_DEV_MSG_CONN_CREATE, smp_id(), sint, conn_id);
+ sint_enable(sint, vec, true);
+}
+
+void msg_conn_destroy(u8 sint, u8 conn_id)
+{
+ sint_disable(sint);
+ synic_ctl(HV_TEST_DEV_MSG_CONN_DESTROY, 0, 0, conn_id);
+}
+
+void evt_conn_create(u8 sint, u8 vec, u8 conn_id)
+{
+ synic_ctl(HV_TEST_DEV_EVT_CONN_CREATE, smp_id(), sint, conn_id);
+ sint_enable(sint, vec, true);
+}
+
+void evt_conn_destroy(u8 sint, u8 conn_id)
+{
+ sint_disable(sint);
+ synic_ctl(HV_TEST_DEV_EVT_CONN_DESTROY, 0, 0, conn_id);
}
--
2.9.4
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH kvm-unit-tests 4/5] hyperv: add more hyperv definitions
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
` (2 preceding siblings ...)
2017-06-06 19:19 ` [PATCH kvm-unit-tests 3/5] hyperv: add more test control codes Roman Kagan
@ 2017-06-06 19:19 ` Roman Kagan
2017-06-06 19:19 ` [PATCH kvm-unit-tests 5/5] add hyperv_connections test Roman Kagan
2017-06-14 18:58 ` [PATCH kvm-unit-tests 0/5] add test for hyperv connections Radim Krčmář
5 siblings, 0 replies; 14+ messages in thread
From: Roman Kagan @ 2017-06-06 19:19 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, Evgeny Yakovlev,
Denis V . Lunev
Add Hyper-V definitions necessary for message end event connection
tests.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
x86/hyperv.h | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/x86/hyperv.h b/x86/hyperv.h
index 76a569a..e135221 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -10,6 +10,9 @@
#define HV_X64_MSR_SYNIC_AVAILABLE (1 << 2)
#define HV_X64_MSR_SYNTIMER_AVAILABLE (1 << 3)
+#define HV_X64_MSR_GUEST_OS_ID 0x40000000
+#define HV_X64_MSR_HYPERCALL 0x40000001
+
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
@@ -155,6 +158,31 @@ struct hv_message_page {
struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
};
+#define HV_EVENT_FLAGS_COUNT (256 * 8)
+
+struct hv_event_flags {
+ ulong flags[HV_EVENT_FLAGS_COUNT / (8 * sizeof(ulong))];
+};
+
+struct hv_event_flags_page {
+ struct hv_event_flags slot[HV_SYNIC_SINT_COUNT];
+};
+
+#define HV_X64_MSR_HYPERCALL_ENABLE 0x1
+
+#define HV_HYPERCALL_FAST (1u << 16)
+
+#define HVCALL_POST_MESSAGE 0x5c
+#define HVCALL_SIGNAL_EVENT 0x5d
+
+struct hv_input_post_message {
+ u32 connectionid;
+ u32 reserved;
+ u32 message_type;
+ u32 payload_size;
+ u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
+};
+
static inline bool synic_supported(void)
{
return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
--
2.9.4
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
` (3 preceding siblings ...)
2017-06-06 19:19 ` [PATCH kvm-unit-tests 4/5] hyperv: add more hyperv definitions Roman Kagan
@ 2017-06-06 19:19 ` Roman Kagan
2017-06-13 19:28 ` Radim Krčmář
2017-06-14 18:58 ` [PATCH kvm-unit-tests 0/5] add test for hyperv connections Radim Krčmář
5 siblings, 1 reply; 14+ messages in thread
From: Roman Kagan @ 2017-06-06 19:19 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, Evgeny Yakovlev,
Denis V . Lunev
Add a test for Hyper-V message and event connections.
It requires QEMU with the extended test device supporting message end
event connection test modes (recently posted on qemu-devel). On older
QEMU versions it fails.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
x86/Makefile.common | 3 +
x86/hyperv_connections.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++
x86/unittests.cfg | 5 +
3 files changed, 336 insertions(+)
create mode 100644 x86/hyperv_connections.c
diff --git a/x86/Makefile.common b/x86/Makefile.common
index 7bb6b50..ca97a8e 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -49,6 +49,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
$(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \
$(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \
$(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \
+ $(TEST_DIR)/hyperv_connections.flat \
ifdef API
tests-api = api/api-sample api/dirty-log api/dirty-log-perf
@@ -71,6 +72,8 @@ $(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o
$(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o
+$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o
+
arch_clean:
$(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \
$(TEST_DIR)/.*.d lib/x86/.*.d \
diff --git a/x86/hyperv_connections.c b/x86/hyperv_connections.c
new file mode 100644
index 0000000..5ce1fb3
--- /dev/null
+++ b/x86/hyperv_connections.c
@@ -0,0 +1,328 @@
+#include "libcflat.h"
+#include "vm.h"
+#include "smp.h"
+#include "isr.h"
+#include "atomic.h"
+#include "hyperv.h"
+#include "bitops.h"
+
+#define MAX_CPUS 64
+
+#define MSG_VEC 0xb0
+#define EVT_VEC 0xb1
+#define MSG_SINT 0x8
+#define EVT_SINT 0x9
+#define MSG_CONN_BASE 0x10
+#define EVT_CONN_BASE 0x20
+#define MSG_TYPE 0x12345678
+
+#define WAIT_CYCLES 10000000
+
+static atomic_t ncpus_done;
+
+struct hv_vcpu {
+ struct hv_message_page *msg_page;
+ struct hv_event_flags_page *evt_page;
+ struct hv_input_post_message *post_msg;
+ u8 msg_conn;
+ u8 evt_conn;
+ u64 hvcall_status;
+ atomic_t sint_received;
+};
+
+static struct hv_vcpu hv_vcpus[MAX_CPUS];
+
+static void sint_isr(isr_regs_t *regs)
+{
+ atomic_inc(&hv_vcpus[smp_id()].sint_received);
+}
+
+static void *hypercall_page;
+
+static void setup_hypercall()
+{
+ u64 guestid = (0x8f00ull << 48);
+
+ hypercall_page = alloc_page();
+ memset(hypercall_page, 0, PAGE_SIZE);
+
+ wrmsr(HV_X64_MSR_GUEST_OS_ID, guestid);
+
+ wrmsr(HV_X64_MSR_HYPERCALL,
+ (u64)virt_to_phys(hypercall_page) | HV_X64_MSR_HYPERCALL_ENABLE);
+}
+
+static void teardown_hypercall()
+{
+ wrmsr(HV_X64_MSR_HYPERCALL, 0);
+ wrmsr(HV_X64_MSR_GUEST_OS_ID, 0);
+ free_page(hypercall_page);
+}
+
+static u64 do_hypercall(u16 code, u64 arg, bool fast)
+{
+ u64 ret;
+ u64 ctl = code;
+ if (fast)
+ ctl |= HV_HYPERCALL_FAST;
+
+ asm volatile ("call *%[hcall_page]"
+#ifdef __x86_64__
+ "\n mov $0,%%r8"
+ : "=a"(ret)
+ : "c"(ctl), "d"(arg),
+#else
+ : "=A"(ret)
+ : "A"(ctl),
+ "b" ((u32)(arg >> 32)), "c" ((u32)arg),
+ "D"(0), "S"(0),
+#endif
+ [hcall_page] "m" (hypercall_page)
+#ifdef __x86_64__
+ : "r8"
+#endif
+ );
+
+ return ret;
+}
+
+static void setup_cpu(void *ctx)
+{
+ int vcpu = smp_id();
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+
+ write_cr3((ulong)ctx);
+ irq_enable();
+
+ hv->msg_page = alloc_page();
+ hv->evt_page = alloc_page();
+ hv->post_msg = alloc_page();
+ memset(hv->msg_page, 0, sizeof(*hv->msg_page));
+ memset(hv->evt_page, 0, sizeof(*hv->evt_page));
+ memset(hv->post_msg, 0, sizeof(*hv->post_msg));
+ hv->msg_conn = MSG_CONN_BASE + vcpu;
+ hv->evt_conn = EVT_CONN_BASE + vcpu;
+
+ wrmsr(HV_X64_MSR_SIMP,
+ (u64)virt_to_phys(hv->msg_page) | HV_SYNIC_SIMP_ENABLE);
+ wrmsr(HV_X64_MSR_SIEFP,
+ (u64)virt_to_phys(hv->evt_page) | HV_SYNIC_SIEFP_ENABLE);
+ wrmsr(HV_X64_MSR_SCONTROL, HV_SYNIC_CONTROL_ENABLE);
+
+ msg_conn_create(MSG_SINT, MSG_VEC, hv->msg_conn);
+ evt_conn_create(EVT_SINT, EVT_VEC, hv->evt_conn);
+
+ hv->post_msg->connectionid = hv->msg_conn;
+ hv->post_msg->message_type = MSG_TYPE;
+ hv->post_msg->payload_size = 8;
+ hv->post_msg->payload[0] = (u64)vcpu << 16;
+}
+
+static void teardown_cpu(void *ctx)
+{
+ int vcpu = smp_id();
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+
+ evt_conn_destroy(EVT_SINT, hv->evt_conn);
+ msg_conn_destroy(MSG_SINT, hv->msg_conn);
+
+ wrmsr(HV_X64_MSR_SCONTROL, 0);
+ wrmsr(HV_X64_MSR_SIEFP, 0);
+ wrmsr(HV_X64_MSR_SIMP, 0);
+
+ free_page(hv->post_msg);
+ free_page(hv->evt_page);
+ free_page(hv->msg_page);
+}
+
+static void do_msg(void *ctx)
+{
+ int vcpu = (ulong)ctx;
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ struct hv_input_post_message *msg = hv->post_msg;
+
+ msg->payload[0]++;
+ atomic_set(&hv->sint_received, 0);
+ hv->hvcall_status = do_hypercall(HVCALL_POST_MESSAGE,
+ virt_to_phys(msg), 0);
+ atomic_inc(&ncpus_done);
+}
+
+static void clear_msg(void *ctx)
+{
+ /* should only be done on the current vcpu */
+ int vcpu = smp_id();
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT];
+
+ atomic_set(&hv->sint_received, 0);
+ msg->header.message_type = 0;
+ barrier();
+ wrmsr(HV_X64_MSR_EOM, 0);
+ atomic_inc(&ncpus_done);
+}
+
+static bool msg_ok(int vcpu)
+{
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ struct hv_input_post_message *post_msg = hv->post_msg;
+ struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT];
+
+ return msg->header.message_type == post_msg->message_type &&
+ msg->header.payload_size == post_msg->payload_size &&
+ msg->header.message_flags.msg_pending == 0 &&
+ msg->u.payload[0] == post_msg->payload[0] &&
+ hv->hvcall_status == 0 &&
+ atomic_read(&hv->sint_received) == 1;
+}
+
+static bool msg_busy(int vcpu)
+{
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ struct hv_input_post_message *post_msg = hv->post_msg;
+ struct hv_message *msg = &hv->msg_page->sint_message[MSG_SINT];
+
+ return msg->header.message_type == post_msg->message_type &&
+ msg->header.payload_size == post_msg->payload_size &&
+ msg->header.message_flags.msg_pending == 1 &&
+ msg->u.payload[0] == post_msg->payload[0] - 1 &&
+ hv->hvcall_status == 0 &&
+ atomic_read(&hv->sint_received) == 0;
+}
+
+static void do_evt(void *ctx)
+{
+ int vcpu = (ulong)ctx;
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+
+ atomic_set(&hv->sint_received, 0);
+ hv->hvcall_status = do_hypercall(HVCALL_SIGNAL_EVENT,
+ hv->evt_conn, 1);
+ atomic_inc(&ncpus_done);
+}
+
+static void clear_evt(void *ctx)
+{
+ /* should only be done on the current vcpu */
+ int vcpu = smp_id();
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ ulong *flags = hv->evt_page->slot[EVT_SINT].flags;
+
+ atomic_set(&hv->sint_received, 0);
+ flags[BIT_WORD(hv->evt_conn)] &= ~BIT_MASK(hv->evt_conn);
+ barrier();
+ atomic_inc(&ncpus_done);
+}
+
+static bool evt_ok(int vcpu)
+{
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ ulong *flags = hv->evt_page->slot[EVT_SINT].flags;
+
+ return flags[BIT_WORD(hv->evt_conn)] == BIT_MASK(hv->evt_conn) &&
+ hv->hvcall_status == 0 &&
+ atomic_read(&hv->sint_received) == 1;
+}
+
+static bool evt_busy(int vcpu)
+{
+ struct hv_vcpu *hv = &hv_vcpus[vcpu];
+ ulong *flags = hv->evt_page->slot[EVT_SINT].flags;
+
+ return flags[BIT_WORD(hv->evt_conn)] == BIT_MASK(hv->evt_conn) &&
+ hv->hvcall_status == 0 &&
+ atomic_read(&hv->sint_received) == 0;
+}
+
+static int run_test(int ncpus, int dst_add, ulong wait_cycles,
+ void (*func)(void *), bool (*is_ok)(int))
+{
+ int i, ret = 0;
+
+ atomic_set(&ncpus_done, 0);
+ for (i = 0; i < ncpus; i++) {
+ ulong dst = (i + dst_add) % ncpus;
+ on_cpu_async(i, func, (void *)dst);
+ }
+ while (atomic_read(&ncpus_done) != ncpus) {
+ pause();
+ }
+
+ while (wait_cycles--) {
+ pause();
+ }
+
+ if (is_ok) {
+ for (i = 0; i < ncpus; i++) {
+ ret += is_ok(i);
+ }
+ }
+ return ret;
+}
+
+int main(int ac, char **av)
+{
+ int ncpus, i, ncpus_ok;
+
+ if (!synic_supported()) {
+ report_skip("Hyper-V SynIC is not supported");
+ goto summary;
+ }
+
+ setup_vm();
+ smp_init();
+ ncpus = cpu_count();
+ if (ncpus > MAX_CPUS) {
+ ncpus = MAX_CPUS;
+ }
+
+ handle_irq(MSG_VEC, sint_isr);
+ handle_irq(EVT_VEC, sint_isr);
+
+ setup_hypercall();
+
+ for (i = 0; i < ncpus; i++) {
+ on_cpu(i, setup_cpu, (void *)read_cr3());
+ }
+
+ ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, do_msg, msg_ok);
+ report("send message to self: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ run_test(ncpus, 0, 0, clear_msg, NULL);
+
+ ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_msg, msg_ok);
+ report("send message to another cpu: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_msg, msg_busy);
+ report("send message to busy slot: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, clear_msg, msg_ok);
+ report("receive pending message: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ ncpus_ok = run_test(ncpus, 0, WAIT_CYCLES, do_evt, evt_ok);
+ report("signal event on self: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ run_test(ncpus, 0, 0, clear_evt, NULL);
+
+ ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_evt, evt_ok);
+ report("signal event on another cpu: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ ncpus_ok = run_test(ncpus, 1, WAIT_CYCLES, do_evt, evt_busy);
+ report("signal event already set: %d/%d",
+ ncpus_ok == ncpus, ncpus_ok, ncpus);
+
+ for (i = 0; i < ncpus; i++) {
+ on_cpu(i, teardown_cpu, NULL);
+ }
+
+ teardown_hypercall();
+
+summary:
+ return report_summary();
+}
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 5ab4667..f53151f 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -503,6 +503,11 @@ file = hyperv_synic.flat
smp = 2
extra_params = -cpu kvm64,hv_synic -device hyperv-testdev
+[hyperv_connections]
+file = hyperv_connections.flat
+smp = 2
+extra_params = -cpu kvm64,hv_synic -device hyperv-testdev
+
[hyperv_stimer]
file = hyperv_stimer.flat
smp = 2
--
2.9.4
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-06 19:19 ` [PATCH kvm-unit-tests 5/5] add hyperv_connections test Roman Kagan
@ 2017-06-13 19:28 ` Radim Krčmář
2017-06-14 11:28 ` Paolo Bonzini
2017-06-14 12:01 ` Roman Kagan
0 siblings, 2 replies; 14+ messages in thread
From: Radim Krčmář @ 2017-06-13 19:28 UTC (permalink / raw)
To: Roman Kagan; +Cc: kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
2017-06-06 22:19+0300, Roman Kagan:
> Add a test for Hyper-V message and event connections.
>
> It requires QEMU with the extended test device supporting message end
> event connection test modes (recently posted on qemu-devel). On older
> QEMU versions it fails.
Doesn't QEMU provide a way to detect this feature from the outside (some
command line magic) that we could use it to skip the test?
Thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-13 19:28 ` Radim Krčmář
@ 2017-06-14 11:28 ` Paolo Bonzini
2017-06-14 12:02 ` Roman Kagan
2017-06-14 12:01 ` Roman Kagan
1 sibling, 1 reply; 14+ messages in thread
From: Paolo Bonzini @ 2017-06-14 11:28 UTC (permalink / raw)
To: Radim Krčmář, Roman Kagan
Cc: kvm, Evgeny Yakovlev, Denis V . Lunev
On 13/06/2017 21:28, Radim Krčmář wrote:
>> It requires QEMU with the extended test device supporting message end
>> event connection test modes (recently posted on qemu-devel). On older
>> QEMU versions it fails.
> Doesn't QEMU provide a way to detect this feature from the outside (some
> command line magic) that we could use it to skip the test?
Should we check whether SIGNAL_EVENT returns
HV_STATUS_INVALID_HYPERCALL_CODE or HV_STATUS_INVALID_CONNECTION_ID, and
if the former skip the test completely?
Paolo
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-14 11:28 ` Paolo Bonzini
@ 2017-06-14 12:02 ` Roman Kagan
0 siblings, 0 replies; 14+ messages in thread
From: Roman Kagan @ 2017-06-14 12:02 UTC (permalink / raw)
To: Paolo Bonzini
Cc: Radim Krčmář, kvm, Evgeny Yakovlev,
Denis V . Lunev
On Wed, Jun 14, 2017 at 01:28:23PM +0200, Paolo Bonzini wrote:
>
>
> On 13/06/2017 21:28, Radim Krčmář wrote:
> >> It requires QEMU with the extended test device supporting message end
> >> event connection test modes (recently posted on qemu-devel). On older
> >> QEMU versions it fails.
> > Doesn't QEMU provide a way to detect this feature from the outside (some
> > command line magic) that we could use it to skip the test?
>
> Should we check whether SIGNAL_EVENT returns
> HV_STATUS_INVALID_HYPERCALL_CODE or HV_STATUS_INVALID_CONNECTION_ID, and
> if the former skip the test completely?
Yeah this looks like a workable solution, thanks!
Roman.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-13 19:28 ` Radim Krčmář
2017-06-14 11:28 ` Paolo Bonzini
@ 2017-06-14 12:01 ` Roman Kagan
2017-06-14 12:59 ` Radim Krčmář
1 sibling, 1 reply; 14+ messages in thread
From: Roman Kagan @ 2017-06-14 12:01 UTC (permalink / raw)
To: Radim Krčmář
Cc: kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
On Tue, Jun 13, 2017 at 09:28:59PM +0200, Radim Krčmář wrote:
> 2017-06-06 22:19+0300, Roman Kagan:
> > Add a test for Hyper-V message and event connections.
> >
> > It requires QEMU with the extended test device supporting message end
> > event connection test modes (recently posted on qemu-devel). On older
> > QEMU versions it fails.
>
> Doesn't QEMU provide a way to detect this feature from the outside (some
> command line magic) that we could use it to skip the test?
I didn't know there was such a trick. However, I failed to figure out
how to get it to work here: the -device options appeared to be
interpreted after -kernel so it didn't cause a SKIP; adding a dedicated
toplevel command-line option would probably be an overkill.
Roman.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-14 12:01 ` Roman Kagan
@ 2017-06-14 12:59 ` Radim Krčmář
2017-06-14 13:21 ` Roman Kagan
0 siblings, 1 reply; 14+ messages in thread
From: Radim Krčmář @ 2017-06-14 12:59 UTC (permalink / raw)
To: Roman Kagan, kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
2017-06-14 15:01+0300, Roman Kagan:
> On Tue, Jun 13, 2017 at 09:28:59PM +0200, Radim Krčmář wrote:
> > 2017-06-06 22:19+0300, Roman Kagan:
> > > Add a test for Hyper-V message and event connections.
> > >
> > > It requires QEMU with the extended test device supporting message end
> > > event connection test modes (recently posted on qemu-devel). On older
> > > QEMU versions it fails.
> >
> > Doesn't QEMU provide a way to detect this feature from the outside (some
> > command line magic) that we could use it to skip the test?
>
> I didn't know there was such a trick. However, I failed to figure out
> how to get it to work here: the -device options appeared to be
> interpreted after -kernel so it didn't cause a SKIP;
Hm, the test should be skipped if QEMU fails to start.
> adding a dedicated
> toplevel command-line option would probably be an overkill.
Right, I assumed that QEMU wants to prevent migration to QEMU's that
don't support this feature (which usually implies a property), but it
seems that there are no real users to care about ...
The solution proposed by Paolo looks good.
Thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-14 12:59 ` Radim Krčmář
@ 2017-06-14 13:21 ` Roman Kagan
2017-06-14 16:34 ` Radim Krčmář
0 siblings, 1 reply; 14+ messages in thread
From: Roman Kagan @ 2017-06-14 13:21 UTC (permalink / raw)
To: Radim Krčmář
Cc: kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
On Wed, Jun 14, 2017 at 02:59:51PM +0200, Radim Krčmář wrote:
> 2017-06-14 15:01+0300, Roman Kagan:
> > On Tue, Jun 13, 2017 at 09:28:59PM +0200, Radim Krčmář wrote:
> > > 2017-06-06 22:19+0300, Roman Kagan:
> > > > Add a test for Hyper-V message and event connections.
> > > >
> > > > It requires QEMU with the extended test device supporting message end
> > > > event connection test modes (recently posted on qemu-devel). On older
> > > > QEMU versions it fails.
> > >
> > > Doesn't QEMU provide a way to detect this feature from the outside (some
> > > command line magic) that we could use it to skip the test?
> >
> > I didn't know there was such a trick. However, I failed to figure out
> > how to get it to work here: the -device options appeared to be
> > interpreted after -kernel so it didn't cause a SKIP;
>
> Hm, the test should be skipped if QEMU fails to start.
IIUC the SKIP is taken when QEMU is run with the command line as if in
the real test, but with a -kernel option pointing at a non-existing
file, and the error message contains that filename.
The assumption is apparently that QEMU was ok with all other options.
The problem is that many options are interpreted after -kernel, so the
skip-checking logic decides that QEMU is ok with the options but the
actual test start shows that it's not, resulting in a FAIL.
Roman.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 5/5] add hyperv_connections test
2017-06-14 13:21 ` Roman Kagan
@ 2017-06-14 16:34 ` Radim Krčmář
0 siblings, 0 replies; 14+ messages in thread
From: Radim Krčmář @ 2017-06-14 16:34 UTC (permalink / raw)
To: Roman Kagan, kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
2017-06-14 16:21+0300, Roman Kagan:
> On Wed, Jun 14, 2017 at 02:59:51PM +0200, Radim Krčmář wrote:
> > 2017-06-14 15:01+0300, Roman Kagan:
> > > On Tue, Jun 13, 2017 at 09:28:59PM +0200, Radim Krčmář wrote:
> > > > 2017-06-06 22:19+0300, Roman Kagan:
> > > > > Add a test for Hyper-V message and event connections.
> > > > >
> > > > > It requires QEMU with the extended test device supporting message end
> > > > > event connection test modes (recently posted on qemu-devel). On older
> > > > > QEMU versions it fails.
> > > >
> > > > Doesn't QEMU provide a way to detect this feature from the outside (some
> > > > command line magic) that we could use it to skip the test?
> > >
> > > I didn't know there was such a trick. However, I failed to figure out
> > > how to get it to work here: the -device options appeared to be
> > > interpreted after -kernel so it didn't cause a SKIP;
> >
> > Hm, the test should be skipped if QEMU fails to start.
>
> IIUC the SKIP is taken when QEMU is run with the command line as if in
> the real test, but with a -kernel option pointing at a non-existing
> file, and the error message contains that filename.
Yes, it's an ugly hack.
> The assumption is apparently that QEMU was ok with all other options.
>
> The problem is that many options are interpreted after -kernel, so the
> skip-checking logic decides that QEMU is ok with the options but the
> actual test start shows that it's not, resulting in a FAIL.
I see, thanks, that is a bug.
Dropping the -kernel option in the check seems nicer than providing a
minimal working kernel ... I'll see how much refactoring is needed.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH kvm-unit-tests 0/5] add test for hyperv connections
2017-06-06 19:19 [PATCH kvm-unit-tests 0/5] add test for hyperv connections Roman Kagan
` (4 preceding siblings ...)
2017-06-06 19:19 ` [PATCH kvm-unit-tests 5/5] add hyperv_connections test Roman Kagan
@ 2017-06-14 18:58 ` Radim Krčmář
5 siblings, 0 replies; 14+ messages in thread
From: Radim Krčmář @ 2017-06-14 18:58 UTC (permalink / raw)
To: Roman Kagan; +Cc: kvm, Paolo Bonzini, Evgeny Yakovlev, Denis V . Lunev
2017-06-06 22:19+0300, Roman Kagan:
> A patchset adding support for Hyper-V message and event connections has
> been posted on qemu-devel. It also contained extensions for
> hyperv_testdev to support testing those features.
>
> This series makes use of this support and adds a test for them.
>
> Roman Kagan (5):
> hyperv: move test dev control codes to C file
> hyperv: don't take vcpu where inappropriate
> hyperv: add more test control codes
> hyperv: add more hyperv definitions
I have applied the first four patches, thanks.
> add hyperv_connections test
And another kvm-unit-tests series allows two improvements for v2 of
[5/5]: You can add "group = hyperv" to the test in x86/unittests.cfg and
use on_cpus() instead of open coded run-on-all-cpus-and-wait sequence.
^ permalink raw reply [flat|nested] 14+ messages in thread