All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches
@ 2024-03-06 17:18 Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 01/13] x86: hyperv: Use correct macro in checking SynIC timer support Vitaly Kuznetsov
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

A number of Hyper-V related patches were sent in the past but never made it
to kvm-unit-tests tree. As there are code dependencies between them, I've
decided to put them all in a combined series. Besides various fixes, the
series adds support for !CONFIG_KVM_HYPERV and direct mode synthetic timers.

Metin Kaya (4):
  x86: hyperv: Use correct macro in checking SynIC timer support
  x86: hyperv: improve naming of stimer functions
  x86: hyperv_clock: handle non-consecutive APIC IDs
  x86: hyperv_clock: print sequence field of reference TSC page

Vitaly Kuznetsov (9):
  x86: hyper-v: Use '-cpu host,hv_passhtrough' for Hyper-V tests
  x86: hyper-v: Use report_skip() in hyperv_stimer when pre-requisites
    are not met
  x86: hyper-v:  Use 'goto' instead of putting the whole test in an 'if'
    branch in hyperv_synic
  x86: hyper-v: Unify hyperv_clock with other Hyper-V tests
  x86: hyperv_stimer: keep SINT number parameter in 'struct stimer'
  x86: hyperv_stimer: define union hv_stimer_config
  x86: hyperv_stimer: don't require hyperv-testdev
  x86: hyperv_stimer: add direct mode tests
  x86: hyperv-v: Rewrite flaky hv_clock_test()

 x86/hyperv.h             |  35 ++++++--
 x86/hyperv_clock.c       |  87 +++++++++++--------
 x86/hyperv_connections.c |   2 +-
 x86/hyperv_stimer.c      | 176 ++++++++++++++++++++++++++++++---------
 x86/hyperv_synic.c       |  61 +++++++-------
 x86/unittests.cfg        |  14 +++-
 6 files changed, 259 insertions(+), 116 deletions(-)

-- 
2.44.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 01/13] x86: hyperv: Use correct macro in checking SynIC timer support
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 02/13] x86: hyperv: improve naming of stimer functions Vitaly Kuznetsov
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

From: Metin Kaya <metikaya@amazon.com>

This commit fixes 69d4bf751641520f5b2d8e3f160c63c8966fcd8b.
stimer_supported() should use HV_X64_MSR_SYNTIMER_AVAILABLE instead of
HV_X64_MSR_SYNIC_AVAILABLE.

Fixes: 69d4bf7 ("x86: Hyper-V SynIC timers test")
Signed-off-by: Metin Kaya <metikaya@amazon.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/x86/hyperv.h b/x86/hyperv.h
index e3803e02f4dc..bc165c344a11 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -190,7 +190,7 @@ static inline bool synic_supported(void)
 
 static inline bool stimer_supported(void)
 {
-    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
+    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
 }
 
 static inline bool hv_time_ref_counter_supported(void)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 02/13] x86: hyperv: improve naming of stimer functions
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 01/13] x86: hyperv: Use correct macro in checking SynIC timer support Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 03/13] x86: hyperv_clock: handle non-consecutive APIC IDs Vitaly Kuznetsov
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

From: Metin Kaya <metikaya@amazon.com>

- synic_supported() is renamed to hv_synic_supported().
- stimer_supported() is renamed to hv_stimer_supported().

Signed-off-by: Metin Kaya <metikaya@amazon.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv.h             | 4 ++--
 x86/hyperv_connections.c | 2 +-
 x86/hyperv_stimer.c      | 4 ++--
 x86/hyperv_synic.c       | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/x86/hyperv.h b/x86/hyperv.h
index bc165c344a11..3e1723ee9609 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -183,12 +183,12 @@ struct hv_input_post_message {
 	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
 };
 
-static inline bool synic_supported(void)
+static inline bool hv_synic_supported(void)
 {
    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
 }
 
-static inline bool stimer_supported(void)
+static inline bool hv_stimer_supported(void)
 {
     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
 }
