From patchwork Thu Aug 11 17:16:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 596660 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:b345:0:0:0:0 with SMTP id w5csp925785maz; Thu, 11 Aug 2022 10:23:16 -0700 (PDT) X-Google-Smtp-Source: AA6agR5MZpkXcmzMwyoskTNLwVhbqLlQOal6j2CG9cStH1PdhZ+lyn5cTkKI2kkiH7KTIrxn0rCQ X-Received: by 2002:a05:620a:198e:b0:6b6:4f9c:592b with SMTP id bm14-20020a05620a198e00b006b64f9c592bmr16500qkb.736.1660238596301; Thu, 11 Aug 2022 10:23:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1660238596; cv=none; d=google.com; s=arc-20160816; b=AS2GvliT7ZyQ1tMPRlbw64GxTR54ej/uyvqNghGmll+CJ7X695tBc7kUpYIY6ZW80R qDsD4FtonvXRDS9lE4VBdWrvoqsY65AbnA/7yKDKEKol8GAsNTSssM+OcjuOY4m7Z/jU 9q8T4sf2BG0mRfOpuI47iZ5pgWlQ2SXkkjPJ+gUC0j6tKIrvrvapo7hy+O4BLQeBvarI WQ1iCW+dhbmkzTUt0CiNOZaXznER/ZnMo/U1h2sgIzhiwikWOM8HgZqku8AflOXbvG2A s4jeq4SgLSMS7oK0y8Xj51sMtjvmKVkB5fgXsELL0nFhseNm0yPd0L/2QfrzDW7rgiRY z8AQ== 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:to:from :dkim-signature; bh=ulFcTK/UMwbyB6T+H2cmDJnndecNUSXMdH2zsNS8rWY=; b=jpYFV/JdJyNhBmF5y8g2xdBZHshGcaPx1aNPZzYqgOuTK9ycul1Hu0udoll9vCpSqP zy9m2iqDckcU6iUFEx+7f7Z4obG0HM6xnnq9mjrS7zgdjLPjlCBgURJkli60XGvxJpIA 3NTocVF7hhWjgqnEczNOlNAsa8w8XsrmRHTeB5/SRWGykk3Xd7MVBGhRU++TmX/QecQw 9K6ElmSP1pMPt6vpt7OdDq3837OrtY9/yW5slG9v/ON3jp4AQ+D+dLeJcnGGnPf+B9xj SbxfmM7z5SGNh52WaEQksgZ3KNObBmEUqKEmSDsvEECp0ECsh/M0XKdCiQ+RoPtRtDkI D6Fw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TW+iMmrx; 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 j11-20020a05621419cb00b0047660f10badsi2248581qvc.285.2022.08.11.10.23.16 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Thu, 11 Aug 2022 10:23:16 -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; dkim=pass header.i=@linaro.org header.s=google header.b=TW+iMmrx; 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]:44192 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oMBtq-0001yy-Ok for patch@linaro.org; Thu, 11 Aug 2022 13:23:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43212) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oMBnJ-0006qs-RI for qemu-devel@nongnu.org; Thu, 11 Aug 2022 13:16:29 -0400 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]:38639) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oMBnF-0000tv-5r for qemu-devel@nongnu.org; Thu, 11 Aug 2022 13:16:29 -0400 Received: by mail-wr1-x431.google.com with SMTP id bv3so22040172wrb.5 for ; Thu, 11 Aug 2022 10:16:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc; bh=ulFcTK/UMwbyB6T+H2cmDJnndecNUSXMdH2zsNS8rWY=; b=TW+iMmrxXvn4IUI5eXZS5bL4HRuuZsFJkGJbLKpM+WCfO3Roo/5brIAbqrOF5p9xiD pmCeUFh2IpbrS3zu4DGQuiet5wYvkQnSS95fdsqDlOsxz9A6dLNlNKDgXCM88QbPWqYu FaoZIDYPYxgta90s3c9pDAReZeDcMnALOgnpUo3p50Cos2OqIULVk+xJb6N3fR9grd8V GNQAOPoeVl7SW2/wQJUGMY+IOYzWszC8aUIIcxKEy3CmUzNpBRqpPttM1xGloAA206vY SmeFUTqS63uBP4NHn6Kojtbcz7LEG8y9ZGXoEp5asFNWT3ActGjwhnZWrz+f1XUBpMOc vEVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc; bh=ulFcTK/UMwbyB6T+H2cmDJnndecNUSXMdH2zsNS8rWY=; b=3mtSHkxGtxy9ngbkn63hKTEjdTn6Q64agkgEg43JtTCK9sL7BDGQ3ACdscRDLfqqFz 2eKPIUsqKMm50rClVRIyiMyCW5RL1Sxyl2KDHuUTY4Wr64Qq/LRJ1hq/Sb17lTfLlQd4 ffyVvDxZH4Ad1cH/Zbk5zuYRaSWPRnOPCnl6OfZQvRQjwKTdoki4EJNQJSUiQ/P9Da9+ Qh5mbsV3B75HxXJwl5SutfhxhEJRb0BoEJ5ZpWEvSsBWrFQbe3Ewr+BXMyqjhSLzKvUF q1YQriDDurwvM/ePN/sy1lOb2OaUmIMztkozLNpeK+M+9Ey47M146bBmeCpTX1RXNNcB r7JQ== X-Gm-Message-State: ACgBeo0T4Kzpelgjf/StTStkG+s77kK7dE7lqbTGHCiczuxwfO239dIg sDP/lXrE9aFSTv1L73NGeu9DRdLZaPNkuQ== X-Received: by 2002:a5d:47a1:0:b0:221:7e3b:b3b4 with SMTP id 1-20020a5d47a1000000b002217e3bb3b4mr17662wrb.694.1660238183645; Thu, 11 Aug 2022 10:16:23 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id b1-20020a05600c4e0100b003a2f6367049sm6633918wmq.48.2022.08.11.10.16.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Aug 2022 10:16:23 -0700 (PDT) From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Subject: [PATCH 03/10] target/arm: Don't mishandle count when enabling or disabling PMU counters Date: Thu, 11 Aug 2022 18:16:12 +0100 Message-Id: <20220811171619.1154755-4-peter.maydell@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220811171619.1154755-1-peter.maydell@linaro.org> References: <20220811171619.1154755-1-peter.maydell@linaro.org> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::431; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x431.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" The PMU cycle and event counter infrastructure design requires that operations on the PMU register fields are wrapped in pmu_op_start() and pmu_op_finish() calls (or their more specific pmmcntr and pmevcntr equivalents). This includes any changes to registers which affect whether the counter should be enabled or disabled, but we forgot to do this. The effect of this bug is that in sequences like: * disable the cycle counter (PMCCNTR) using the PMCNTEN register * write a value such as 0xfffff000 to the PMCCNTR * restart the counter by writing to PMCNTEN the value written to the cycle counter is corrupted, and it starts counting from the wrong place. (Essentially, we fail to record that the QEMU_CLOCK_VIRTUAL timestamp when the counter should be considered to have started counting is the point when PMCNTEN is written to enable the counter.) Add the necessary bracketing calls, so that updates to the various registers which affect whether the PMU is counting are handled correctly. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- target/arm/helper.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/target/arm/helper.c b/target/arm/helper.c index 87c89748954..7a367371921 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1079,6 +1079,14 @@ static CPAccessResult pmreg_access_ccntr(CPUARMState *env, return pmreg_access(env, ri, isread); } +/* + * Bits in MDCR_EL2 and MDCR_EL3 which pmu_counter_enabled() looks at. + * We use these to decide whether we need to wrap a write to MDCR_EL2 + * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. + */ +#define MDCR_EL2_PMU_ENABLE_BITS (MDCR_HPME | MDCR_HPMD | MDCR_HPMN) +#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME) + /* Returns true if the counter (pass 31 for PMCCNTR) should count events using * the current EL, security state, and register configuration. */ @@ -1432,15 +1440,19 @@ static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *ri) static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + pmu_op_start(env); value &= pmu_counter_mask(env); env->cp15.c9_pmcnten |= value; + pmu_op_finish(env); } static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + pmu_op_start(env); value &= pmu_counter_mask(env); env->cp15.c9_pmcnten &= ~value; + pmu_op_finish(env); } static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4681,7 +4693,39 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + /* + * Some MDCR_EL3 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op = (env->cp15.mdcr_el3 ^ value) & MDCR_EL3_PMU_ENABLE_BITS; + + if (pmu_op) { + pmu_op_start(env); + } env->cp15.mdcr_el3 = value & SDCR_VALID_MASK; + if (pmu_op) { + pmu_op_finish(env); + } +} + +static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Some MDCR_EL3 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op = (env->cp15.mdcr_el2 ^ value) & MDCR_EL2_PMU_ENABLE_BITS; + + if (pmu_op) { + pmu_op_start(env); + } + env->cp15.mdcr_el2 = value; + if (pmu_op) { + pmu_op_finish(env); + } } static const ARMCPRegInfo v8_cp_reginfo[] = { @@ -7669,6 +7713,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) ARMCPRegInfo mdcr_el2 = { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1, + .writefn = mdcr_el2_write, .access = PL2_RW, .resetvalue = pmu_num_counters(env), .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), };