Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp524391pxb; Wed, 27 Jan 2021 13:52:53 -0800 (PST) X-Google-Smtp-Source: ABdhPJzQ0qC0WiIoERpNaugto1mv8zMcZGe8Om1fasjKBn++gaCE4uVPojN/0e1dgLMPYgw8aRhq X-Received: by 2002:a17:906:cce9:: with SMTP id ot41mr4010435ejb.61.1611784372974; Wed, 27 Jan 2021 13:52:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611784372; cv=none; d=google.com; s=arc-20160816; b=oqbbbnYUkNs04swqlNlbIcwnSqulfiBYcXks8Xc/F+caa09qsEfsIZZjSjpBnXl1nr 7fE1AuueQrStIJhr6WIWnnq7QLG6+fgFMdXqxNRCkm7lXfP++Ax2sGtiyCMLBfMCi4Nk x+Ag9xETjq1D/yJoLruVZoWM+I1IXO404sskLllHhuCDznzY08XSFBbFlEfE7+W/W6KE /5L3AiuVKl/X8VlchjTRwh2fDYYcj8rfxOoU2ZdQ5TXQ5nQYba/QK68z3BHi8YXAGm8c tRpGBKe5BrL3qfOp35EMbemoABjhQHDqKLt///RYj3yIA1W5MrjiDNbIxtJd8lfFNRBB ChyQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=roA7uvN4lD6oKmNVZD2TgGT46HN0+6Xh07yDAwolM4g=; b=Bx5TtSR4bCDBb5FAv27gZvdRbgJtzN4/iiiK1bgrDfHHddDUG+Ry3O84pVMgpAtylJ bsG0/OpUsx2A8rb9sWXtJC5zkMEtlNZ+mLYLyviHR+K7ahZ1vguvx6+SRiiuXR2A9tmB DzBvigLJR+7GiBQywiSaPlR2h0CGjbQx4Fo0+8NTg0CgMm46IjHJssiEEIjTr8C+KDLs eSFIRx4lGzU0aba5mPx2LbkytT3bMFNClSqKGeJEK9vnyP2+HVOeI9RAXYHC2MIgVgBn OuaDGFG6BGXW0r6yWKJWCpBJImPQthIDGM4YDk4mWsOHgkcOz3qe0iat6sJdAqK7eQFs 82LA== 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 h17si1691868edv.235.2021.01.27.13.52.26; Wed, 27 Jan 2021 13:52:52 -0800 (PST) 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 S235568AbhA0Jtf (ORCPT + 99 others); Wed, 27 Jan 2021 04:49:35 -0500 Received: from foss.arm.com ([217.140.110.172]:32950 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231951AbhA0I7I (ORCPT ); Wed, 27 Jan 2021 03:59:08 -0500 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 5FA911480; Wed, 27 Jan 2021 00:55:46 -0800 (PST) Received: from p8cg001049571a15.arm.com (unknown [10.163.91.246]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7BF853F66B; Wed, 27 Jan 2021 00:55:43 -0800 (PST) From: Anshuman Khandual To: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org Cc: mathieu.poirier@linaro.org, suzuki.poulose@arm.com, mike.leach@linaro.org, lcherian@marvell.com, linux-kernel@vger.kernel.org, Anshuman Khandual , Leo Yan Subject: [PATCH V3 07/14] coresight: etm-perf: Handle stale output handles Date: Wed, 27 Jan 2021 14:25:31 +0530 Message-Id: <1611737738-1493-8-git-send-email-anshuman.khandual@arm.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1611737738-1493-1-git-send-email-anshuman.khandual@arm.com> References: <1611737738-1493-1-git-send-email-anshuman.khandual@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Suzuki K Poulose The context associated with an ETM for a given perf event includes : - handle -> the perf output handle for the AUX buffer. - the path for the trace components - the buffer config for the sink. The path and the buffer config are part of the "aux_priv" data (etm_event_data) setup by the setup_aux() callback, and made available via perf_get_aux(handle). Now with a sink supporting IRQ, the sink could "end" an output handle when the buffer reaches the programmed limit and would try to restart a handle. This could fail if there is not enough space left the AUX buffer (e.g, the userspace has not consumed the data). This leaves the "handle" disconnected from the "event" and also the "perf_get_aux()" cleared. This all happens within the sink driver, without the etm_perf driver being aware. Now when the event is actually stopped, etm_event_stop() will need to access the "event_data". But since the handle is not valid anymore, we loose the information to stop the "trace" path. So, we need a reliable way to access the etm_event_data even when the handle may not be active. This patch replaces the per_cpu handle array with a per_cpu context for the ETM, which tracks the "handle" as well as the "etm_event_data". The context notes the etm_event_data at etm_event_start() and clears it at etm_event_stop(). This makes sure that we don't access a stale "etm_event_data" as we are guaranteed that it is not freed by free_aux() as long as the event is active and tracing, also provides us with access to the critical information needed to wind up a session even in the absence of an active output_handle. This is not an issue for the legacy sinks as none of them supports an IRQ and is centrally handled by the etm-perf. Cc: Mathieu Poirier Cc: Anshuman Khandual Cc: Leo Yan Cc: Mike Leach Signed-off-by: Suzuki K Poulose Signed-off-by: Anshuman Khandual --- drivers/hwtracing/coresight/coresight-etm-perf.c | 45 +++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index eb9e7e9..a3977b0 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -24,7 +24,26 @@ static struct pmu etm_pmu; static bool etm_perf_up; -static DEFINE_PER_CPU(struct perf_output_handle, ctx_handle); +/* + * An ETM context for a running event includes the perf aux handle + * and aux_data. For ETM, the aux_data (etm_event_data), consists of + * the trace path and the sink configuration. The event data is accessible + * via perf_get_aux(handle). However, a sink could "end" a perf output + * handle via the IRQ handler. And if the "sink" encounters a failure + * to "begin" another session (e.g due to lack of space in the buffer), + * the handle will be cleared. Thus, the event_data may not be accessible + * from the handle when we get to the etm_event_stop(), which is required + * for stopping the trace path. The event_data is guaranteed to stay alive + * until "free_aux()", which cannot happen as long as the event is active on + * the ETM. Thus the event_data for the session must be part of the ETM context + * to make sure we can disable the trace path. + */ +struct etm_ctxt { + struct perf_output_handle handle; + struct etm_event_data *event_data; +}; + +static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt); static DEFINE_PER_CPU(struct coresight_device *, csdev_src); /* ETMv3.5/PTM's ETMCR is 'config' */ @@ -332,7 +351,8 @@ static void etm_event_start(struct perf_event *event, int flags) { int cpu = smp_processor_id(); struct etm_event_data *event_data; - struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle); + struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); + struct perf_output_handle *handle = &ctxt->handle; struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); struct list_head *path; @@ -374,6 +394,8 @@ static void etm_event_start(struct perf_event *event, int flags) if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF)) goto fail_disable_path; + /* Save the event_data for this ETM */ + ctxt->event_data = event_data; out: return; @@ -392,13 +414,20 @@ static void etm_event_stop(struct perf_event *event, int mode) int cpu = smp_processor_id(); unsigned long size; struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); - struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle); - struct etm_event_data *event_data = perf_get_aux(handle); + struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt); + struct perf_output_handle *handle = &ctxt->handle; + struct etm_event_data *event_data = ctxt->event_data; struct list_head *path; + /* Clear the event_data as this ETM is stopping the trace. */ + ctxt->event_data = NULL; if (event->hw.state == PERF_HES_STOPPED) return; + /* We must have a valid event_data for a running event */ + if (WARN_ON(!event_data)) + return; + if (!csdev) return; @@ -416,7 +445,13 @@ static void etm_event_stop(struct perf_event *event, int mode) /* tell the core */ event->hw.state = PERF_HES_STOPPED; - if (mode & PERF_EF_UPDATE) { + /* + * If the handle is not bound to an event anymore + * (e.g, the sink driver was unable to restart the + * handle due to lack of buffer space), we don't + * have to do anything here. + */ + if (handle->event && (mode & PERF_EF_UPDATE)) { if (WARN_ON_ONCE(handle->event != event)) return; -- 2.7.4