From patchwork Mon Nov 20 17:35:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 745377 Delivered-To: patch@linaro.org Received: by 2002:a5d:5052:0:b0:32d:baff:b0ca with SMTP id h18csp1432911wrt; Mon, 20 Nov 2023 09:35:56 -0800 (PST) X-Google-Smtp-Source: AGHT+IF6qWZNqQB72pIxkosgzxNoMHNrmkqE94cqERopxzrA1ZE+BXhjsjsYdRGxO2WnODzztuOu X-Received: by 2002:a05:622a:1a95:b0:418:1f52:1421 with SMTP id s21-20020a05622a1a9500b004181f521421mr11004156qtc.9.1700501755811; Mon, 20 Nov 2023 09:35:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700501755; cv=none; d=google.com; s=arc-20160816; b=Nkq12dTOegzH2t/e7FqP160S0wKO3pQjdHePLfigshFPm3bA/SKVu3wP4QYdhwi2T2 iJXRMwgvYCp8X5ca95YB5j8Tw9vO35wMHpyqg5lWjW04zAOA2iPmHWzlxOMfxMYddnUb hyMb7L9rBi+dupy1RNGBTRlsW+s3b3BtqdgxwkIiS/SsZI5Qk8P2ZliIR/xS2arRevKA T5Rf4MOo3Y6vxPXHJszuyiLaEmyiFUlP9D9zmPjA+2rUEhyBWU9WMjS75uK8XiI6Zqi2 cGhLRWen7xND6BBYhTq6f889Jd4ggj4MP1okMaOOZeMbg4DOMhbS9uUmSmxSVqhtybXa k9uw== 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:message-id:date:subject:cc:to:from:dkim-signature; bh=pxDVMDGr8B4qXH0/pCUMU+JxzeY5WrCdtQLxJO9oIRQ=; fh=KlbSfc2y1lBwVVuHB14St4FwSXfiQlN4tPIehUx9AdU=; b=eB/r8tfw/IFqjXiHm4oQJuUQ6k+nWR04WBz1xZI/zM0jykPzDaODuTICWXAyGcW8gP oUDKDuewwVM37/6pS3jXVU65PM/a3QGDu/MfGaL3Wgq0hNA9ZwAZPEx4tPQRyHrpLCyV FEvj5Ea4sE6mTIkumw4IQftGbBGyzQgt0J15hFExqF6VzulfeaEB3zdYiGpewh6g0Mbr 1Ud9rGQtbj272e8KhJrP4Lvr7w58cal26ubN0j99kjMJYWsADSQGwc+/uFQ7RtoqEML4 QuRV8IaAJJaFAI10CkaJ5nPVQzXXJym0n1ebw9PMBtQ9ctW33GiGQUG7lUKmanrQDK9E YzyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=k9m0hQDc; 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id w5-20020a05622a134500b00421ab8f9888si8132431qtk.342.2023.11.20.09.35.55 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Mon, 20 Nov 2023 09:35:55 -0800 (PST) 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; dkim=pass header.i=@linaro.org header.s=google header.b=k9m0hQDc; 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r58BO-0005nk-LW; Mon, 20 Nov 2023 12:35:38 -0500 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 1r58Ax-0005bj-JY for qemu-devel@nongnu.org; Mon, 20 Nov 2023 12:35:11 -0500 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1r58Au-0002Ra-UE for qemu-devel@nongnu.org; Mon, 20 Nov 2023 12:35:10 -0500 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-32deb2809daso3103654f8f.3 for ; Mon, 20 Nov 2023 09:35:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1700501707; x=1701106507; darn=nongnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=pxDVMDGr8B4qXH0/pCUMU+JxzeY5WrCdtQLxJO9oIRQ=; b=k9m0hQDc3h6Dh4WBqj8tbKIrYhqT3xsJPQdcmlzr3orJ5Ok3bEru3F4wsMpKx7GDEi dL1iuYy0MBP4FO3X5DoEMLmjyVxI8F93Ro6evndjmScc6Z1hWHqL/D3eoqWGcP2/ADG+ T5WSZeCnN3ncDaAJfdptbe5ax38sjlu31X0EYTvdSKU5kNeUlSQ/5AULquf8Ie0Ztf1B wD0vSBFxIsdD1VqNzIob8yyhR+HxE8G1U0al9cyi4hL7F9Xt5eXjKRr+qEtUdrsw8D2i 96YQ1YelWDJyd6lyuZzZ2yVQRsju+f3BKo6nv7rwyg2gOlVEXEgRe9U9LA3giXP6KY0t x4GQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700501707; x=1701106507; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=pxDVMDGr8B4qXH0/pCUMU+JxzeY5WrCdtQLxJO9oIRQ=; b=UOcGrJPVVLjbdcNGehqueL5P/M278LReggXNEeu5YMYQf3Xg7RF6rFQ5zqHTuaveG1 nu9mQ6HuIj0FT2kqGbMNj+C9dLlRJKK0DodjTHp3EdsF2zBsXIYjk3VQ8UeElCwEpU4i Xtop2OMB9hCvMvbqjPDcKHCXl9+ln8xc0riQkI50uL1myDhMPDV3hRFF4Ai/i2QaQQ4Y c90a9WHWU8Sh1nEElHZSeFhM8+qys3HNgyo5WT530c5KPABSNybXRyX/9zQdfrj+pFQD sBhEdzKQwY7W/YZ9xo3sRIjz4J94MVLAZk7V/9rVbUXM54zFwVnKrhzESM9gQ1QG5rGY 9GQg== X-Gm-Message-State: AOJu0YwCDfJNckgBaEPbNIl5uV36tYpgPP84SLT4eYDPBrmcXpv+T/xZ QomWhkKSRZHWs8eslDfqtzSC0w== X-Received: by 2002:a5d:5f56:0:b0:332:c9ed:cc2c with SMTP id cm22-20020a5d5f56000000b00332c9edcc2cmr2339234wrb.3.1700501707346; Mon, 20 Nov 2023 09:35:07 -0800 (PST) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id d5-20020adfef85000000b0032fb46812c2sm11850633wro.12.2023.11.20.09.35.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Nov 2023 09:35:07 -0800 (PST) From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: =?utf-8?q?Alex_Benn=C3=A9e?= , Leonid Komarianskyi Subject: [PATCH for-8.2] target/arm: Handle overflow in calculation of next timer tick Date: Mon, 20 Nov 2023 17:35:06 +0000 Message-Id: <20231120173506.3729884-1-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::436; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x436.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable 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 In commit edac4d8a168 back in 2015 when we added support for the virtual timer offset CNTVOFF_EL2, we didn't correctly update the timer-recalculation code that figures out when the timer interrupt is next going to change state. We got it wrong in two ways: * for the 0->1 transition, we didn't notice that gt->cval + offset can overflow a uint64_t * for the 1->0 transition, we didn't notice that the transition might now happen before the count rolls over, if offset > count In the former case, we end up trying to set the next interrupt for a time in the past, which results in QEMU hanging as the timer fires continuously. In the latter case, we would fail to update the interrupt status when we are supposed to. Fix the calculations in both cases. The test case is Alex Bennée's from the bug report, and tests the 0->1 transition overflow case. Fixes: edac4d8a168 ("target-arm: Add CNTVOFF_EL2") Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/60 Signed-off-by: Alex Bennée Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- Thanks to Leonid for his recent patch which prodded me into looking at this again. I preferred to fix both halves of the if(), rather than just one, and I have thrown in Alex's test case since it was conveniently to hand. --- target/arm/helper.c | 25 ++++++++++-- tests/tcg/aarch64/system/vtimer.c | 48 +++++++++++++++++++++++ tests/tcg/aarch64/Makefile.softmmu-target | 7 +++- 3 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 tests/tcg/aarch64/system/vtimer.c diff --git a/target/arm/helper.c b/target/arm/helper.c index ff1970981ee..0430ae55edf 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -2646,11 +2646,28 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx) gt->ctl = deposit32(gt->ctl, 2, 1, istatus); if (istatus) { - /* Next transition is when count rolls back over to zero */ - nexttick = UINT64_MAX; + /* + * Next transition is when (count - offset) rolls back over to 0. + * If offset > count then this is when count == offset; + * if offset <= count then this is when count == offset + UINT64_MAX + * For the latter case we set nexttick to an "as far in future + * as possible" value and let the code below handle it. + */ + if (offset > count) { + nexttick = offset; + } else { + nexttick = UINT64_MAX; + } } else { - /* Next transition is when we hit cval */ - nexttick = gt->cval + offset; + /* + * Next transition is when (count - offset) == cval, i.e. + * when count == (cval + offset). + * If that would overflow, then again we set up the next interrupt + * for "as far in the future as possible" for the code below. + */ + if (uadd64_overflow(gt->cval, offset, &nexttick)) { + nexttick = UINT64_MAX; + } } /* * Note that the desired next expiry time might be beyond the diff --git a/tests/tcg/aarch64/system/vtimer.c b/tests/tcg/aarch64/system/vtimer.c new file mode 100644 index 00000000000..42f2f7796c7 --- /dev/null +++ b/tests/tcg/aarch64/system/vtimer.c @@ -0,0 +1,48 @@ +/* + * Simple Virtual Timer Test + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +/* grabbed from Linux */ +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#define read_sysreg(r) ({ \ + uint64_t __val; \ + asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \ + __val; \ +}) + +#define write_sysreg(r, v) do { \ + uint64_t __val = (uint64_t)(v); \ + asm volatile("msr " __stringify(r) ", %x0" \ + : : "rZ" (__val)); \ +} while (0) + +int main(void) +{ + int i; + + ml_printf("VTimer Test\n"); + + write_sysreg(cntvoff_el2, 1); + write_sysreg(cntv_cval_el0, -1); + write_sysreg(cntv_ctl_el0, 1); + + ml_printf("cntvoff_el2=%lx\n", read_sysreg(cntvoff_el2)); + ml_printf("cntv_cval_el0=%lx\n", read_sysreg(cntv_cval_el0)); + ml_printf("cntv_ctl_el0=%lx\n", read_sysreg(cntv_ctl_el0)); + + /* Now read cval a few times */ + for (i = 0; i < 10; i++) { + ml_printf("%d: cntv_cval_el0=%lx\n", i, read_sysreg(cntv_cval_el0)); + } + + return 0; +} diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index b74a2534e38..d71659cc226 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -45,7 +45,8 @@ TESTS+=memory-sve # Running QEMU_BASE_MACHINE=-M virt -cpu max -display none -QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel +QEMU_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output +QEMU_OPTS+=$(QEMU_BASE_MACHINE) $(QEMU_BASE_ARGS) -kernel # console test is manual only QEMU_SEMIHOST=-chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline @@ -55,6 +56,10 @@ run-semiconsole: semiconsole run-plugin-semiconsole-with-%: semiconsole $(call skip-test, $<, "MANUAL ONLY") +# vtimer test needs EL2 +QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4 +run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_BASE_ARGS) -kernel + # Simple Record/Replay Test .PHONY: memory-record run-memory-record: memory-record memory