diff --git a/x86/hyperv_connections.c b/x86/hyperv_connections.c
index cf043664b329..2c6841553ee4 100644
--- a/x86/hyperv_connections.c
+++ b/x86/hyperv_connections.c
@@ -266,7 +266,7 @@ int main(int ac, char **av)
 {
 	int ncpus, ncpus_ok, i;
 
-	if (!synic_supported()) {
+	if (!hv_synic_supported()) {
 		report_skip("Hyper-V SynIC is not supported");
 		goto summary;
 	}
diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index f7c679160bdf..2344eaf56f11 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -352,12 +352,12 @@ static void stimer_test_all(void)
 int main(int ac, char **av)
 {
 
-    if (!synic_supported()) {
+    if (!hv_synic_supported()) {
         report_pass("Hyper-V SynIC is not supported");
         goto done;
     }
 
-    if (!stimer_supported()) {
+    if (!hv_stimer_supported()) {
         report_pass("Hyper-V SynIC timers are not supported");
         goto done;
     }
diff --git a/x86/hyperv_synic.c b/x86/hyperv_synic.c
index 9d61d8362ebd..00655db10131 100644
--- a/x86/hyperv_synic.c
+++ b/x86/hyperv_synic.c
@@ -142,7 +142,7 @@ static void synic_test_cleanup(void *ctx)
 int main(int ac, char **av)
 {
 
-    if (synic_supported()) {
+    if (hv_synic_supported()) {
         int ncpus, i;
         bool ok;
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 03/13] x86: hyperv_clock: handle non-consecutive APIC IDs
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 01/13] x86: hyperv: Use correct macro in checking SynIC timer support Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 02/13] x86: hyperv: improve naming of stimer functions Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 04/13] x86: hyperv_clock: print sequence field of reference TSC page Vitaly Kuznetsov
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

From: Metin Kaya <metikaya@amazon.com>

smp_id() should not be used if APIC IDs are not allocated consecutively.
Fix it by using on_cpu_async() with CPU ID parameter.

Fixes: 907ce0f78c94 ("KVM: x86: add hyperv clock test case")
Signed-off-by: Metin Kaya <metikaya@amazon.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_clock.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/x86/hyperv_clock.c b/x86/hyperv_clock.c
index f1e7204a8ea9..dcf101af6968 100644
--- a/x86/hyperv_clock.c
+++ b/x86/hyperv_clock.c
@@ -63,7 +63,7 @@ uint64_t loops[MAX_CPU];
 
 static void hv_clock_test(void *data)
 {
-	int i = smp_id();
+	int i = (long)data;
 	uint64_t t = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
 	uint64_t end = t + 3 * TICKS_PER_SEC;
 	uint64_t msr_sample = t + TICKS_PER_SEC;
@@ -80,7 +80,7 @@ static void hv_clock_test(void *data)
 		if (t < msr_sample) {
 			max_delta = delta > max_delta ? delta: max_delta;
 		} else if (delta < 0 || delta > max_delta * 3 / 2) {
-			printf("suspecting drift on CPU %d? delta = %d, acceptable [0, %d)\n", smp_id(),
+			printf("suspecting drift on CPU %d? delta = %d, acceptable [0, %d)\n", i,
 			       delta, max_delta);
 			ok[i] = false;
 			got_drift = true;
@@ -88,7 +88,7 @@ static void hv_clock_test(void *data)
 		}
 
 		if (now < t && !got_warp) {
-			printf("warp on CPU %d!\n", smp_id());
+			printf("warp on CPU %d!\n", i);
 			ok[i] = false;
 			got_warp = true;
 			break;
@@ -97,7 +97,7 @@ static void hv_clock_test(void *data)
 	} while(t < end);
 
 	if (!got_drift)
-		printf("delta on CPU %d was %d...%d\n", smp_id(), min_delta, max_delta);
+		printf("delta on CPU %d was %d...%d\n", i, min_delta, max_delta);
 	barrier();
 }
 
@@ -106,7 +106,11 @@ static void check_test(int ncpus)
 	int i;
 	bool pass;
 
-	on_cpus(hv_clock_test, NULL);
+	for (i = ncpus - 1; i >= 0; i--)
+		on_cpu_async(i, hv_clock_test, (void *)(long)i);
+
+	while (cpus_active() > 1)
+		pause();
 
 	pass = true;
 	for (i = ncpus - 1; i >= 0; i--)
@@ -117,6 +121,7 @@ static void check_test(int ncpus)
 
 static void hv_perf_test(void *data)
 {
+	int i = (long)data;
 	uint64_t t = hv_clock_read();
 	uint64_t end = t + 1000000000 / 100;
 	uint64_t local_loops = 0;
@@ -126,7 +131,7 @@ static void hv_perf_test(void *data)
 		local_loops++;
 	} while(t < end);
 
-	loops[smp_id()] = local_loops;
+	loops[i] = local_loops;
 }
 
 static void perf_test(int ncpus)
@@ -134,7 +139,11 @@ static void perf_test(int ncpus)
 	int i;
 	uint64_t total_loops;
 
-	on_cpus(hv_perf_test, NULL);
+	for (i = ncpus - 1; i >= 0; i--)
+		on_cpu_async(i, hv_perf_test, (void *)(long)i);
+
+	while (cpus_active() > 1)
+		pause();
 
 	total_loops = 0;
 	for (i = ncpus - 1; i >= 0; i--)
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 04/13] x86: hyperv_clock: print sequence field of reference TSC page
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (2 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 03/13] x86: hyperv_clock: handle non-consecutive APIC IDs Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 05/13] x86: hyper-v: Use '-cpu host,hv_passhtrough' for Hyper-V tests Vitaly Kuznetsov
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

From: Metin Kaya <metikaya@amazon.com>

Having TscSequence in the log message for completeness.

Signed-off-by: Metin Kaya <metikaya@amazon.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_clock.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/x86/hyperv_clock.c b/x86/hyperv_clock.c
index dcf101af6968..9c30fbebf249 100644
--- a/x86/hyperv_clock.c
+++ b/x86/hyperv_clock.c
@@ -181,7 +181,8 @@ int main(int ac, char **av)
 		exit(1);
 	}
 
-	printf("scale: %" PRIx64" offset: %" PRId64"\n", shadow.tsc_scale, shadow.tsc_offset);
+	printf("sequence: %u. scale: %" PRIx64" offset: %" PRId64"\n",
+	       shadow.tsc_sequence, shadow.tsc_scale, shadow.tsc_offset);
 	ref1 = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
 	tsc1 = rdtsc();
 	t1 = hvclock_tsc_to_ticks(&shadow, tsc1);
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 05/13] x86: hyper-v: Use '-cpu host,hv_passhtrough' for Hyper-V tests
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (3 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 04/13] x86: hyperv_clock: print sequence field of reference TSC page Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 06/13] x86: hyper-v: Use report_skip() in hyperv_stimer when pre-requisites are not met Vitaly Kuznetsov
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

