From patchwork Mon Jun 26 18:49:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Tokarev X-Patchwork-Id: 696472 Delivered-To: patch@linaro.org Received: by 2002:adf:e885:0:0:0:0:0 with SMTP id d5csp3384204wrm; Mon, 26 Jun 2023 11:58:16 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4HH/Cn5qw96bHkkddCqjMAr88Ctn/bLF78E2xZ6b3UGjYsEc3FseJPsEmBul9znY2dx/HZ X-Received: by 2002:a05:620a:2455:b0:763:de2c:1a8a with SMTP id h21-20020a05620a245500b00763de2c1a8amr21218837qkn.57.1687805895969; Mon, 26 Jun 2023 11:58:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1687805895; cv=none; d=google.com; s=arc-20160816; b=rMy2Ai1dhz+M/FPrIUqswukGA7CpCZHIkHAxnfHob9OFr2/H/TI1RfCq7e2HrITHvB vaOvhFdazMFZ1hWqOjvuQPgnWjBPn59Fl5XwE96bL6fY4mZiif5NBn9j06GVbVE9nuIZ ancKBeqM9XQfxd+AE1eXMqGibys5GlzdWqMw/Opixpn2Kpo73FFNp1D+JekjWr97PQwN Td5Nh8HzVAcwLZ8vmKfi9g0mrBwMO53Z9oS+08nemlalkjaVrUzgdo7nLF+cWIDuahgZ +PJoCA5a6vK1MQmTAta/dJdoAr9kCu055pcykAicQiIHTzNu6zRDMjoQGjiUHKOqbhNB hPmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from; bh=NhRi3p1hDy9Xk0RJq9I6RZyIc/6CLrr0Ob/vBCkatbc=; fh=9Puwj9MOBIDO5gzvzLBZlV9GG/phz4th2oI9KImXtng=; b=Qo5HQDpkpyFxyYIUCTHnAZ3wBjtEdbfulE+5GFzxyd7nn4V/keJyAcf/lsIW5fjMkO L6WHjrQeS7CpQNWR3BVJUWXPDFXg/k4GRqlIRoxZllZfzt6gM+xHHIvTKjFYnGEPbtFy Si9HM3gDWIBD9vi9RynwtSiEMgPAHo+pcOzk23NIqfGfVhQU20nZTjGJyLFlDvakwDVO iFl5BKIxGwKxFy1C7sR8QGcmBq74eg0Iet9T7iaZ/KjYc98lI2QfOTUvWS1KrPO+lIL6 LfSvERdS/GFt4w6IKWG9H+21XDc4EharwFwW/z6Rb8GM9jqaNGeFu+Gwg+a7MB47UsFs f+pg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id p8-20020a05622a13c800b003ff3a2f91a5si2082772qtk.672.2023.06.26.11.58.15 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Mon, 26 Jun 2023 11:58:15 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qDrN0-0003Ao-5c; Mon, 26 Jun 2023 14:55:26 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qDrMP-0001ye-3E; Mon, 26 Jun 2023 14:54:49 -0400 Received: from isrv.corpit.ru ([86.62.121.231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qDrLn-0005V0-SF; Mon, 26 Jun 2023 14:54:13 -0400 Received: from tsrv.corpit.ru (tsrv.tls.msk.ru [192.168.177.2]) by isrv.corpit.ru (Postfix) with ESMTP id 418D8EF41; Mon, 26 Jun 2023 21:50:29 +0300 (MSK) Received: from tls.msk.ru (mjt.wg.tls.msk.ru [192.168.177.130]) by tsrv.corpit.ru (Postfix) with SMTP id C36D1F7D0; Mon, 26 Jun 2023 21:50:27 +0300 (MSK) Received: (nullmailer pid 1574085 invoked by uid 1000); Mon, 26 Jun 2023 18:50:16 -0000 From: Michael Tokarev To: qemu-devel@nongnu.org, qemu-stable@nongnu.org Cc: Peter Maydell , Joel Stanley , Michael Tokarev Subject: [Stable-8.0.3 42/54] hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop Date: Mon, 26 Jun 2023 21:49:49 +0300 Message-Id: <20230626185002.1573836-42-mjt@tls.msk.ru> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=86.62.121.231; envelope-from=mjt@tls.msk.ru; helo=isrv.corpit.ru X-Spam_score_int: -68 X-Spam_score: -6.9 X-Spam_bar: ------ X-Spam_report: (-6.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_HI=-5, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org From: Peter Maydell The nrf51_timer has a free-running counter which we implement using the pattern of using two fields (update_counter_ns, counter) to track the last point at which we calculated the counter value, and the counter value at that time. Then we can find the current counter value by converting the difference in wall-clock time between then and now to a tick count that we need to add to the counter value. Unfortunately the nrf51_timer's implementation of this has a bug which means it loses time every time update_counter() is called. After updating s->counter it always sets s->update_counter_ns to 'now', even though the actual point when s->counter hit the new value will be some point in the past (half a tick, say). In the worst case (guest code in a tight loop reading the counter, icount mode) the counter is continually queried less than a tick after it was last read, so s->counter never advances but s->update_counter_ns does, and the guest never makes forward progress. The fix for this is to only advance update_counter_ns to the timestamp of the last tick, not all the way to 'now'. (This is the pattern used in hw/misc/mps2-fpgaio.c's counter.) Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell Reviewed-by: Joel Stanley Message-id: 20230606134917.3782215-1-peter.maydell@linaro.org (cherry picked from commit d2f9a79a8cf6ab992e1d0f27ad05b3e582d2b18a) Signed-off-by: Michael Tokarev diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c index 42be79c736..50c6772383 100644 --- a/hw/timer/nrf51_timer.c +++ b/hw/timer/nrf51_timer.c @@ -45,7 +45,12 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now) uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns); s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]); - s->update_counter_ns = now; + /* + * Only advance the sync time to the timestamp of the last tick, + * not all the way to 'now', so we don't lose time if we do + * multiple resyncs in a single tick. + */ + s->update_counter_ns += ticks_to_ns(s, ticks); return ticks; }