From patchwork Sat May 25 15:12:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 10960867 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B6F7A112C for ; Sat, 25 May 2019 15:20:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A1B50287AE for ; Sat, 25 May 2019 15:20:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 922DF287F9; Sat, 25 May 2019 15:20:28 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 133F2287AE for ; Sat, 25 May 2019 15:20:24 +0000 (UTC) Received: from localhost ([127.0.0.1]:43285 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hUYT0-0002SA-2n for patchwork-qemu-devel@patchwork.kernel.org; Sat, 25 May 2019 11:20:14 -0400 Received: from eggs.gnu.org ([209.51.188.92]:33140) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hUYNA-0006DB-80 for qemu-devel@nongnu.org; Sat, 25 May 2019 11:14:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hUYN9-000272-0F for qemu-devel@nongnu.org; Sat, 25 May 2019 11:14:12 -0400 Received: from 5.mo68.mail-out.ovh.net ([46.105.62.179]:50703) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hUYN8-00025d-QW for qemu-devel@nongnu.org; Sat, 25 May 2019 11:14:10 -0400 Received: from player698.ha.ovh.net (unknown [10.108.57.178]) by mo68.mail-out.ovh.net (Postfix) with ESMTP id 8391212D049 for ; Sat, 25 May 2019 17:14:09 +0200 (CEST) Received: from kaod.org (lfbn-1-10649-41.w90-89.abo.wanadoo.fr [90.89.235.41]) (Authenticated sender: clg@kaod.org) by player698.ha.ovh.net (Postfix) with ESMTPSA id 2C724625A813; Sat, 25 May 2019 15:14:03 +0000 (UTC) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: Peter Maydell Date: Sat, 25 May 2019 17:12:33 +0200 Message-Id: <20190525151241.5017-12-clg@kaod.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190525151241.5017-1-clg@kaod.org> References: <20190525151241.5017-1-clg@kaod.org> MIME-Version: 1.0 X-Ovh-Tracer-Id: 6611565728465783569 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeduuddruddukedgkeejucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 46.105.62.179 Subject: [Qemu-devel] [PATCH 11/19] aspeed/timer: Provide back-pressure information for short periods X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrew Jeffery , =?utf-8?q?C=C3=A9dric_Le_Goater?= , qemu-arm@nongnu.org, qemu-devel@nongnu.org, Joel Stanley Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Andrew Jeffery First up: This is not the way the hardware behaves. However, it helps resolve real-world problems with short periods being used under Linux. Commit 4451d3f59f2a ("clocksource/drivers/fttmr010: Fix set_next_event handler") in Linux fixed the timer driver to correctly schedule the next event for the Aspeed controller, and in combination with 5daa8212c08e ("ARM: dts: aspeed: Describe random number device") Linux will now set a timer with a period as low as 1us. Configuring a qemu timer with such a short period results in spending time handling the interrupt in the model rather than executing guest code, leading to noticeable "sticky" behaviour in the guest. The behaviour of Linux is correct with respect to the hardware, so we need to improve our handling under emulation. The approach chosen is to provide back-pressure information by calculating an acceptable minimum number of ticks to be set on the model. Under Linux an additional read is added in the timer configuration path to detect back-pressure, which will never occur on hardware. However if back-pressure is observed, the driver alerts the clock event subsystem, which then performs its own next event dilation via a config option - d1748302f70b ("clockevents: Make minimum delay adjustments configurable") A minimum period of 5us was experimentally determined on a Lenovo T480s, which I've increased to 20us for "safety". Signed-off-by: Andrew Jeffery Signed-off-by: Cédric Le Goater --- include/hw/timer/aspeed_timer.h | 1 + hw/misc/aspeed_scu.c | 6 ++++++ hw/timer/aspeed_timer.c | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h index 1fb949e16710..10c851ebb6d7 100644 --- a/include/hw/timer/aspeed_timer.h +++ b/include/hw/timer/aspeed_timer.h @@ -41,6 +41,7 @@ typedef struct AspeedTimer { * interrupts, signalling with both the rising and falling edge. */ int32_t level; + uint32_t min_ticks; uint32_t reload; uint32_t match[2]; uint64_t start; diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index ab1e18ed4b0f..a7b37e5ece01 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -422,6 +422,12 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp) TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE); sysbus_init_mmio(sbd, &s->iomem); + + /* + * Reset on realize to ensure the APB clock value is calculated in time for + * use by the timer model, which is reset before the SCU. + */ + aspeed_scu_reset(dev); } static const VMStateDescription vmstate_aspeed_scu = { diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c index 6c184572ea04..9988b8fbbf17 100644 --- a/hw/timer/aspeed_timer.c +++ b/hw/timer/aspeed_timer.c @@ -259,7 +259,7 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg, switch (reg) { case TIMER_REG_RELOAD: old_reload = t->reload; - t->reload = value; + t->reload = value < t->min_ticks ? t->min_ticks : value; /* If the reload value was not previously set, or zero, and * the current value is valid, try to start the timer if it is @@ -311,7 +311,11 @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable) static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable) { + AspeedTimerCtrlState *s = timer_to_ctrl(t); + uint32_t rate = enable ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq; + trace_aspeed_timer_ctrl_external_clock(t->id, enable); + t->min_ticks = muldiv64(20 * SCALE_US, rate, NANOSECONDS_PER_SECOND); } static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)