To make Hyper-V tests skip gracefully when Hyper-V emulation support is
missing in KVM run all tests with '-cpu host,hv_passhtrough' which is
supposed to enable all enlightenments. Tests can (and will) check CPUID
and report_skip() when the required features are missing.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/unittests.cfg | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 3fe59449b650..a5574b105efc 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -451,25 +451,25 @@ arch = x86_64
 [hyperv_synic]
 file = hyperv_synic.flat
 smp = 2
-extra_params = -cpu kvm64,hv_vpindex,hv_synic -device hyperv-testdev
+extra_params = -cpu host,hv_passthrough -device hyperv-testdev
 groups = hyperv
 
 [hyperv_connections]
 file = hyperv_connections.flat
 smp = 2
-extra_params = -cpu kvm64,hv_vpindex,hv_synic -device hyperv-testdev
+extra_params = -cpu host,hv_passthrough -device hyperv-testdev
 groups = hyperv
 
 [hyperv_stimer]
 file = hyperv_stimer.flat
 smp = 2
-extra_params = -cpu kvm64,hv_vpindex,hv_time,hv_synic,hv_stimer -device hyperv-testdev
+extra_params = -cpu host,hv_passthrough -device hyperv-testdev
 groups = hyperv
 
 [hyperv_clock]
 file = hyperv_clock.flat
 smp = 2
-extra_params = -cpu kvm64,hv_time
+extra_params = -cpu host,hv_passthrough
 arch = x86_64
 groups = hyperv
 check = /sys/devices/system/clocksource/clocksource0/current_clocksource=tsc
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 06/13] x86: hyper-v: Use report_skip() in hyperv_stimer when pre-requisites are not met
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (4 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 05/13] x86: hyper-v: Use '-cpu host,hv_passhtrough' for Hyper-V tests Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 07/13] x86: hyper-v: Use 'goto' instead of putting the whole test in an 'if' branch in hyperv_synic Vitaly Kuznetsov
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

'report_pass()' is supposed to be used when tests actually pass, use
'report_skip()' to match other tests.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_stimer.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index 2344eaf56f11..9259e28c6a90 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -353,17 +353,17 @@ int main(int ac, char **av)
 {
 
     if (!hv_synic_supported()) {
-        report_pass("Hyper-V SynIC is not supported");
+        report_skip("Hyper-V SynIC is not supported");
         goto done;
     }
 
     if (!hv_stimer_supported()) {
-        report_pass("Hyper-V SynIC timers are not supported");
+        report_skip("Hyper-V SynIC timers are not supported");
         goto done;
     }
 
     if (!hv_time_ref_counter_supported()) {
-        report_pass("Hyper-V time reference counter is not supported");
+        report_skip("Hyper-V time reference counter is not supported");
         goto done;
     }
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 07/13] x86: hyper-v:  Use 'goto' instead of putting the whole test in an 'if' branch in hyperv_synic
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (5 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 06/13] x86: hyper-v: Use report_skip() in hyperv_stimer when pre-requisites are not met Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 08/13] x86: hyper-v: Unify hyperv_clock with other Hyper-V tests Vitaly Kuznetsov
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

Unify 'hyperv_synic' test with other Hyper-V tests by using the:

 if (required-features-missing) {
    report_skip();
    goto done;
 }
 ...

 done:
     return report_summary();

pattern.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_synic.c | 61 +++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 30 deletions(-)

