From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.0 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAA3AC433E0 for ; Wed, 1 Jul 2020 07:20:44 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5FDBE206BE for ; Wed, 1 Jul 2020 07:20:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Dh2p+FP7"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="cisUn+93" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5FDBE206BE Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=+rDZlMv1Jdnp4QzrOfVFFfp99wUGrRnSQyS+7Kz1fJc=; b=Dh2p+FP7JIKLc0K3I2gaDuCBY FMYZzV1fxgHFYxWVB1Yoyeawn/o2BWkXES9KArKAcTPXfgA6xG3zF7YfhSd2AnKQwLu9jZhTvnOlt zgexwzbNrAP2jaP1K0rRxnUePukM8vbQrLX9rIj4ln6KBEYYMufImFAEgoPO4qS1/KpZb6+/xqf0D AA/yQm2KtLH0u1YqaPBJMwSOGudndesZIMeGBclFzl5g5A2dWsW1uB1Srv51RaZtFbnx4Cb8fXfF/ pL8dk6jjzdUpgYH/DftOVh6w1KqH22xhcmaBHYj+wuMJSjYu6J5qEpp92SOC5SJ/PIgJTwY2G/AxK 0woKOiu8Q==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jqX10-0003CC-0g; Wed, 01 Jul 2020 07:18:42 +0000 Received: from mail29.static.mailgun.info ([104.130.122.29]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jqWz6-0001pX-WA for linux-arm-kernel@lists.infradead.org; Wed, 01 Jul 2020 07:16:48 +0000 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1593587806; h=Content-Transfer-Encoding: MIME-Version: References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=wdAABJf6LQ9lJTzHImLBNqOMCfSovp9cfW6HnzVR/TY=; b=cisUn+932zVt9ZbKZxmyk2tzYl9lIQ9jkqgOrloa5c50SeDAbU6N2FSqQO5paR1Bxs+HoFBr +/nOU5hTfMiy0FKd2i6LR2f0ihcQGuqMhtvxg0ok/dHmy4k8pEZz8j/eEYwRkq8/aysNqz8z WYnJgllqIN7A5Lwd1z+4RFUUGRg= X-Mailgun-Sending-Ip: 104.130.122.29 X-Mailgun-Sid: WyJiYzAxZiIsICJsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmciLCAiYmU5ZTRhIl0= Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by smtp-out-n16.prod.us-east-1.postgun.com with SMTP id 5efc38530206ad41d1f7db84 (version=TLS1.2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256); Wed, 01 Jul 2020 07:16:35 GMT Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 1EFB2C433B6; Wed, 1 Jul 2020 07:16:35 +0000 (UTC) Received: from tingweiz-gv.qualcomm.com (unknown [180.166.53.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: tingwei) by smtp.codeaurora.org (Postfix) with ESMTPSA id D077BC433AD; Wed, 1 Jul 2020 07:16:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org D077BC433AD Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=none smtp.mailfrom=tingwei@codeaurora.org From: Tingwei Zhang To: Mathieu Poirier , Suzuki K Poulose Subject: [PATCH v1 21/21] coresight: perf: clean up perf event on device unregister path Date: Wed, 1 Jul 2020 15:14:27 +0800 Message-Id: <20200701071427.10477-22-tingwei@codeaurora.org> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20200701071427.10477-1-tingwei@codeaurora.org> References: <20200701071427.10477-1-tingwei@codeaurora.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200701_031647_157469_56D6E1CE X-CRM114-Status: GOOD ( 27.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: tsoni@codeaurora.org, Sai Prakash Ranjan , Kim Phillips , Mao Jinlong , Alexander Shishkin , Greg Kroah-Hartman , coresight@lists.linaro.org, Randy Dunlap , Mian Yousaf Kaukab , Russell King , Tingwei Zhang , Leo Yan , linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When coresight unreigster is called, check whether this device is used by any perf event. Stop and release that perf event to avoid accessing removed coresight device data later. Signed-off-by: Tingwei Zhang --- drivers/hwtracing/coresight/coresight-core.c | 7 + .../hwtracing/coresight/coresight-etm-perf.c | 157 +++++++++++++++++- .../hwtracing/coresight/coresight-etm-perf.h | 2 + drivers/hwtracing/coresight/coresight-priv.h | 4 +- kernel/events/core.c | 1 + 5 files changed, 164 insertions(+), 7 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index 55ff45a9729e..8261d527c8fb 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -1475,9 +1475,16 @@ void coresight_unregister(struct coresight_device *csdev) mutex_lock(&coresight_mutex); coresight_disable_with(csdev); + /* + * Disable all perf events that have trace path related to csdev. + * Deny any request to create new trace path. + */ + etm_perf_disable_with(csdev); /* Remove references of that device in the topology */ coresight_remove_conns(csdev); coresight_release_platform_data(csdev->pdata); + /* New trace path in perf can be established */ + etm_perf_disable_done(); mutex_unlock(&coresight_mutex); device_unregister(&csdev->dev); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index b466162d8254..95aeb1ca807c 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -23,9 +23,22 @@ static struct pmu etm_pmu; static bool etm_perf_up; +/* Count for on going tasks which are changing coresight topology */ +static atomic_t *cs_updating_cnt; + +static DEFINE_MUTEX(cs_path_mutex); static DEFINE_PER_CPU(struct perf_output_handle, ctx_handle); static DEFINE_PER_CPU(struct coresight_device *, csdev_src); +static DEFINE_PER_CPU(bool, csdev_src_removing); + +struct ev_data { + struct etm_event_data *event_data; + struct list_head link; +}; + +/* List for all events */ +static LIST_HEAD(ev_list); /* ETMv3.5/PTM's ETMCR is 'config' */ PMU_FORMAT_ATTR(cycacc, "config:" __stringify(ETM_OPT_CYCACC)); @@ -64,6 +77,8 @@ static const struct attribute_group *etm_pmu_attr_groups[] = { NULL, }; +static void update_cs_cfg(void *ignored); + static inline struct list_head ** etm_event_cpu_path_ptr(struct etm_event_data *data, int cpu) { @@ -135,15 +150,35 @@ static void free_sink_buffer(struct etm_event_data *event_data) cpu = cpumask_first(mask); sink = coresight_get_sink(etm_event_cpu_path(event_data, cpu)); sink_ops(sink)->free_buffer(event_data->snk_config); + event_data->snk_config = NULL; } -static void free_event_data(struct work_struct *work) +static void del_event_from_list(struct etm_event_data *event_data, + struct ev_data *del_ev_data) +{ + struct ev_data *ev_data = NULL; + struct ev_data *ev_data_next = NULL; + + if (IS_ERR_OR_NULL(del_ev_data)) { + list_for_each_entry_safe(ev_data, ev_data_next, &ev_list, link) { + if (ev_data->event_data == event_data) { + del_ev_data = ev_data; + break; + } + } + } + if (!(IS_ERR_OR_NULL(del_ev_data))) { + list_del(&del_ev_data->link); + kfree(del_ev_data); + } +} + +static void _free_event_data(struct etm_event_data *event_data, + struct ev_data *ev_data) { int cpu; cpumask_t *mask; - struct etm_event_data *event_data; - event_data = container_of(work, struct etm_event_data, work); mask = &event_data->mask; /* Free the sink buffers, if there are any */ @@ -159,6 +194,20 @@ static void free_event_data(struct work_struct *work) } free_percpu(event_data->path); + del_event_from_list(event_data, ev_data); +} + +static void free_event_data(struct work_struct *work) +{ + struct etm_event_data *event_data; + + event_data = container_of(work, struct etm_event_data, work); + + mutex_lock(&cs_path_mutex); + if (event_data->snk_config) + _free_event_data(event_data, NULL); + mutex_unlock(&cs_path_mutex); + kfree(event_data); } @@ -212,7 +261,10 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, cpumask_t *mask; struct coresight_device *sink; struct etm_event_data *event_data = NULL; + struct ev_data *ev_data; + if (atomic_read(cs_updating_cnt)) + return NULL; event_data = alloc_event_data(cpu); if (!event_data) return NULL; @@ -231,6 +283,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, mask = &event_data->mask; + mutex_lock(&cs_path_mutex); /* * Setup the path for each CPU in a trace session. We try to build * trace path for each CPU in the mask. If we don't find an ETM @@ -282,10 +335,19 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, if (!event_data->snk_config) goto err; + ev_data = kzalloc(sizeof(struct ev_data), GFP_KERNEL); + if (!ev_data) { + *etm_event_cpu_path_ptr(event_data, cpu) = NULL; + goto err; + } + ev_data->event_data = event_data; + list_add(&ev_data->link, &ev_list); + mutex_unlock(&cs_path_mutex); out: return event_data; err: + mutex_unlock(&cs_path_mutex); etm_free_aux(event_data); event_data = NULL; goto out; @@ -299,7 +361,7 @@ static void etm_event_start(struct perf_event *event, int flags) struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu); struct list_head *path; - if (!csdev) + if (!csdev || atomic_read(cs_updating_cnt)) goto fail; /* @@ -310,6 +372,9 @@ static void etm_event_start(struct perf_event *event, int flags) if (!event_data) goto fail; + if (!event_data->snk_config) + goto fail; + path = etm_event_cpu_path(event_data, cpu); /* We need a sink, no need to continue without one */ sink = coresight_get_sink(path); @@ -391,7 +456,7 @@ static int etm_event_add(struct perf_event *event, int mode) int ret = 0; struct hw_perf_event *hwc = &event->hw; - if (mode & PERF_EF_START) { + if (mode & PERF_EF_START && !atomic_read(cs_updating_cnt)) { etm_event_start(event, 0); if (hwc->state & PERF_HES_STOPPED) ret = -EINVAL; @@ -499,9 +564,14 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link) if (ret) return ret; per_cpu(csdev_src, cpu) = csdev; + per_cpu(csdev_src_removing, cpu) = false; } else { sysfs_remove_link(&pmu_dev->kobj, entry); - per_cpu(csdev_src, cpu) = NULL; + /* + * Set to NULL later when device is unregistered to avoid + * conflict with ongoing event. + */ + per_cpu(csdev_src_removing, cpu) = true; } return 0; @@ -580,10 +650,79 @@ void etm_perf_del_symlink_sink(struct coresight_device *csdev) csdev->ea = NULL; } +static void update_cs_cfg(void *ignored) +{ + /* + * Reschedule running events. + * Events will be stopped and coresight path will be disabled. + * Coresight path won't be enabled again until coresight update + * is done. + */ + perf_pmu_resched(&etm_pmu); +} + +static void update_cs_path(struct coresight_device *csdev) +{ + struct ev_data *ev_data = NULL; + struct ev_data *ev_data_next = NULL; + struct etm_event_data *event_data; + unsigned int cpu; + cpumask_t *mask; + bool ret = false; + + mutex_lock(&cs_path_mutex); + + list_for_each_entry_safe(ev_data, ev_data_next, &ev_list, link) { + event_data = ev_data->event_data; + if (!event_data->snk_config) + continue; + + mask = &event_data->mask; + + for_each_cpu(cpu, mask) { + struct list_head **ppath; + + ppath = etm_event_cpu_path_ptr(event_data, cpu); + if (!(IS_ERR_OR_NULL(*ppath))) { + ret = coresight_dev_on_path(*ppath, csdev); + if (ret) + break; + } + } + + if (ret) + _free_event_data(event_data, ev_data); + } + + mutex_unlock(&cs_path_mutex); + for_each_possible_cpu(cpu) { + if (per_cpu(csdev_src_removing, cpu)) { + per_cpu(csdev_src, cpu) = NULL; + per_cpu(csdev_src_removing, cpu) = false; + } + } +} + +void etm_perf_disable_with(struct coresight_device *csdev) +{ + atomic_inc(cs_updating_cnt); + get_online_cpus(); + on_each_cpu(update_cs_cfg, NULL, 1); + put_online_cpus(); + /* Free events which have trace path related to csdev */ + update_cs_path(csdev); +} + +void etm_perf_disable_done(void) +{ + atomic_dec(cs_updating_cnt); +} + int __init etm_perf_init(void) { int ret; + etm_pmu.module = THIS_MODULE; etm_pmu.capabilities = (PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE); @@ -601,6 +740,11 @@ int __init etm_perf_init(void) etm_pmu.addr_filters_validate = etm_addr_filters_validate; etm_pmu.nr_addr_filters = ETM_ADDR_CMP_MAX; + cs_updating_cnt = kcalloc(1, sizeof(*cs_updating_cnt), GFP_KERNEL); + if (!cs_updating_cnt) + return -ENOMEM; + atomic_set(cs_updating_cnt, 0); + ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1); if (ret == 0) etm_perf_up = true; @@ -610,5 +754,6 @@ int __init etm_perf_init(void) void __exit etm_perf_exit(void) { + kfree(cs_updating_cnt); perf_pmu_unregister(&etm_pmu); } diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h index 3e4f2ad5e193..221831732cb1 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.h +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h @@ -61,6 +61,8 @@ struct etm_event_data { int etm_perf_symlink(struct coresight_device *csdev, bool link); int etm_perf_add_symlink_sink(struct coresight_device *csdev); void etm_perf_del_symlink_sink(struct coresight_device *csdev); +void etm_perf_disable_with(struct coresight_device *csdev); +void etm_perf_disable_done(void); static inline void *etm_perf_sink_config(struct perf_output_handle *handle) { struct etm_event_data *data = perf_get_aux(handle); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index 56d677473be4..f91fff8267be 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -151,8 +151,10 @@ struct coresight_device *coresight_get_sink(struct list_head *path); struct coresight_device *coresight_get_enabled_sink(bool reset); struct coresight_device *coresight_get_sink_by_id(u32 id); struct list_head *coresight_build_path(struct coresight_device *csdev, - struct coresight_device *sink); + struct coresight_device *sink); void coresight_release_path(struct list_head *path); +bool coresight_dev_on_path(struct list_head *path, + struct coresight_device *csdev); #if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X) extern int etm_readl_cp14(u32 off, unsigned int *val); diff --git a/kernel/events/core.c b/kernel/events/core.c index e296c5c59c6f..cce7a2b82a4b 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2723,6 +2723,7 @@ void perf_pmu_resched(struct pmu *pmu) ctx_resched(cpuctx, task_ctx, EVENT_ALL|EVENT_CPU); perf_ctx_unlock(cpuctx, task_ctx); } +EXPORT_SYMBOL_GPL(perf_pmu_resched); /* * Cross CPU call to install and enable a performance event -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel