From patchwork Tue Dec 7 15:46:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 12662147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86766C433F5 for ; Tue, 7 Dec 2021 15:46:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239041AbhLGPu0 (ORCPT ); Tue, 7 Dec 2021 10:50:26 -0500 Received: from foss.arm.com ([217.140.110.172]:35216 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238505AbhLGPuZ (ORCPT ); Tue, 7 Dec 2021 10:50:25 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3422D13A1; Tue, 7 Dec 2021 07:46:55 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 717773F5A1; Tue, 7 Dec 2021 07:46:54 -0800 (PST) From: Alexandru Elisei To: drjones@redhat.com, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Subject: [kvm-unit-tests PATCH 1/4] arm: timer: Fix TVAL comparison for timer condition met Date: Tue, 7 Dec 2021 15:46:38 +0000 Message-Id: <20211207154641.87740-2-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211207154641.87740-1-alexandru.elisei@arm.com> References: <20211207154641.87740-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org ARM DDI 0487G.a states on page D13-4180 that, when the virtual timer is enabled, the timer condition is met when CNTVCT_EL0 - CNTV_CVAL_EL0 >= 0. Multiplying both sides of the inequality by -1, we get the equivalent condition CNTV_CVAL_EL0 - CNTVCT_EL0 <= 0 for when the timer should fire. On the same page, it states that a read of the CNTV_TVAL_EL0 register returns CNTV_CVAL_EL0 - CNTVCT_EL0 if the virtual timer is enabled. Putting the two together, the timer condition is met when the value of the TVAL register is less than or *equal* to 0. Same rules apply for the physical timer. Fix the check for the timer expiring by treating a TVAL value equal to zero as a valid condition for the timer to fire. Signed-off-by: Alexandru Elisei --- arm/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arm/timer.c b/arm/timer.c index 09e3f8f6bd7d..2a6687f22874 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -277,7 +277,7 @@ static void test_timer(struct timer_info *info) local_irq_enable(); left = info->read_tval(); report(info->irq_received, "interrupt received after TVAL/WFI"); - report(left < 0, "timer has expired"); + report(left <= 0, "timer has expired"); report_info("TVAL is %d ticks", left); } From patchwork Tue Dec 7 15:46:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 12662149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE27FC433FE for ; Tue, 7 Dec 2021 15:46:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239045AbhLGPu1 (ORCPT ); Tue, 7 Dec 2021 10:50:27 -0500 Received: from foss.arm.com ([217.140.110.172]:35222 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238505AbhLGPu0 (ORCPT ); Tue, 7 Dec 2021 10:50:26 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3DA6211D4; Tue, 7 Dec 2021 07:46:56 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7B5FA3F5A1; Tue, 7 Dec 2021 07:46:55 -0800 (PST) From: Alexandru Elisei To: drjones@redhat.com, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Subject: [kvm-unit-tests PATCH 2/4] arm: timer: Move the different tests into their own functions Date: Tue, 7 Dec 2021 15:46:39 +0000 Message-Id: <20211207154641.87740-3-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211207154641.87740-1-alexandru.elisei@arm.com> References: <20211207154641.87740-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org At the moment, the timer test is one big function that checks different aspects of the timer implementation, and it's not immediately obvious if a check depends on a state from a previous test, making understanding the code more difficult than necessary. Move the checks into logically distinct functions and leave the timer in a known state before proceeding to the next test to make the code easier to understand, maintain and extend. The timer interrupt is now enabled at the GIC level in test_init() to break the dependency that the tests have on the timer pending test running first. There should be no functional change as a result of this patch. Signed-off-by: Alexandru Elisei --- arm/timer.c | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/arm/timer.c b/arm/timer.c index 2a6687f22874..617845c6525d 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -226,16 +226,23 @@ static bool test_cval_10msec(struct timer_info *info) return difference < time_10ms; } -static void test_timer(struct timer_info *info) +static void disable_timer(struct timer_info *info) +{ + info->write_ctl(0); + info->irq_received = false; +} + +static void test_timer_pending(struct timer_info *info) { u64 now = info->read_counter(); u64 time_10s = read_sysreg(cntfrq_el0) * 10; u64 later = now + time_10s; - s32 left; - /* We don't want the irq handler to fire because that will change the + /* + * We don't want the irq handler to fire because that will change the * timer state and we want to test the timer output signal. We can - * still read the pending state even if it's disabled. */ + * still read the pending state even if it's disabled. + */ set_timer_irq_enabled(info, false); /* Enable the timer, but schedule it for much later */ @@ -248,10 +255,9 @@ static void test_timer(struct timer_info *info) report(timer_pending(info) && gic_timer_check_state(info, GIC_IRQ_STATE_PENDING), "interrupt signal pending"); - /* Disable the timer again and prepare to take interrupts */ - info->write_ctl(0); - info->irq_received = false; + disable_timer(info); set_timer_irq_enabled(info, true); + report(!info->irq_received, "no interrupt when timer is disabled"); report(!timer_pending(info) && gic_timer_check_state(info, GIC_IRQ_STATE_INACTIVE), "interrupt signal no longer pending"); @@ -261,14 +267,21 @@ static void test_timer(struct timer_info *info) report(timer_pending(info) && gic_timer_check_state(info, GIC_IRQ_STATE_INACTIVE), "interrupt signal not pending"); + disable_timer(info); +} + +static void test_timer_cval(struct timer_info *info) +{ report(test_cval_10msec(info), "latency within 10 ms"); report(info->irq_received, "interrupt received"); - /* Disable the timer again */ - info->write_ctl(0); + disable_timer(info); +} + +static void test_timer_tval(struct timer_info *info) +{ + s32 left; - /* Test TVAL and IRQ trigger */ - info->irq_received = false; info->write_tval(read_sysreg(cntfrq_el0) / 100); /* 10 ms */ local_irq_disable(); info->write_ctl(ARCH_TIMER_CTL_ENABLE); @@ -279,6 +292,15 @@ static void test_timer(struct timer_info *info) report(info->irq_received, "interrupt received after TVAL/WFI"); report(left <= 0, "timer has expired"); report_info("TVAL is %d ticks", left); + + disable_timer(info); +} + +static void test_timer(struct timer_info *info) +{ + test_timer_pending(info); + test_timer_cval(info); + test_timer_tval(info); } static void test_vtimer(void) @@ -329,6 +351,8 @@ static void test_init(void) } install_irq_handler(EL1H_IRQ, irq_handler); + set_timer_irq_enabled(&ptimer_info, true); + set_timer_irq_enabled(&vtimer_info, true); local_irq_enable(); } From patchwork Tue Dec 7 15:46:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 12662151 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C881C433F5 for ; Tue, 7 Dec 2021 15:46:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239049AbhLGPu2 (ORCPT ); Tue, 7 Dec 2021 10:50:28 -0500 Received: from foss.arm.com ([217.140.110.172]:35232 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238505AbhLGPu2 (ORCPT ); Tue, 7 Dec 2021 10:50:28 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 97B0D11D4; Tue, 7 Dec 2021 07:46:57 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D4E943F5A1; Tue, 7 Dec 2021 07:46:56 -0800 (PST) From: Alexandru Elisei To: drjones@redhat.com, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Subject: [kvm-unit-tests PATCH 3/4] arm: timer: Test CVAL before interrupt pending state Date: Tue, 7 Dec 2021 15:46:40 +0000 Message-Id: <20211207154641.87740-4-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211207154641.87740-1-alexandru.elisei@arm.com> References: <20211207154641.87740-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The timer pending test uses CVAL to trigger changes in the timer interrupt state. Move the CVAL test before the pending test to make sure that writes to the CVAL register have an effect on the timer internal state before using the register for other tests. Signed-off-by: Alexandru Elisei --- arm/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arm/timer.c b/arm/timer.c index 617845c6525d..7b2d82896c74 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -298,8 +298,8 @@ static void test_timer_tval(struct timer_info *info) static void test_timer(struct timer_info *info) { - test_timer_pending(info); test_timer_cval(info); + test_timer_pending(info); test_timer_tval(info); } From patchwork Tue Dec 7 15:46:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 12662153 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A1A87C4332F for ; Tue, 7 Dec 2021 15:47:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239057AbhLGPua (ORCPT ); Tue, 7 Dec 2021 10:50:30 -0500 Received: from foss.arm.com ([217.140.110.172]:35238 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238505AbhLGPu3 (ORCPT ); Tue, 7 Dec 2021 10:50:29 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 999A911D4; Tue, 7 Dec 2021 07:46:58 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D99AB3F5A1; Tue, 7 Dec 2021 07:46:57 -0800 (PST) From: Alexandru Elisei To: drjones@redhat.com, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Subject: [kvm-unit-tests PATCH 4/4] arm: timer: Take into account other wake-up events for the TVAL test Date: Tue, 7 Dec 2021 15:46:41 +0000 Message-Id: <20211207154641.87740-5-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20211207154641.87740-1-alexandru.elisei@arm.com> References: <20211207154641.87740-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The TVAL test programs the timer to fire into the future, waits for an interrupt using the WFI instruction, and when the instruction completes it checks that the timer interrupt has fired. According to ARM DDI 0487G.a there are other wake-up events that can cause the WFI to complete (listed on page D1-2520), among them interrupts routed to a higher exception level, where the hypervisor is running (if running under virtualization) or firmware (if running on baremetal). In practice, this is unlikely to have caused a false test failure, because for a GICv3 (which the author assumes is a lot more common than a GICv4+) the WFI is trapped by KVM and the VCPU thread is resumed only after the timer asserts the interrupt, as the test expects. Signed-off-by: Alexandru Elisei --- arm/timer.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/arm/timer.c b/arm/timer.c index 7b2d82896c74..8a668e8adac8 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -278,17 +278,44 @@ static void test_timer_cval(struct timer_info *info) disable_timer(info); } -static void test_timer_tval(struct timer_info *info) +static void timer_do_wfi(struct timer_info *info) { - s32 left; - - info->write_tval(read_sysreg(cntfrq_el0) / 100); /* 10 ms */ local_irq_disable(); - info->write_ctl(ARCH_TIMER_CTL_ENABLE); + if (info->irq_received) + goto out; report_info("waiting for interrupt..."); wfi(); +out: local_irq_enable(); - left = info->read_tval(); +} + +static void test_timer_tval(struct timer_info *info) +{ + u64 time_10ms = read_sysreg(cntfrq_el0) / 100; + s32 left; + int i; + + info->write_tval(time_10ms); + info->write_ctl(ARCH_TIMER_CTL_ENABLE); + + for (;;) { + timer_do_wfi(info); + left = info->read_tval(); + if (info->irq_received || left <= 0) + break; + } + + /* Wait one second for the GIC to update the interrupt state. */ + if (left <= 0 && !info->irq_received) { + for (i = 0; i < 10; i++) { + timer_do_wfi(info); + if (info->irq_received) + break; + mdelay(100); + } + left = info->read_tval(); + } + report(info->irq_received, "interrupt received after TVAL/WFI"); report(left <= 0, "timer has expired"); report_info("TVAL is %d ticks", left);