All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode
@ 2019-10-22 15:56 Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 1/4] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Vitaly Kuznetsov @ 2019-10-22 15:56 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Roman Kagan

I should've done that when QEMU patche for 'hv_stimer_direct' landed but
better late than never, right?

Testing 'direct' mode requires us to add 'hv_stimer_direct' CPU flag to
QEMU, create a new entry in unittests.cfg to not lose the ability to test
stimers in 'message' mode with older QEMUs/kernels. Unfortunately, a
failure with './run_tests' will still be visible.

Vitaly Kuznetsov (4):
  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.h        |  29 +++++++--
 x86/hyperv_stimer.c | 152 ++++++++++++++++++++++++++++++++++----------
 x86/unittests.cfg   |   8 ++-
 3 files changed, 150 insertions(+), 39 deletions(-)

-- 
2.20.1


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

* [PATCH kvm-unit-tests 1/4] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer'
  2019-10-22 15:56 [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode Vitaly Kuznetsov
@ 2019-10-22 15:56 ` Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 2/4] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Vitaly Kuznetsov @ 2019-10-22 15:56 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Roman Kagan

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 b6332fd57bbd..3b452749c2b3 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.20.1


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

* [PATCH kvm-unit-tests 2/4] x86: hyperv_stimer: define union hv_stimer_config
  2019-10-22 15:56 [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 1/4] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
@ 2019-10-22 15:56 ` Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 3/4] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 4/4] x86: hyperv_stimer: add direct mode tests Vitaly Kuznetsov
  3 siblings, 0 replies; 5+ messages in thread
From: Vitaly Kuznetsov @ 2019-10-22 15:56 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Roman Kagan

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 e135221fa28a..9a83da483467 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 3b452749c2b3..6f72205d97c0 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.20.1


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

* [PATCH kvm-unit-tests 3/4] x86: hyperv_stimer: don't require hyperv-testdev
  2019-10-22 15:56 [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 1/4] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 2/4] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
@ 2019-10-22 15:56 ` Vitaly Kuznetsov
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 4/4] x86: hyperv_stimer: add direct mode tests Vitaly Kuznetsov
  3 siblings, 0 replies; 5+ messages in thread
From: Vitaly Kuznetsov @ 2019-10-22 15:56 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Roman Kagan

'hyperv-testdev' is redundant 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 5ecb9bba535b..5c0c55a0f405 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -303,7 +303,7 @@ 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 kvm64,hv_vpindex,hv_time,hv_synic,hv_stimer
 groups = hyperv
 
 [hyperv_clock]
-- 
2.20.1


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

* [PATCH kvm-unit-tests 4/4] x86: hyperv_stimer: add direct mode tests
  2019-10-22 15:56 [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode Vitaly Kuznetsov
                   ` (2 preceding siblings ...)
  2019-10-22 15:56 ` [PATCH kvm-unit-tests 3/4] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
@ 2019-10-22 15:56 ` Vitaly Kuznetsov
  3 siblings, 0 replies; 5+ messages in thread
From: Vitaly Kuznetsov @ 2019-10-22 15:56 UTC (permalink / raw)
  To: kvm; +Cc: Paolo Bonzini, Roman Kagan

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 | 109 ++++++++++++++++++++++++++++++++++++++------
 x86/unittests.cfg   |   6 +++
 3 files changed, 108 insertions(+), 14 deletions(-)

diff --git a/x86/hyperv.h b/x86/hyperv.h
index 9a83da483467..718744c4d179 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 stimer_supported(void)
     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_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 6f72205d97c0..3e6a4a04d9df 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,7 @@ 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);
+    process_stimer_expired(timer);
 
     msg->header.message_type = HVMSG_NONE;
     mb();
@@ -159,6 +162,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 +200,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 +263,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 +335,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 +397,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;
 
@@ -347,12 +415,25 @@ 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");
+
+        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, (void *)read_cr3());
-    on_cpus(stimer_test, NULL);
-    on_cpus(stimer_test_cleanup, NULL);
+        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)
@@ -373,7 +454,7 @@ int main(int ac, char **av)
         goto done;
     }
 
-    stimer_test_all();
+    stimer_test_all(stimer_direct_supported());
 done:
     return report_summary();
 }
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 5c0c55a0f405..933fed1c2038 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -306,6 +306,12 @@ smp = 2
 extra_params = -cpu kvm64,hv_vpindex,hv_time,hv_synic,hv_stimer
 groups = hyperv
 
+[hyperv_stimer_direct]
+file = hyperv_stimer.flat
+smp = 2
+extra_params = -cpu kvm64,hv_vpindex,hv_time,hv_synic,hv_stimer,hv_stimer_direct
+groups = hyperv
+
 [hyperv_clock]
 file = hyperv_clock.flat
 smp = 2
-- 
2.20.1


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

end of thread, other threads:[~2019-10-22 15:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-22 15:56 [PATCH kvm-unit-tests 0/4] x86: hyperv_stimer: test direct mode Vitaly Kuznetsov
2019-10-22 15:56 ` [PATCH kvm-unit-tests 1/4] x86: hyperv_stimer: keep SINT number parameter in 'struct stimer' Vitaly Kuznetsov
2019-10-22 15:56 ` [PATCH kvm-unit-tests 2/4] x86: hyperv_stimer: define union hv_stimer_config Vitaly Kuznetsov
2019-10-22 15:56 ` [PATCH kvm-unit-tests 3/4] x86: hyperv_stimer: don't require hyperv-testdev Vitaly Kuznetsov
2019-10-22 15:56 ` [PATCH kvm-unit-tests 4/4] x86: hyperv_stimer: add direct mode tests 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.