diff --git a/x86/hyperv_synic.c b/x86/hyperv_synic.c
index 00655db10131..761df8ac43c0 100644
--- a/x86/hyperv_synic.c
+++ b/x86/hyperv_synic.c
@@ -141,45 +141,46 @@ static void synic_test_cleanup(void *ctx)
 
 int main(int ac, char **av)
 {
+    int ncpus, i;
+    bool ok;
 
-    if (hv_synic_supported()) {
-        int ncpus, i;
-        bool ok;
-
-        setup_vm();
-        enable_apic();
+    if (!hv_synic_supported()) {
+	report_skip("Hyper-V SynIC is not supported");
+	goto done;
+    }
 
-        ncpus = cpu_count();
-        if (ncpus > MAX_CPUS)
-            report_abort("number cpus exceeds %d", MAX_CPUS);
-        printf("ncpus = %d\n", ncpus);
+    setup_vm();
+    enable_apic();
 
-        synic_prepare_sint_vecs();
+    ncpus = cpu_count();
+    if (ncpus > MAX_CPUS)
+	report_abort("number cpus exceeds %d", MAX_CPUS);
+    printf("ncpus = %d\n", ncpus);
 
-        printf("prepare\n");
-        on_cpus(synic_test_prepare, (void *)read_cr3());
+    synic_prepare_sint_vecs();
 
-        for (i = 0; i < ncpus; i++) {
-            printf("test %d -> %d\n", i, ncpus - 1 - i);
-            on_cpu_async(i, synic_test, (void *)(ulong)(ncpus - 1 - i));
-        }
-        while (cpus_active() > 1)
-            pause();
+    printf("prepare\n");
+    on_cpus(synic_test_prepare, (void *)read_cr3());
 
-        printf("cleanup\n");
-        on_cpus(synic_test_cleanup, NULL);
+    for (i = 0; i < ncpus; i++) {
+	printf("test %d -> %d\n", i, ncpus - 1 - i);
+	on_cpu_async(i, synic_test, (void *)(ulong)(ncpus - 1 - i));
+    }
+    while (cpus_active() > 1)
+	pause();
 
-        ok = true;
-        for (i = 0; i < ncpus; ++i) {
-            printf("isr_enter_count[%d] = %d\n",
-                   i, atomic_read(&isr_enter_count[i]));
-            ok &= atomic_read(&isr_enter_count[i]) == 16;
-        }
+    printf("cleanup\n");
+    on_cpus(synic_test_cleanup, NULL);
 
-        report(ok, "Hyper-V SynIC test");
-    } else {
-        printf("Hyper-V SynIC is not supported");
+    ok = true;
+    for (i = 0; i < ncpus; ++i) {
+	printf("isr_enter_count[%d] = %d\n",
+	       i, atomic_read(&isr_enter_count[i]));
+	ok &= atomic_read(&isr_enter_count[i]) == 16;
     }
 
+    report(ok, "Hyper-V SynIC test");
+
+done:
     return report_summary();
 }
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 08/13] x86: hyper-v: Unify hyperv_clock with other Hyper-V tests
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (6 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 07/13] x86: hyper-v: Use 'goto' instead of putting the whole test in an 'if' branch in hyperv_synic Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 09/13] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

Always do 'return report_summary()' at the end, use report_abort() when an
abnormality is detected.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_clock.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/x86/hyperv_clock.c b/x86/hyperv_clock.c
index 9c30fbebf249..d0993bb75ac7 100644
--- a/x86/hyperv_clock.c
+++ b/x86/hyperv_clock.c
@@ -153,7 +153,6 @@ static void perf_test(int ncpus)
 
 int main(int ac, char **av)
 {
-	int nerr = 0;
 	int ncpus;
 	struct hv_reference_tsc_page shadow;
 	uint64_t tsc1, t1, tsc2, t2;
@@ -161,7 +160,7 @@ int main(int ac, char **av)
 
 	if (!hv_time_ref_counter_supported()) {
 		report_skip("time reference counter is unsupported");
-		return report_summary();
+		goto done;
 	}
 
 	setup_vm();
@@ -176,10 +175,8 @@ int main(int ac, char **av)
 	       "MSR value after enabling");
 
 	hvclock_get_time_values(&shadow, hv_clock);
-	if (shadow.tsc_sequence == 0 || shadow.tsc_sequence == 0xFFFFFFFF) {
-		printf("Reference TSC page not available\n");
-		exit(1);
-	}
+	if (shadow.tsc_sequence == 0 || shadow.tsc_sequence == 0xFFFFFFFF)
+		report_abort("Reference TSC page not available\n");
 
 	printf("sequence: %u. scale: %" PRIx64" offset: %" PRId64"\n",
 	       shadow.tsc_sequence, shadow.tsc_scale, shadow.tsc_offset);
@@ -206,5 +203,6 @@ int main(int ac, char **av)
 	report(rdmsr(HV_X64_MSR_REFERENCE_TSC) == 0,
 	       "MSR value after disabling");
 
-	return nerr > 0 ? 1 : 0;
+done:
+	return report_summary();
 }
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 09/13] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer'
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (7 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 08/13] x86: hyper-v: Unify hyperv_clock with other Hyper-V tests Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 10/13] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

