Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp45243pxb; Thu, 14 Oct 2021 23:47:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxL00mnguiKxuD6IWDV/mh9tF/weBjcUGUEE4j3CppG/3ZbR2h9V98/+v+ku9yoNx9oBelh X-Received: by 2002:a62:8f8e:0:b0:44c:f130:9291 with SMTP id n136-20020a628f8e000000b0044cf1309291mr9951184pfd.19.1634280454655; Thu, 14 Oct 2021 23:47:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634280454; cv=none; d=google.com; s=arc-20160816; b=Sg6i3swqcHgefgvU/5rtE3Nx/Yh+VSb2mdqawQpUgWJA6OR/E3O9YBsj0ZrDrTtX1X bdzQ+fHbKB87ZXkucnGTWjDqtN/VEd3ATGKI+Dk/2r1INThWflechbYt3bYcKe62aB7S YzCPwS0hTQCrrL2pp1r4ERJu/arSbGPXmElJ/I310AJs8OxBRFUXS4bZdAcYiUl26pUX llFGbkb4KG0pyVd1n7ySqYwtOxcNBzwuzRO2kAou4tzaDEJw0IbfI588tP60JajRMceS H/6iFuK8r/szDHa6ce7ux6Xh51qSDvzmUdBiCvcacYJfEV/PsiXoJFBkAjFJRt2mZvPz dJSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=FnWPkLMJMKEqZlK6X4ugkJW7j1S2Gb4gbfZxuP0AUo4=; b=L/EV0XHKjOHkdocYD+JF1H1giAiahzskzOgwgooKw8TKAln/J20BYoTtRsDioRWeQk u/9Wed6MNsC1tiwng5JJENmG52Af1xXhdsDGaeBQ+/9jMxPuoy9gvatRpdNIM4WMA8wK OQABljxM9XwxjWSa2+Gc1cGbkgVQuK6EGe7MpR6aX7xLnsTh7Pe3cLD8NAeOR1Zk/ghq JgVn/Q5kh62IGeLfcrbJ6bSfenBydGb7wR/09/gW+vHbqELqQaYAoJRwJt4uRoYhRqz7 zP96LK6mntoYAafygXpsS8iJysFPBZQfoG7HNI2kR/RiicW6KbPIFW2MT3aC9uLb1dop JnUQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g16si7522178pfj.10.2021.10.14.23.46.09; Thu, 14 Oct 2021 23:47:34 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234295AbhJNWeO (ORCPT + 99 others); Thu, 14 Oct 2021 18:34:14 -0400 Received: from foss.arm.com ([217.140.110.172]:32806 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234296AbhJNWeD (ORCPT ); Thu, 14 Oct 2021 18:34:03 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C09A5150C; Thu, 14 Oct 2021 15:31:57 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 55F953F694; Thu, 14 Oct 2021 15:31:56 -0700 (PDT) From: Suzuki K Poulose To: will@kernel.org, mathieu.poirier@linaro.org Cc: catalin.marinas@arm.com, anshuman.khandual@arm.com, mike.leach@linaro.org, leo.yan@linaro.org, maz@kernel.org, coresight@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Suzuki K Poulose Subject: [PATCH v5 13/15] coresight: trbe: Work around write to out of range Date: Thu, 14 Oct 2021 23:31:23 +0100 Message-Id: <20211014223125.2605031-14-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20211014223125.2605031-1-suzuki.poulose@arm.com> References: <20211014223125.2605031-1-suzuki.poulose@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org TRBE implementations affected by Arm erratum (2253138 or 2224489), could write to the next address after the TRBLIMITR.LIMIT, instead of wrapping to the TRBBASER. This implies that the TRBE could potentially corrupt : - A page used by the rest of the kernel/user (if the LIMIT = end of perf ring buffer) - A page within the ring buffer, but outside the driver's range. [head, head + size]. This may contain some trace data, may be consumed by the userspace. We workaround this erratum by : - Making sure that there is at least an extra PAGE space left in the TRBE's range than we normally assign. This will be additional to other restrictions (e.g, the TRBE alignment for working around TRBE_WORKAROUND_OVERWRITE_IN_FILL_MODE, where there is a minimum of PAGE_SIZE. Thus we would have 2 * PAGE_SIZE) - Adjust the LIMIT to leave the last PAGE_SIZE out of the TRBE's allowed range (i.e, TRBEBASER...TRBLIMITR.LIMIT), by : TRBLIMITR.LIMIT -= PAGE_SIZE Cc: Anshuman Khandual Cc: Mathieu Poirier Cc: Mike Leach Cc: Leo Yan Reviewed-by: Mathieu Poirier Signed-off-by: Suzuki K Poulose --- drivers/hwtracing/coresight/coresight-trbe.c | 63 +++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 5fb9f49eab33..eca2e7e94079 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -90,9 +90,11 @@ struct trbe_buf { * - Streamlined detection of erratum across the system */ #define TRBE_WORKAROUND_OVERWRITE_FILL_MODE 0 +#define TRBE_WORKAROUND_WRITE_OUT_OF_RANGE 1 static int trbe_errata_cpucaps[] = { [TRBE_WORKAROUND_OVERWRITE_FILL_MODE] = ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE, + [TRBE_WORKAROUND_WRITE_OUT_OF_RANGE] = ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE, -1, /* Sentinel, must be the last entry */ }; @@ -160,6 +162,11 @@ static inline bool trbe_may_overwrite_in_fill_mode(struct trbe_cpudata *cpudata) return trbe_has_erratum(cpudata, TRBE_WORKAROUND_OVERWRITE_FILL_MODE); } +static inline bool trbe_may_write_out_of_range(struct trbe_cpudata *cpudata) +{ + return trbe_has_erratum(cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE); +} + static int trbe_alloc_node(struct perf_event *event) { if (event->cpu == -1) @@ -305,7 +312,21 @@ static unsigned long trbe_snapshot_offset(struct perf_output_handle *handle) static u64 trbe_min_trace_buf_size(struct perf_output_handle *handle) { - return TRBE_TRACE_MIN_BUF_SIZE; + u64 size = TRBE_TRACE_MIN_BUF_SIZE; + struct trbe_buf *buf = etm_perf_sink_config(handle); + struct trbe_cpudata *cpudata = buf->cpudata; + + /* + * When the TRBE is affected by an erratum that could make it + * write to the next "virtually addressed" page beyond the LIMIT. + * We need to make sure there is always a PAGE after the LIMIT, + * within the buffer. Thus we ensure there is at least an extra + * page than normal. With this we could then adjust the LIMIT + * pointer down by a PAGE later. + */ + if (trbe_may_write_out_of_range(cpudata)) + size += PAGE_SIZE; + return size; } /* @@ -611,6 +632,17 @@ static unsigned long trbe_get_trace_size(struct perf_output_handle *handle, /* * If the TRBE has wrapped around the write pointer has * wrapped and should be treated as limit. + * + * When the TRBE is affected by TRBE_WORKAROUND_WRITE_OUT_OF_RANGE, + * it may write upto 64bytes beyond the "LIMIT". The driver already + * keeps a valid page next to the LIMIT and we could potentially + * consume the trace data that may have been collected there. But we + * cannot be really sure it is available, and the TRBPTR may not + * indicate the same. Also, affected cores are also affected by another + * erratum which forces the PAGE_SIZE alignment on the TRBPTR, and thus + * could potentially pad an entire PAGE_SIZE - 64bytes, to get those + * 64bytes. Thus we ignore the potential triggering of the erratum + * on WRAP and limit the data to LIMIT. */ if (wrap) write = get_trbe_limit_pointer(); @@ -864,6 +896,35 @@ static int trbe_apply_work_around_before_enable(struct trbe_buf *buf) buf->trbe_write += TRBE_WORKAROUND_OVERWRITE_FILL_MODE_SKIP_BYTES; } + /* + * TRBE_WORKAROUND_WRITE_OUT_OF_RANGE could cause the TRBE to write to + * the next page after the TRBLIMITR.LIMIT. For perf, the "next page" + * may be: + * - The page beyond the ring buffer. This could mean, TRBE could + * corrupt another entity (kernel / user) + * - A portion of the "ring buffer" consumed by the userspace. + * i.e, a page outisde [head, head + size]. + * + * We work around this by: + * - Making sure that we have at least an extra space of PAGE left + * in the ring buffer [head, head + size], than we normally do + * without the erratum. See trbe_min_trace_buf_size(). + * + * - Adjust the TRBLIMITR.LIMIT to leave the extra PAGE outside + * the TRBE's range (i.e [TRBBASER, TRBLIMITR.LIMI] ). + */ + if (trbe_has_erratum(buf->cpudata, TRBE_WORKAROUND_WRITE_OUT_OF_RANGE)) { + s64 space = buf->trbe_limit - buf->trbe_write; + /* + * We must have more than a PAGE_SIZE worth space in the proposed + * range for the TRBE. + */ + if (WARN_ON(space <= PAGE_SIZE || + !IS_ALIGNED(buf->trbe_limit, PAGE_SIZE))) + return -EINVAL; + buf->trbe_limit -= PAGE_SIZE; + } + return 0; } -- 2.25.4