All of lore.kernel.org
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com
Subject: [kvm-unit-tests PATCH 1/2] x86/apic: separate reporting from actual measurements
Date: Tue, 28 Apr 2026 15:35:23 +0200	[thread overview]
Message-ID: <20260428133524.3628482-2-imammedo@redhat.com> (raw)
In-Reply-To: <20260428133524.3628482-1-imammedo@redhat.com>

Move report() calls to the end of the function so that serial I/O
does not interfere with timer measurements.

While at it, wrap the test body in a for loop as preparation
for adding retry logic to deal with failures due to large
enough vCPU stalls.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 x86/apic.c | 109 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 63 insertions(+), 46 deletions(-)

diff --git a/x86/apic.c b/x86/apic.c
index 0a52e9a4..d4eb8e11 100644
--- a/x86/apic.c
+++ b/x86/apic.c
@@ -573,62 +573,79 @@ static inline void apic_change_mode(unsigned long new_mode)
 
 static void test_apic_change_mode(void)
 {
-	uint32_t tmict = 0x999999;
+	const uint32_t tmict_values[] = {
+		0x999999,    /* ~10ms */
+	};
+	int retry, max_retries = ARRAY_SIZE(tmict_values);
+	uint32_t tmict;
+	bool tmict_reset = false, o_nonzero = false, o_reached_zero = false;
+	bool p_nonzero = false, p_not_reset = false, p_after_wrap = false;
+	bool p2o_not_reset = false, p2o_reached_zero = false, p2o_stay_zero = false;
 
 	printf("starting apic change mode\n");
 
-	apic_write(APIC_TMICT, tmict);
+	for (retry = 0; retry < max_retries; retry++) {
+		tmict = tmict_values[retry];
+		apic_write(APIC_TMICT, tmict);
+		apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+		tmict_reset = apic_read(APIC_TMICT) == tmict;
 
-	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+		/* Testing one-shot */
+		apic_change_mode(APIC_LVT_TIMER_ONESHOT);
+		apic_write(APIC_TMICT, tmict);
+		o_nonzero = apic_read(APIC_TMCCT);
 
-	report(apic_read(APIC_TMICT) == tmict, "TMICT value reset");
+		wait_until_tmcct_is_zero(tmict, false);
+		o_reached_zero = !apic_read(APIC_TMCCT);
 
-	/* Testing one-shot */
-	apic_change_mode(APIC_LVT_TIMER_ONESHOT);
-	apic_write(APIC_TMICT, tmict);
-	report(apic_read(APIC_TMCCT), "TMCCT should have a non-zero value");
+		/*
+		 * Write TMICT before changing mode from one-shot to periodic
+		 * TMCCT should be reset to TMICT periodicly
+		 */
+		apic_write(APIC_TMICT, tmict);
+		wait_until_tmcct_is_zero(tmict, true);
+		apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+		p_nonzero = apic_read(APIC_TMCCT);
 
-	wait_until_tmcct_is_zero(tmict, false);
-	report(!apic_read(APIC_TMCCT), "TMCCT should have reached 0");
+		/*
+		 * After the change of mode, the counter should not be reset
+		 * and continue counting down from where it was
+		 */
+		p_not_reset = apic_read(APIC_TMCCT) < (tmict / 2);
+		/*
+		 * Specifically wait for timer wrap around and skip 0.
+		 * Under KVM lapic there is a possibility that a small amount
+		 * of consecutive TMCCR reads return 0 while hrtimer is reset
+		 * in an async callback
+		 */
+		wait_until_tmcct_wrap_around(tmict, false);
+		p_after_wrap = apic_read(APIC_TMCCT) > (tmict / 2);
 
-	/*
-	 * Write TMICT before changing mode from one-shot to periodic TMCCT should
-	 * be reset to TMICT periodicly
-	 */
-	apic_write(APIC_TMICT, tmict);
-	wait_until_tmcct_is_zero(tmict, true);
-	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
-	report(apic_read(APIC_TMCCT), "TMCCT should have a non-zero value");
+		wait_until_tmcct_is_zero(tmict, true);
+		/*
+		 * Keep the same TMICT and change timer mode to one-shot
+		 * TMCCT should be > 0 and count-down to 0
+		 */
+		apic_change_mode(APIC_LVT_TIMER_ONESHOT);
+		p2o_not_reset = apic_read(APIC_TMCCT) < (tmict / 2);
 
-	/*
-	 * After the change of mode, the counter should not be reset and continue
-	 * counting down from where it was
-	 */
-	report(apic_read(APIC_TMCCT) < (tmict / 2),
-	       "TMCCT should not be reset to TMICT value");
-	/*
-	 * Specifically wait for timer wrap around and skip 0.
-	 * Under KVM lapic there is a possibility that a small amount of consecutive
-	 * TMCCR reads return 0 while hrtimer is reset in an async callback
-	 */
-	wait_until_tmcct_wrap_around(tmict, false);
-	report(apic_read(APIC_TMCCT) > (tmict / 2),
-	       "TMCCT should be reset to the initial-count");
+		wait_until_tmcct_is_zero(tmict, false);
+		p2o_reached_zero = !apic_read(APIC_TMCCT);
 
-	wait_until_tmcct_is_zero(tmict, true);
-	/*
-	 * Keep the same TMICT and change timer mode to one-shot
-	 * TMCCT should be > 0 and count-down to 0
-	 */
-	apic_change_mode(APIC_LVT_TIMER_ONESHOT);
-	report(apic_read(APIC_TMCCT) < (tmict / 2),
-	       "TMCCT should not be reset to init");
-	wait_until_tmcct_is_zero(tmict, false);
-	report(!apic_read(APIC_TMCCT), "TMCCT should have reach zero");
-
-	/* now tmcct == 0 and tmict != 0 */
-	apic_change_mode(APIC_LVT_TIMER_PERIODIC);
-	report(!apic_read(APIC_TMCCT), "TMCCT should stay at zero");
+		/* now tmcct == 0 and tmict != 0 */
+		apic_change_mode(APIC_LVT_TIMER_PERIODIC);
+		p2o_stay_zero = !apic_read(APIC_TMCCT);
+	}
+
+	report(tmict_reset, "TMICT value reset");
+	report(o_nonzero, "one-shot: TMCCT should have a non-zero value");
+	report(o_reached_zero, "one-shot: TMCCT should have reached 0");
+	report(p_nonzero, "periodic: TMCCT should have a non-zero value");
+	report(p_not_reset, "TMCCT should not be reset to TMICT value");
+	report(p_after_wrap, "TMCCT should be reset to the initial-count");
+	report(p2o_not_reset, "TMCCT should not be reset to init");
+	report(p2o_reached_zero, "TMCCT should have reach zero");
+	report(p2o_stay_zero, "TMCCT should stay at zero");
 }
 
 #define KVM_HC_SEND_IPI 10
-- 
2.47.3


  reply	other threads:[~2026-04-28 13:35 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28 13:35 [kvm-unit-tests PATCH 0/2] x86/apic: fix false test_apic_change_mode failures on stalled vCPUs Igor Mammedov
2026-04-28 13:35 ` Igor Mammedov [this message]
2026-04-28 13:35 ` [kvm-unit-tests PATCH 2/2] x86/apic: add retry logic to test_apic_change_mode Igor Mammedov
2026-10-06  7:15   ` Sean Christopherson
2026-10-05 15:23 ` [kvm-unit-tests PATCH 0/2] x86/apic: fix false test_apic_change_mode failures on stalled vCPUs Igor Mammedov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260428133524.3628482-2-imammedo@redhat.com \
    --to=imammedo@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.