As a preparation to enabling direct synthetic timers support stop
passing SINT number to stimer_start.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_stimer.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index 9259e28c6a90..f4eb9f2bb158 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -161,11 +161,10 @@ static void stimer_isr_auto_eoi(isr_regs_t *regs)
 
 static void stimer_start(struct stimer *timer,
                          bool auto_enable, bool periodic,
-                         u64 tick_100ns, int sint)
+                         u64 tick_100ns)
 {
     u64 config, count;
 
-    timer->sint = sint;
     atomic_set(&timer->fire_count, 0);
 
     config = 0;
@@ -173,7 +172,7 @@ static void stimer_start(struct stimer *timer,
         config |= HV_STIMER_PERIODIC;
     }
 
-    config |= ((u8)(sint & 0xFF)) << 16;
+    config |= ((u8)(timer->sint & 0xFF)) << 16;
     config |= HV_STIMER_ENABLE;
     if (auto_enable) {
         config |= HV_STIMER_AUTOENABLE;
@@ -218,18 +217,29 @@ static void synic_disable(void)
 
 static void stimer_test_prepare(void *ctx)
 {
+    int vcpu = smp_id();
+    struct svcpu *svcpu = &g_synic_vcpu[vcpu];
+    struct stimer *timer1, *timer2;
+
     write_cr3((ulong)ctx);
     synic_enable();
+
     synic_sint_create(SINT1_NUM, SINT1_VEC, false);
     synic_sint_create(SINT2_NUM, SINT2_VEC, true);
+
+    timer1 = &svcpu->timer[0];
+    timer2 = &svcpu->timer[1];
+
+    timer1->sint = SINT1_NUM;
+    timer2->sint = SINT2_NUM;
 }
 
 static void stimer_test_periodic(int vcpu, struct stimer *timer1,
                                  struct stimer *timer2)
 {
     /* Check periodic timers */
-    stimer_start(timer1, false, true, ONE_MS_IN_100NS, SINT1_NUM);
-    stimer_start(timer2, false, true, ONE_MS_IN_100NS, SINT2_NUM);
+    stimer_start(timer1, false, true, ONE_MS_IN_100NS);
+    stimer_start(timer2, false, true, ONE_MS_IN_100NS);
     while ((atomic_read(&timer1->fire_count) < 1000) ||
            (atomic_read(&timer2->fire_count) < 1000)) {
         pause();
@@ -242,7 +252,7 @@ static void stimer_test_periodic(int vcpu, struct stimer *timer1,
 static void stimer_test_one_shot(int vcpu, struct stimer *timer)
 {
     /* Check one-shot timer */
-    stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM);
+    stimer_start(timer, false, false, ONE_MS_IN_100NS);
     while (atomic_read(&timer->fire_count) < 1) {
         pause();
     }
@@ -253,7 +263,7 @@ static void stimer_test_one_shot(int vcpu, struct stimer *timer)
 static void stimer_test_auto_enable_one_shot(int vcpu, struct stimer *timer)
 {
     /* Check auto-enable one-shot timer */
-    stimer_start(timer, true, false, ONE_MS_IN_100NS, SINT1_NUM);
+    stimer_start(timer, true, false, ONE_MS_IN_100NS);
     while (atomic_read(&timer->fire_count) < 1) {
         pause();
     }
@@ -264,7 +274,7 @@ static void stimer_test_auto_enable_one_shot(int vcpu, struct stimer *timer)
 static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer)
 {
     /* Check auto-enable periodic timer */
-    stimer_start(timer, true, true, ONE_MS_IN_100NS, SINT1_NUM);
+    stimer_start(timer, true, true, ONE_MS_IN_100NS);
     while (atomic_read(&timer->fire_count) < 1000) {
         pause();
     }
@@ -280,7 +290,7 @@ static void stimer_test_one_shot_busy(int vcpu, struct stimer *timer)
     msg->header.message_type = HVMSG_TIMER_EXPIRED;
     wmb();
 
-    stimer_start(timer, false, false, ONE_MS_IN_100NS, SINT1_NUM);
+    stimer_start(timer, false, false, ONE_MS_IN_100NS);
 
     do
         rmb();
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 10/13] x86: hyperv_stimer: define union hv_stimer_config
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (8 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 09/13] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 11/13] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

As a preparation to enabling direct synthetic timers properly define
hv_stimer_config.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv.h        | 22 +++++++++++++++++-----
 x86/hyperv_stimer.c | 21 ++++++++-------------
 2 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/x86/hyperv.h b/x86/hyperv.h
index 3e1723ee9609..2fc70e561ef2 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -60,11 +60,23 @@
 #define HV_SYNIC_SINT_VECTOR_MASK               (0xFF)
 #define HV_SYNIC_SINT_COUNT                     16
 
-#define HV_STIMER_ENABLE                (1ULL << 0)
-#define HV_STIMER_PERIODIC              (1ULL << 1)
-#define HV_STIMER_LAZY                  (1ULL << 2)
-#define HV_STIMER_AUTOENABLE            (1ULL << 3)
-#define HV_STIMER_SINT(config)          (__u8)(((config) >> 16) & 0x0F)
+/*
+ * Synthetic timer configuration.
+ */
+union hv_stimer_config {
+	u64 as_uint64;
+	struct {
+		u64 enable:1;
+		u64 periodic:1;
+		u64 lazy:1;
+		u64 auto_enable:1;
+		u64 apic_vector:8;
+		u64 direct_mode:1;
+		u64 reserved_z0:3;
+		u64 sintx:4;
+		u64 reserved_z1:44;
+	};
+};
 
 #define HV_SYNIC_STIMER_COUNT           (4)
 
diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index f4eb9f2bb158..0b9ec7a5b1b4 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -163,20 +163,15 @@ static void stimer_start(struct stimer *timer,
                          bool auto_enable, bool periodic,
                          u64 tick_100ns)
 {
-    u64 config, count;
+    u64 count;
+    union hv_stimer_config config = {.as_uint64 = 0};
 
     atomic_set(&timer->fire_count, 0);
 
-    config = 0;
-    if (periodic) {
-        config |= HV_STIMER_PERIODIC;
-    }
-
-    config |= ((u8)(timer->sint & 0xFF)) << 16;
-    config |= HV_STIMER_ENABLE;
-    if (auto_enable) {
-        config |= HV_STIMER_AUTOENABLE;
-    }
+    config.periodic = periodic;
+    config.enable = 1;
+    config.auto_enable = auto_enable;
+    config.sintx = timer->sint;
 
     if (periodic) {
         count = tick_100ns;
@@ -186,9 +181,9 @@ static void stimer_start(struct stimer *timer,
 
     if (!auto_enable) {
         wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count);
-        wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config);
+        wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config.as_uint64);
     } else {
-        wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config);
+        wrmsr(HV_X64_MSR_STIMER0_CONFIG + timer->index*2, config.as_uint64);
         wrmsr(HV_X64_MSR_STIMER0_COUNT + timer->index*2, count);
     }
 }
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 11/13] x86: hyperv_stimer: don't require hyperv-testdev
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (9 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 10/13] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 12/13] x86: hyperv_stimer: add direct mode tests Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 13/13] x86: hyperv-v: Rewrite flaky hv_clock_test() Vitaly Kuznetsov
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

