From patchwork Wed Jul 26 11:42:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoffer Dall X-Patchwork-Id: 9864613 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9B3306038C for ; Wed, 26 Jul 2017 11:42:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A1FFA28634 for ; Wed, 26 Jul 2017 11:42:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 93DC928745; Wed, 26 Jul 2017 11:42:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0BA0728634 for ; Wed, 26 Jul 2017 11:42:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751636AbdGZLmy (ORCPT ); Wed, 26 Jul 2017 07:42:54 -0400 Received: from mail-wm0-f42.google.com ([74.125.82.42]:34258 "EHLO mail-wm0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751616AbdGZLmx (ORCPT ); Wed, 26 Jul 2017 07:42:53 -0400 Received: by mail-wm0-f42.google.com with SMTP id t138so736694wmt.1 for ; Wed, 26 Jul 2017 04:42:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=thSxJb555kI2Ha0NEfVmJ8iP6PA/Kc5xUUQQIWR1jQc=; b=DQkbum3IdNABzOehuJGQUuce5VEF7QORESNTZsp2jeIYYGFT7PSKWgxxw0gSDB46pj IBEWNWe11ntLKHNnwserCeEmMvYXSsaCO1nczFqKMLtIW/zHVfueS3URmdux1bEEhGqs GaKfwbULkyCaqtr1y6WOJMZWBNPlCqyklMHPU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=thSxJb555kI2Ha0NEfVmJ8iP6PA/Kc5xUUQQIWR1jQc=; b=l2bqr85zYjHlTA65KTuRkeLwYZ1xWHK+0i/5Hr8t1WvgOC8EcTtjEBf+aZKzv5MqjG pkkxhCacIKDNy3tOzfTeGgkRz3xUjiSCtQEvefak/zS5Y9VzqXChx78Wg+TPEuDSHqj/ BD4rn9IpIKPLTtmqpVR4bYo0Tbl0yfgyNVYFfzN7iCqcdc+tPfof1KSqvbUiEekppQgv LDTX2bqT02t3BZYmzXzebk8xXA17E4mTRSl0nuxhBWM0irhc6Ae8kFIdpiaPoyc2bd5o ma965IMIOdiQXNsG9vcpBzWNphja5mt86Bthp8/u2GHK1gYHD5wm50/5yR3eOicde4RW bypA== X-Gm-Message-State: AIVw111Pz6h7zo5nB4jbW4Hlac8E+4nvQYfPhlocwPmxYnKGrI+1Y9ej z7VFI4C1U4yU6950Pnahzw== X-Received: by 10.80.166.97 with SMTP id d88mr585443edc.196.1501069372410; Wed, 26 Jul 2017 04:42:52 -0700 (PDT) Received: from localhost.localdomain (xd93ddc2d.cust.hiper.dk. [217.61.220.45]) by smtp.gmail.com with ESMTPSA id x36sm8553362edb.64.2017.07.26.04.42.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 26 Jul 2017 04:42:51 -0700 (PDT) From: Christoffer Dall To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Andrew Jones , Alexander Graf , Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Marc Zyngier , Christoffer Dall Subject: [PATCH kvm-unit-tests] arm64: timer: Avoid IRQ race in timer test Date: Wed, 26 Jul 2017 13:42:49 +0200 Message-Id: <20170726114249.17774-1-cdall@linaro.org> X-Mailer: git-send-email 2.9.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current timer test relies on testing the pending state of the timer before the interrupt handler has run which could lower the pending signal again (because it masks the timer output signal). What we really want is to make sure the output signal from the timer as perceived by the virtual interrupt controller is low when the timer is programmed some time far in the future. The proper way to do that is to disable the timer interrupt on the distributor and then reading its pending state. Signed-off-by: Christoffer Dall --- arm/timer.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/arm/timer.c b/arm/timer.c index 33dfc6f..e824338 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -96,6 +96,23 @@ static struct timer_info ptimer_info = { .write_ctl = write_ptimer_ctl, }; +static void set_timer_irq_enabled(struct timer_info *info, bool enabled) +{ + u32 val = 0; + + if (enabled) + val = 1 << PPI(info->irq); + + switch (gic_version()) { + case 2: + writel(val, gicv2_dist_base() + GICD_ISENABLER + 0); + break; + case 3: + writel(val, gicv3_sgi_base() + GICR_ISENABLER0); + break; + } +} + static void irq_handler(struct pt_regs *regs) { struct timer_info *info; @@ -133,6 +150,8 @@ static bool test_cval_10msec(struct timer_info *info) /* Program timer to fire in 10 ms */ before_timer = info->read_counter(); info->write_cval(before_timer + time_10ms); + info->write_ctl(ARCH_TIMER_CTL_ENABLE); + isb(); /* Wait for the timer to fire */ while (!(info->read_ctl() & ARCH_TIMER_CTL_ISTATUS)) @@ -159,13 +178,25 @@ static void test_timer(struct timer_info *info) u64 time_10s = read_sysreg(cntfrq_el0) * 10; u64 later = now + time_10s; + /* 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. */ + set_timer_irq_enabled(info, false); - /* Enable the timer, but schedule it for much later*/ + /* Enable the timer, but schedule it for much later */ info->write_cval(later); - isb(); info->write_ctl(ARCH_TIMER_CTL_ENABLE); - + isb(); report("not pending before", !gic_timer_pending(info)); + + info->write_cval(now - 1); + isb(); + report("interrupt signal pending", gic_timer_pending(info)); + + /* Disable the timer again and prepare to take interrupts */ + info->write_ctl(0); + set_timer_irq_enabled(info, true); + report("latency within 10 ms", test_cval_10msec(info)); report("interrupt received", info->irq_received); @@ -211,13 +242,9 @@ static void test_init(void) switch (gic_version()) { case 2: - writel(1 << PPI(vtimer_info.irq), gicv2_dist_base() + GICD_ISENABLER + 0); - writel(1 << PPI(ptimer_info.irq), gicv2_dist_base() + GICD_ISENABLER + 0); gic_ispendr = gicv2_dist_base() + GICD_ISPENDR; break; case 3: - writel(1 << PPI(vtimer_info.irq), gicv3_sgi_base() + GICR_ISENABLER0); - writel(1 << PPI(ptimer_info.irq), gicv3_sgi_base() + GICR_ISENABLER0); gic_ispendr = gicv3_sgi_base() + GICD_ISPENDR; break; }