From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 963732D8DDF for ; Tue, 28 Jul 2026 15:01:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785250865; cv=none; b=uHC4Gu3qa6NztlLwu+IGxV5TGdYjg2dz5r8h8f/wScRwUnN74ZvfMiqLzfeo+YnZXL3SxT+mJqpEA8pJLoeb0cP0RRE2g6CMsxVa2beywYfOuZ5L5NBTnGjI9sF7lyYnv5e+JXM1zTxZ1dVIoVaH8pX+bPRSSaVYpjDn7nrUSzk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785250865; c=relaxed/simple; bh=tWYx3RlfS4EQsZZeMRBuI8QTN8Bl+IHYZJ8zPrn14UU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GXJtFJ8W5Ze4ulTSAl8QOX3Dsg4bJCWqfusPYnE3rpFdYdelvwxUJFAdXsRC+P7sUBrwzSBGeupV6+2Z0B3rbUV6gYUcRqU+8TSOtf96KBCWjnavmxVypVt47Q04QDBT1E+QPy/VmJXh3FKwR/IQYjBc0ySJwVKmmQBU1QHH2/c= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=Iq3uHNdD; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Iq3uHNdD" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-496b7622a83so20906135e9.2 for ; Tue, 28 Jul 2026 08:01:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1785250861; x=1785855661; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=kyldpWdr+agt4WTnOhFl2wnppMTguRaoBzlozBAALhg=; b=Iq3uHNdD/FjVGVxP5Pjm/ov34jiRgksPTRPTGkj5nEoJy5yaiEAAq50JKrvI3/vWds yxXVPblKzixeCfTPrILOODBqPMfxJEDjIwzkciKGY15QpXV7+2DMxdZY1bN8OfH2Jkv6 /hMg3ZgJYI3+9eiBW/6oXGDzLLkYKgRC8Rnl5LSuhhkPgmeJBh4SntgrC6lt6ijjLChe /y7/MZRTItU6ZU1ApP/ltMUkuH8gHYDBYBiIZAkbTzGUTwmzkWkQ+UWRg3M6Rg+x3avi 1Vjy/vEX2oVr+pwucM9FSqayk8GZD2IcDG0Nloo9x1yG5B48xAh0we2dGlLwCI9chCPw J/Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785250861; x=1785855661; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=kyldpWdr+agt4WTnOhFl2wnppMTguRaoBzlozBAALhg=; b=Jm0DC38HUL9WzzgLkWkAa/t075LpPKCMlkXant8d9am2YhhrQaZEyE1D6dLL+79gGj kt4a216ZkvupeT6C8u//FMUXos5sxNVwzzkFxTh4oqC3tuwFvGZmbx422fNx/E66Zywc 7RbWIaiA7YqOKYsh5EeOFV9T3ZUDfjIVQduErc5rle8bRt9sBQQl4ndPWxRUEuVfMAeF d/CgWpuy8DHJvbI9vyIyG41L35INhlUzG1fATuZunlUXZ/Z3M+oSzPo1PCHlAOk+nNak EfEzmFdvbS/6s+lzWKswSg4pkJO1r0xJkWjCxRMAyIhXRR7KvKyVduBuId6gQxNmHZT1 /v0Q== X-Forwarded-Encrypted: i=1; AHgh+RqEfah7dHfHTi00O2+v7AFE3pli/eadbTZ0Qro1FMUB9sZu+nM8JhxAz3BjdaZs0K3gLHeHhpesSrIRXF8=@vger.kernel.org X-Gm-Message-State: AOJu0YzxZXKA5NxYGraErb+wGfcwRerhhpfi9LVH2cjU7Mv9KjgUl13g DhnKw0SgNWbEdOtiO1Qll0RyV39lpLDCjFbtVHym62yMgZmyz82D4aNOt2tGyNXqH6k= X-Gm-Gg: AR+sD12r5dVG4jw+bfCj2XysszrsksrEK78TLL1ehgr+S+TG714rZiCZURlOPHdwQXx xORiauu+56nmGMlY4LohpBmsQiRxQBEmo2coA6MRRP84+WfdgH3d12vT5xGiT+L7VWP+iMjHCG0 MBz5H9DAk29Cu1NTvR9ROGj7jxzHDKRZ2jPa/jd5dXOAH1WPlVpBHbeVWVppzGr7SW6h31Iw9y4 fd1n4zQkTFECmvbg+02DjXvNtoQVv6K9Dfkan+6Uwa61zn6QxpmjcnZQgE9ppuAVG7VA10UNuKT bYO26q4Yc8w6svecJpKejiwAS5lE7twelq6gOMbM8Jg9JOgpXiZFXDMEQ0UojrGGUh36spdhCR6 Hbwbi7HsAQ72QTUBpqzqfMXM/7O91fgIlbGstiC8KX2zgmSKfE3fQGkIJn2tUbv3jy69IARqo/D LYTV3XOnQ= X-Received: by 2002:a05:600c:4703:b0:493:fa66:4861 with SMTP id 5b1f17b1804b1-496c6565dfamr35119935e9.25.1785250861215; Tue, 28 Jul 2026 08:01:01 -0700 (PDT) Received: from [192.168.1.3] ([37.18.141.193]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47f85c52fa9sm61036324f8f.20.2026.07.28.08.01.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Jul 2026 08:01:00 -0700 (PDT) From: James Clark Date: Tue, 28 Jul 2026 16:00:13 +0100 Subject: [PATCH v3 1/8] coresight: tmc-etr: Don't stop Perf cleanup for active sysfs reads Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260728-james-cs-multiple-per-threads-v3-1-6aee7579f1dc@linaro.org> References: <20260728-james-cs-multiple-per-threads-v3-0-6aee7579f1dc@linaro.org> In-Reply-To: <20260728-james-cs-multiple-per-threads-v3-0-6aee7579f1dc@linaro.org> To: Suzuki K Poulose , Mike Leach , Leo Yan , Suyash Mahar , Yeoreum Yun Cc: Greg Kroah-Hartman , Qi Liu , Junhao He , coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, James Clark , Jonathan Cameron , sashiko-bot X-Mailer: b4 0.14.0 The linked fixes commit deliberately allows reads of an old sysfs buffer while in Perf mode because they are separate software buffers. However it didn't modify tmc_disable_etr_sink() to match this relaxation. The result is that when a Perf event ends while the sysfs buffer is being read, clean up will be skipped. Fix it by ignoring the sysfs_reading flag unless the active session is a sysfs one. When sysfs and Perf share the same memory in ETR_MODE_RESRV mode, a new Perf session needs to overwrite an old inactive sysfs session by zeroing len. This avoids sysfs from reading stale data because it has a separate set of offsets in its etr_buf struct, even if that's backed by the same memory as the Perf one. Reported-by: sashiko-bot Fixes: cad5f8d399bb ("coresight: tmc-etr: Relax collection of trace from sysfs mode") Signed-off-by: James Clark --- drivers/hwtracing/coresight/coresight-tmc-etf.c | 16 ++++---- drivers/hwtracing/coresight/coresight-tmc-etr.c | 50 +++++++++++++++++++++---- drivers/hwtracing/coresight/coresight-tmc.h | 7 +++- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 8882b1c4cdc0..3836063031d7 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -198,7 +198,7 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) raw_spin_lock_irqsave(&drvdata->spinlock, flags); } - if (drvdata->reading) { + if (drvdata->sysfs_reading) { ret = -EBUSY; goto out; } @@ -259,7 +259,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, raw_spin_lock_irqsave(&drvdata->spinlock, flags); do { ret = -EINVAL; - if (drvdata->reading) + if (drvdata->sysfs_reading) break; /* * No need to continue if the ETB/ETF is already operated @@ -337,7 +337,7 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + if (drvdata->sysfs_reading) { raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -371,7 +371,7 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, bool first_enable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + if (drvdata->sysfs_reading) { raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -401,7 +401,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, bool last_disable = false; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + if (drvdata->sysfs_reading) { raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return; } @@ -718,7 +718,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + if (drvdata->sysfs_reading) { ret = -EBUSY; goto out; } @@ -746,7 +746,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) __tmc_etb_disable_hw(drvdata); } - drvdata->reading = true; + drvdata->sysfs_reading = true; out: raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -797,7 +797,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) drvdata->buf = NULL; } - drvdata->reading = false; + drvdata->sysfs_reading = false; raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); /* diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 361a433e6f0c..be0bbe036d02 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1151,7 +1151,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, * starts at anywhere in the buffer, depending on the RRP, we adjust the * @len returned to handle buffer wrapping around. * - * We are protected here by drvdata->reading != 0, which ensures the + * We are protected here by drvdata->sysfs_reading != 0, which ensures the * sysfs_buf stays alive. */ ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata, @@ -1268,7 +1268,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) raw_spin_lock_irqsave(&drvdata->spinlock, flags); } - if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) { + if (drvdata->sysfs_reading || coresight_get_mode(csdev) == CS_MODE_PERF) { ret = -EBUSY; goto out; } @@ -1732,6 +1732,16 @@ tmc_update_etr_buffer(struct coresight_device *csdev, return size; } +static bool tmc_perf_sysfs_shared(struct tmc_drvdata *drvdata, + struct etr_buf *perf_buf) +{ + /* In ETR_MODE_RESRV mode, sysfs and Perf share the same memory. */ + return perf_buf && + drvdata->sysfs_buf && + drvdata->sysfs_buf->mode == ETR_MODE_RESRV && + perf_buf->mode == ETR_MODE_RESRV; +} + static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, struct coresight_path *path) { @@ -1772,6 +1782,18 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, goto unlock_out; } + /* + * Don't use if it's shared and being read by sysfs. Sysfs may only + * start reading (the cleared zero length buffer) after the first + * tmc_enable_etr_sink_perf(), which changes the result of this check, + * so it should only be done once. + */ + if ((drvdata->sysfs_reading && + tmc_perf_sysfs_shared(drvdata, etr_perf->etr_buf))) { + rc = -EBUSY; + goto unlock_out; + } + rc = tmc_etr_enable_hw(drvdata, etr_perf->etr_buf); if (!rc) { /* Associate with monitored process. */ @@ -1779,6 +1801,10 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, coresight_set_mode(csdev, CS_MODE_PERF); drvdata->perf_buf = etr_perf->etr_buf; csdev->refcnt++; + + /* A new Perf session clears an old sysfs one if the buffer is shared */ + if (tmc_perf_sysfs_shared(drvdata, etr_perf->etr_buf)) + drvdata->sysfs_buf->len = 0; } unlock_out: @@ -1807,7 +1833,13 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + /* + * In SYSFS mode an active read is responsible for disabling and + * enabling HW. Otherwise in Perf mode, an old inactive sysfs session + * may be read which Perf should ignore. + */ + if (drvdata->sysfs_reading && + coresight_get_mode(csdev) == CS_MODE_SYSFS) { raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); return -EBUSY; } @@ -1928,14 +1960,16 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) return -EINVAL; raw_spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { + if (drvdata->sysfs_reading) { ret = -EBUSY; goto out; } /* - * We can safely allow reads even if the ETR is operating in PERF mode, - * since the sysfs session is captured in mode specific data. + * We can safely allow reads even if the ETR is operating in PERF mode + * since sysfs has it's own buffer. For ETR_MODE_RESRV the buffers are + * shared but Perf discards sysfs data before starting a session to + * avoid corruption. * If drvdata::sysfs_data is NULL the trace data has been read already. */ if (!drvdata->sysfs_buf) { @@ -1947,7 +1981,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) __tmc_etr_disable_hw(drvdata); - drvdata->reading = true; + drvdata->sysfs_reading = true; out: raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); @@ -1982,7 +2016,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) drvdata->sysfs_buf = NULL; } - drvdata->reading = false; + drvdata->sysfs_reading = false; raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); /* Free allocated memory out side of the spinlock */ diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h index 319a354ede9f..dc1a57ab8011 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.h +++ b/drivers/hwtracing/coresight/coresight-tmc.h @@ -221,7 +221,10 @@ struct tmc_resrv_buf { * @pid: Process ID of the process that owns the session that is using * this component. For example this would be the pid of the Perf * process. - * @reading: buffer's in the reading through "/dev/xyz.tmc" entry + * @sysfs_reading: Sysfs mode buffer is being read through "/dev/xyz.tmc" entry. + * Note: ETR has a separate software buffer for the two modes so + * the device can still be read while in Perf mode if there is a + * previous inactive sysfs session. * @stop_on_flush: Stop on flush trigger user configuration. * @buf: Snapshot of the trace data for ETF/ETB. * @etr_buf: details of buffer used in TMC-ETR @@ -255,7 +258,7 @@ struct tmc_drvdata { struct miscdevice crashdev; raw_spinlock_t spinlock; pid_t pid; - bool reading; + bool sysfs_reading; bool stop_on_flush; union { char *buf; /* TMC ETB */ -- 2.34.1