'hyperv-testdev' is completely superfluous for stimer tests.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/unittests.cfg | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index a5574b105efc..06164ae22aa7 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -463,7 +463,7 @@ groups = hyperv
 [hyperv_stimer]
 file = hyperv_stimer.flat
 smp = 2
-extra_params = -cpu host,hv_passthrough -device hyperv-testdev
+extra_params = -cpu host,hv_passthrough
 groups = hyperv
 
 [hyperv_clock]
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 12/13] x86: hyperv_stimer: add direct mode tests
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (10 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 11/13] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 13/13] x86: hyperv-v: Rewrite flaky hv_clock_test() Vitaly Kuznetsov
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

All tests but stimer_test_one_shot_busy() are applicable, make them run in
both 'message' and 'direct' modes.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv.h        |   7 +++
 x86/hyperv_stimer.c | 123 ++++++++++++++++++++++++++++++++++++++------
 x86/unittests.cfg   |   6 +++
 3 files changed, 121 insertions(+), 15 deletions(-)

diff --git a/x86/hyperv.h b/x86/hyperv.h
index 2fc70e561ef2..a1443842ed0b 100644
--- a/x86/hyperv.h
+++ b/x86/hyperv.h
@@ -10,6 +10,8 @@
 #define HV_X64_MSR_SYNIC_AVAILABLE              (1 << 2)
 #define HV_X64_MSR_SYNTIMER_AVAILABLE           (1 << 3)
 
+#define HV_STIMER_DIRECT_MODE_AVAILABLE		(1 << 19)
+
 #define HV_X64_MSR_GUEST_OS_ID                  0x40000000
 #define HV_X64_MSR_HYPERCALL                    0x40000001
 
@@ -205,6 +207,11 @@ static inline bool hv_stimer_supported(void)
     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
 }
 
+static inline bool stimer_direct_supported(void)
+{
+    return cpuid(HYPERV_CPUID_FEATURES).d & HV_STIMER_DIRECT_MODE_AVAILABLE;
+}
+
 static inline bool hv_time_ref_counter_supported(void)
 {
     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index 0b9ec7a5b1b4..e50903b24820 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -16,6 +16,9 @@
 #define SINT1_VEC 0xF1
 #define SINT2_VEC 0xF2
 
+#define APIC_VEC1 0xF3
+#define APIC_VEC2 0xF4
+
 #define SINT1_NUM 2
 #define SINT2_NUM 3
 #define ONE_MS_IN_100NS 10000
@@ -25,6 +28,8 @@ static struct spinlock g_synic_alloc_lock;
 struct stimer {
     int sint;
     int index;
+    bool direct;
+    int apic_vec;
     atomic_t fire_count;
 };
 
@@ -81,8 +86,7 @@ static void stimer_shutdown(struct stimer *timer)
     wrmsr(HV_X64_MSR_STIMER0_CONFIG + 2*timer->index, 0);
 }
 
-static void process_stimer_expired(struct svcpu *svcpu, struct stimer *timer,
-                                   u64 expiration_time, u64 delivery_time)
+static void process_stimer_expired(struct stimer *timer)
 {
     atomic_inc(&timer->fire_count);
 }
@@ -119,8 +123,14 @@ static void process_stimer_msg(struct svcpu *svcpu,
         abort();
     }
     timer = &svcpu->timer[payload->timer_index];
-    process_stimer_expired(svcpu, timer, payload->expiration_time,
-                          payload->delivery_time);
+
+    if (timer->direct) {
+        report(false, "VMBus message in direct mode received");
+        report_summary();
+        abort();
+    }
+
+    process_stimer_expired(timer);
 
     msg->header.message_type = HVMSG_NONE;
     mb();
@@ -159,6 +169,32 @@ static void stimer_isr_auto_eoi(isr_regs_t *regs)
     __stimer_isr(vcpu);
 }
 
+static void __stimer_isr_direct(int vcpu, int timer_index)
+{
+    struct svcpu *svcpu = &g_synic_vcpu[vcpu];
+    struct stimer *timer = &svcpu->timer[timer_index];
+
+    process_stimer_expired(timer);
+}
+
+static void stimer_isr_direct1(isr_regs_t *regs)
+{
+    int vcpu = smp_id();
+
+    __stimer_isr_direct(vcpu, 0);
+
+    eoi();
+}
+
+static void stimer_isr_direct2(isr_regs_t *regs)
+{
+    int vcpu = smp_id();
+
+    __stimer_isr_direct(vcpu, 1);
+
+    eoi();
+}
+
 static void stimer_start(struct stimer *timer,
                          bool auto_enable, bool periodic,
                          u64 tick_100ns)
@@ -171,7 +207,12 @@ static void stimer_start(struct stimer *timer,
     config.periodic = periodic;
     config.enable = 1;
     config.auto_enable = auto_enable;
-    config.sintx = timer->sint;
+    if (!timer->direct) {
+        config.sintx = timer->sint;
+    } else {
+        config.direct_mode = 1;
+        config.apic_vector = timer->apic_vec;
+    }
 
     if (periodic) {
         count = tick_100ns;
@@ -229,6 +270,28 @@ static void stimer_test_prepare(void *ctx)
     timer2->sint = SINT2_NUM;
 }
 
+static void stimer_test_prepare_direct(void *ctx)
+{
+    int vcpu = smp_id();
+    struct svcpu *svcpu = &g_synic_vcpu[vcpu];
+    struct stimer *timer1, *timer2;
+
+    write_cr3((ulong)ctx);
+
+    timer1 = &svcpu->timer[0];
+    timer2 = &svcpu->timer[1];
+
+    stimer_init(timer1, 0);
+    stimer_init(timer2, 1);
+
+    timer1->apic_vec = APIC_VEC1;
+    timer2->apic_vec = APIC_VEC2;
+
+    timer1->direct = true;
+    timer2->direct = true;
+}
+
+
 static void stimer_test_periodic(int vcpu, struct stimer *timer1,
                                  struct stimer *timer2)
 {
@@ -279,8 +342,15 @@ static void stimer_test_auto_enable_periodic(int vcpu, struct stimer *timer)
 
 static void stimer_test_one_shot_busy(int vcpu, struct stimer *timer)
 {
-    struct hv_message_page *msg_page = g_synic_vcpu[vcpu].msg_page;
-    struct hv_message *msg = &msg_page->sint_message[timer->sint];
+    struct hv_message_page *msg_page;
+    struct hv_message *msg;
+
+    /* Skipping msg slot busy test in direct mode */
+    if (timer->direct)
+        return;
+
+    msg_page = g_synic_vcpu[vcpu].msg_page;
+    msg = &msg_page->sint_message[timer->sint];
 
     msg->header.message_type = HVMSG_TIMER_EXPIRED;
     wmb();
@@ -334,7 +404,12 @@ static void stimer_test_cleanup(void *ctx)
     synic_disable();
 }
 
-static void stimer_test_all(void)
+static void stimer_test_cleanup_direct(void *ctx)
+{
+    stimers_shutdown();
+}
+
+static void stimer_test_all(bool direct)
 {
     int ncpus;
 
@@ -346,16 +421,30 @@ static void stimer_test_all(void)
         report_abort("number cpus exceeds %d", MAX_CPUS);
     printf("cpus = %d\n", ncpus);
 
-    handle_irq(SINT1_VEC, stimer_isr);
-    handle_irq(SINT2_VEC, stimer_isr_auto_eoi);
+    if (!direct) {
+        printf("Starting Hyper-V SynIC timers tests: message mode\n");
 
-    on_cpus(stimer_test_prepare, (void *)read_cr3());
-    on_cpus(stimer_test, NULL);
-    on_cpus(stimer_test_cleanup, NULL);
+        handle_irq(SINT1_VEC, stimer_isr);
+        handle_irq(SINT2_VEC, stimer_isr_auto_eoi);
+
+	on_cpus(stimer_test_prepare, (void *)read_cr3());
+	on_cpus(stimer_test, NULL);
+	on_cpus(stimer_test_cleanup, NULL);
+    } else {
+        printf("Starting Hyper-V SynIC timers tests: direct mode\n");
+
+        handle_irq(APIC_VEC1, stimer_isr_direct1);
+        handle_irq(APIC_VEC2, stimer_isr_direct2);
+
+        on_cpus(stimer_test_prepare_direct, (void *)read_cr3());
+        on_cpus(stimer_test, NULL);
+        on_cpus(stimer_test_cleanup_direct, NULL);
+    }
 }
 
-int main(int ac, char **av)
+int main(int argc, char **argv)
 {
+    bool direct = argc >= 2 && !strcmp(argv[1], "direct");
 
     if (!hv_synic_supported()) {
         report_skip("Hyper-V SynIC is not supported");
@@ -372,7 +461,11 @@ int main(int ac, char **av)
         goto done;
     }
 
-    stimer_test_all();
+    if (direct && !stimer_direct_supported()) {
+	report_skip("Hyper-V SinIC timer direct mode is not supported");
+    }
+
+    stimer_test_all(direct);
 done:
     return report_summary();
 }
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 06164ae22aa7..124be7a1f208 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -466,6 +466,12 @@ smp = 2
 extra_params = -cpu host,hv_passthrough
 groups = hyperv
 
+[hyperv_stimer_direct]
+file = hyperv_stimer.flat
+smp = 2
+extra_params = -cpu host,hv_passthrough -append direct
+groups = hyperv
+
 [hyperv_clock]
 file = hyperv_clock.flat
 smp = 2
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH kvm-unit-tests 13/13] x86: hyperv-v: Rewrite flaky hv_clock_test()
  2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
                   ` (11 preceding siblings ...)
  2024-03-06 17:18 ` [PATCH kvm-unit-tests 12/13] x86: hyperv_stimer: add direct mode tests Vitaly Kuznetsov
@ 2024-03-06 17:18 ` Vitaly Kuznetsov
  12 siblings, 0 replies; 14+ messages in thread
From: Vitaly Kuznetsov @ 2024-03-06 17:18 UTC (permalink / raw
  To: kvm, Paolo Bonzini; +Cc: Metin Kaya

hv_clock_test() is reported to be flaky:
https://bugzilla.kernel.org/show_bug.cgi?id=217516

The test tries measuring the divergence between MSR based clock and TSC
page over one second and then expects delta to stay within the measured
range over another two seconds. This works well for a completely idle
system but if tasks get scheduled out, rescheduled to a different CPU,...
the test fails. Widening the expected range helps to certain extent but
even when the expected delta is "max_delta * 1024" sporadic failures still
occur.

Rewrite the test completely to make it stable. Check two things:
- MSR based and TSC page clocksources never go backwards.
- MSR based clocksource read between to TSC page reads stays within the
interval.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 x86/hyperv_clock.c | 55 +++++++++++++++++++++++++++-------------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/x86/hyperv_clock.c b/x86/hyperv_clock.c
index d0993bb75ac7..9061da8c6d2c 100644
--- a/x86/hyperv_clock.c
+++ b/x86/hyperv_clock.c
@@ -64,40 +64,51 @@ uint64_t loops[MAX_CPU];
 static void hv_clock_test(void *data)
 {
 	int i = (long)data;
-	uint64_t t = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
-	uint64_t end = t + 3 * TICKS_PER_SEC;
-	uint64_t msr_sample = t + TICKS_PER_SEC;
-	int min_delta = 123456, max_delta = -123456;
+	uint64_t t_msr_prev = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
+	uint64_t t_page_prev = hv_clock_read();
+	uint64_t end = t_page_prev + TICKS_PER_SEC;
 	bool got_drift = false;
-	bool got_warp = false;
+	bool got_warp_msr = false;
+	bool got_warp_page = false;
 
 	ok[i] = true;
 	do {
-		uint64_t now = hv_clock_read();
-		int delta = rdmsr(HV_X64_MSR_TIME_REF_COUNT) - now;
-
-		min_delta = delta < min_delta ? delta : min_delta;
-		if (t < msr_sample) {
-			max_delta = delta > max_delta ? delta: max_delta;
-		} else if (delta < 0 || delta > max_delta * 3 / 2) {
-			printf("suspecting drift on CPU %d? delta = %d, acceptable [0, %d)\n", i,
-			       delta, max_delta);
+		uint64_t t_page_1, t_page_2, t_msr;
+
+		t_page_1 = hv_clock_read();
+		barrier();
+		t_msr = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
+		barrier();
+		t_page_2 = hv_clock_read();
+
+		if (!got_drift && (t_msr < t_page_1 || t_msr > t_page_2)) {
+			printf("drift on CPU %d, MSR value = %ld, acceptable [%ld, %ld]\n", i,
+			       t_msr, t_page_1, t_page_2);
 			ok[i] = false;
 			got_drift = true;
-			max_delta *= 2;
 		}
 
-		if (now < t && !got_warp) {
-			printf("warp on CPU %d!\n", i);
+		if (!got_warp_msr && t_msr < t_msr_prev) {
+			printf("warp on CPU %d, MSR value = %ld prev MSR value = %ld!\n", i,
+			       t_msr, t_msr_prev);
 			ok[i] = false;
-			got_warp = true;
+			got_warp_msr = true;
 			break;
 		}
-		t = now;
-	} while(t < end);
 
-	if (!got_drift)
-		printf("delta on CPU %d was %d...%d\n", i, min_delta, max_delta);
+		if (!got_warp_page && t_page_1 < t_page_prev) {
+			printf("warp on CPU %d, TSC page value = %ld prev TSC page value = %ld!\n", i,
+			       t_page_1, t_page_prev);
+			ok[i] = false;
+			got_warp_page = true;
+			break;
+		}
+
+		t_page_prev = t_page_1;
+		t_msr_prev = t_msr;
+
+	} while(t_page_prev < end);
+
 	barrier();
 }
 
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-03-06 17:19 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-06 17:18 [PATCH kvm-unit-tests 00/13] x86: hyperv-v: Various unmerged patches Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 01/13] x86: hyperv: Use correct macro in checking SynIC timer support Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 02/13] x86: hyperv: improve naming of stimer functions Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 03/13] x86: hyperv_clock: handle non-consecutive APIC IDs Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 04/13] x86: hyperv_clock: print sequence field of reference TSC page Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 05/13] x86: hyper-v: Use '-cpu host,hv_passhtrough' for Hyper-V tests Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 06/13] x86: hyper-v: Use report_skip() in hyperv_stimer when pre-requisites are not met Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 07/13] x86: hyper-v: Use 'goto' instead of putting the whole test in an 'if' branch in hyperv_synic Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 08/13] x86: hyper-v: Unify hyperv_clock with other Hyper-V tests Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 09/13] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 10/13] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 11/13] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 12/13] x86: hyperv_stimer: add direct mode tests Vitaly Kuznetsov
2024-03-06 17:18 ` [PATCH kvm-unit-tests 13/13] x86: hyperv-v: Rewrite flaky hv_clock_test() Vitaly Kuznetsov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.