From: Mathieu Poirier <mathieu.poirier@linaro.org>
To: Mike Leach <mike.leach@linaro.org>
Cc: yabinc@google.com, coresight@lists.linaro.org,
linux-arm-kernel@lists.infradead.org, suzuki.poulose@arm.com
Subject: Re: [RFC PATCH v3 5/9] coresight: etm4x: Add complex configuration handlers to etmv4
Date: Mon, 23 Nov 2020 14:58:20 -0700 [thread overview]
Message-ID: <20201123215820.GD104873@xps15> (raw)
In-Reply-To: <20201030175655.30126-6-mike.leach@linaro.org>
On Fri, Oct 30, 2020 at 05:56:51PM +0000, Mike Leach wrote:
> Adds in handlers to allow the ETMv4 to use the complex configuration
> support. Features and configurations can be loaded and selected in the
> device.
>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
> drivers/hwtracing/coresight/Makefile | 3 +-
> .../hwtracing/coresight/coresight-etm4x-cfg.c | 181 ++++++++++++++++++
> .../hwtracing/coresight/coresight-etm4x-cfg.h | 29 +++
> .../coresight/coresight-etm4x-core.c | 36 +++-
> .../coresight/coresight-etm4x-sysfs.c | 3 +
> 5 files changed, 249 insertions(+), 3 deletions(-)
> create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
>
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index daad9f103a78..ea544206204d 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -16,7 +16,8 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o
> coresight-etm3x-y := coresight-etm3x-core.o coresight-etm-cp14.o \
> coresight-etm3x-sysfs.o
> obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o
> -coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o
> +coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o \
> + coresight-etm4x-cfg.o
> obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
> obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
> obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> new file mode 100644
> index 000000000000..9589d43e7947
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
> @@ -0,0 +1,181 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright(C) 2020 Linaro Limited. All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include "coresight-etm4x.h"
> +#include "coresight-etm4x-cfg.h"
> +#include "coresight-priv.h"
> +#include "coresight-syscfg.h"
> +
> +/**
> + * etm4_cfg_map_reg_offset - validate and map the register offset into a
> + * location in the driver config struct.
> + *
> + * Limits the number of registers that can be accessed and programmed in
> + * features, to those which are used to control the trace capture parameters.
> + *
> + * Omits or limits access to those which the driver must use exclusively.
> + *
> + * Invalid offsets will result in fail code return and feature load failure.
> + *
> + * @drvdata: driver data to map into.
> + * @reg: register to map.
> + * @offset: device offset for the register
> + */
> +static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
> + struct cscfg_reg_csdev *reg, u32 offset)
> +{
> + int err = -EINVAL, idx;
> + struct etmv4_config *drvcfg = &drvdata->config;
> + u32 off_mask;
> +
> +#define CHECKREG(cval, elem) \
> + { \
> + if (offset == cval) { \
> + reg->drv_store = &drvcfg->elem; \
> + err = 0; \
> + break; \
> + } \
> + }
> +
> +#define CHECKREGIDX(cval, elem, off_idx) \
> + { \
> + if (off_mask == cval) { \
> + reg->drv_store = &drvcfg->elem[off_idx]; \
> + err = 0; \
> + break; \
> + } \
> + }
> +
> + if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
> + ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
> + ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
> + do {
> + CHECKREG(TRCEVENTCTL0R, eventctrl0);
> + CHECKREG(TRCEVENTCTL1R, eventctrl1);
> + CHECKREG(TRCSTALLCTLR, stall_ctrl);
> + CHECKREG(TRCTSCTLR, ts_ctrl);
> + CHECKREG(TRCSYNCPR, syncfreq);
> + CHECKREG(TRCCCCTLR, ccctlr);
> + CHECKREG(TRCBBCTLR, bb_ctrl);
> + CHECKREG(TRCVICTLR, vinst_ctrl);
> + CHECKREG(TRCVIIECTLR, viiectlr);
> + CHECKREG(TRCVISSCTLR, vissctlr);
> + CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
> + CHECKREG(TRCSEQRSTEVR, seq_rst);
> + CHECKREG(TRCSEQSTR, seq_state);
> + CHECKREG(TRCEXTINSELR, ext_inp);
> + CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
> + CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
> + CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
> + CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
> + } while (0);
> + } else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) {
> + /* sequencer state control registers */
> + idx = (offset & GENMASK(3, 0)) / 4;
> + if (idx < ETM_MAX_SEQ_STATES) {
> + reg->drv_store = &drvcfg->seq_ctrl[idx];
> + err = 0;
> + }
> + } else if ((offset >= TRCSSCCRn(0)) && (offset <= TRCSSPCICRn(7))) {
> + /* 32 bit, 8 off indexed register sets */
> + idx = (offset & GENMASK(4, 0)) / 4;
> + off_mask = (offset & GENMASK(11, 5));
> + do {
> + CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx);
> + CHECKREGIDX(TRCSSCSRn(0), ss_status, idx);
> + CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx);
This one is harder to understand because of @off_mask - please add it to the
list of parameters to the marcro so that all the element needed to understand
what is going on is at the same place.
> + } while (0);
> + } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
> + /* 64 bit, 8 off indexed register sets */
> + idx = (offset & GENMASK(5, 0)) / 8;
> + off_mask = (offset & GENMASK(11, 6));
> + do {
> + CHECKREGIDX(TRCCIDCVRn(0), ctxid_pid, idx);
> + CHECKREGIDX(TRCVMIDCVRn(0), vmid_val, idx);
> + } while (0);
> + } else if ((offset >= TRCRSCTLRn(2)) &&
> + (offset <= TRCRSCTLRn((ETM_MAX_RES_SEL - 1)))) {
> + /* 32 bit resource selection regs, 32 off, skip fixed 0,1 */
> + idx = (offset & GENMASK(6, 0)) / 4;
> + if (idx < ETM_MAX_RES_SEL) {
> + reg->drv_store = &drvcfg->res_ctrl[idx];
> + err = 0;
> + }
> + } else if ((offset >= TRCACVRn(0)) &&
> + (offset <= TRCACATRn((ETM_MAX_SINGLE_ADDR_CMP - 1)))) {
> + /* 64 bit addr cmp regs, 16 off */
> + idx = (offset & GENMASK(6, 0)) / 8;
> + off_mask = offset & GENMASK(11, 7);
> + do {
> + CHECKREGIDX(TRCACVRn(0), addr_val, idx);
> + CHECKREGIDX(TRCACATRn(0), addr_acc, idx);
> + } while (0);
> + } else if ((offset >= TRCCNTRLDVRn(0)) &&
> + (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
> + /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
> + idx = (offset & GENMASK(3, 0)) / 4;
> + off_mask = offset & GENMASK(11, 4);
> + do {
> + CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx);
> + CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx);
> + CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx);
> + } while (0);
> + }
> + return err;
> +}
> +
> +/**
> + * etm4_cfg_load_feature - load a feature into a device instance.
> + *
> + * @csdev: An ETMv4 CoreSight device.
> + * @feat: The feature to be loaded.
> + *
> + * The function will load a feature instance into the device, checking that
> + * the register definitions are valid for the device.
> + *
> + * Parameter and register definitions will be converted into internal
> + * structures that are used to set the values in the driver when the
> + * feature is enabled for the device.
> + *
> + * The feature spinlock pointer is initialised to the same spinlock
> + * that the driver uses to protect the internal register values.
> + */
> +static int etm4_cfg_load_feature(struct coresight_device *csdev,
> + struct cscfg_feature_csdev *feat)
> +{
> + struct device *dev = csdev->dev.parent;
> + struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
> + const struct cscfg_feature_desc *feat_desc = feat->desc;
> + u32 offset;
> + int i = 0, err = 0;
> +
> + /* essential we set the device spinlock */
Please explain why you are doing this. Otherwise we know it has to be done but
still wonder about the motivation.
> + feat->csdev_spinlock = &drvdata->spinlock;
> +
> + /* process the register descriptions */
> + for (i = 0; i < feat->nr_regs && !err; i++) {
> + offset = feat_desc->regs[i].flags & CS_CFG_REG_ID_MASK;
This confirms my comment from a previous patch. Embedding the offset
in a variable called "flags" is very confusing.
> + err = etm4_cfg_map_reg_offset(drvdata, &feat->regs[i], offset);
> + }
> + return err;
> +}
> +
> +/* match information when loading configurations */
> +#define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
> + CS_CFG_MATCH_CLASS_SRC_ETM4)
> +
> +int etm4_cs_cfg_register(struct coresight_device *csdev, const char *dev_name)
> +{
s/etm4_cs_cfg_register/etm4_cscfg_register()
> + struct cscfg_match_info cfg_info;
> + struct cscfg_csdev_feat_ops ops;
> +
> + cfg_info.dev_name = dev_name;
> + cfg_info.match_flags = CS_CFG_ETM4_MATCH_FLAGS;
> +
> + ops.load_feat = &etm4_cfg_load_feature;
> +
> + return cscfg_register_csdev(csdev, &cfg_info, &ops);
> +}
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
> new file mode 100644
> index 000000000000..bf33c720b5e9
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef _CORESIGHT_CORESIGHT_ETM4X_CFG_H
> +#define _CORESIGHT_CORESIGHT_ETM4X_CFG_H
> +
> +#include "coresight-config.h"
> +#include "coresight-etm4x.h"
> +
> +/* ETMv4 specific config defines */
> +
> +/* resource IDs */
> +
> +#define ETM4_CFG_RES_CTR 0x00001000
> +#define ETM4_CFG_RES_CMP 0x00002000
> +#define ETM4_CFG_RES_CMP_PAIR0 0x00003000
> +#define ETM4_CFG_RES_CMP_PAIR1 0x00004000
> +#define ETM4_CFG_RES_SEL 0x00005000
> +#define ETM4_CFG_RES_SEL_PAIR0 0x00006000
> +#define ETM4_CFG_RES_SEL_PAIR1 0x00007000
> +#define ETM4_CFG_RES_SEQ 0x00008000
> +#define ETM4_CFG_RES_TS 0x00009000
> +#define ETM4_CFG_RES_MASK 0x0000F000
> +
The first #define is used in the next patch but none of the others are.
> +int etm4_cs_cfg_register(struct coresight_device *csdev, const char *dev_name);
> +
> +#endif /* _CORESIGHT_CORESIGHT_ETM4X_CFG_H */
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 6096d7abf80d..88213aa7a72e 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -34,6 +34,8 @@
>
> #include "coresight-etm4x.h"
> #include "coresight-etm-perf.h"
> +#include "coresight-etm4x-cfg.h"
> +#include "coresight-syscfg.h"
>
> static int boot_enable;
> module_param(boot_enable, int, 0444);
> @@ -321,12 +323,15 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
> return ret;
> }
>
> -static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
> +static int etm4_parse_event_config(struct coresight_device *csdev,
> struct perf_event *event)
> {
> int ret = 0;
> + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> struct etmv4_config *config = &drvdata->config;
> struct perf_event_attr *attr = &event->attr;
> + unsigned long cfg_id;
> + int preset;
>
> if (!attr) {
> ret = -EINVAL;
> @@ -384,6 +389,19 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
> /* bit[12], Return stack enable bit */
> config->cfg |= BIT(12);
>
> + /*
> + * Set any selected configuration and preset.
> + *
> + * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
> + * in the perf attributes defined in coresight-etm-perf.c.
> + * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
> + */
> + if (attr->config2 & GENMASK_ULL(63, 32)) {
I understand why you have used a mask of 63-32 but it would be extremely cryptic
for anyone else. Please add a comment that justify your choice.
> + cfg_id = (u32)(attr->config2 >> 32);
> + preset = attr->config & 0xF;
This implies that presets need to start at 1 rather than 0. Otherwise there is
no way to specify the absence of a preset. There is a comment for
cscfg_csdev_enable_config() but adding another one here to complete the equation
would be appreciated.
> + ret = cscfg_csdev_enable_config(csdev, cfg_id, preset);
> + }
> +
> out:
> return ret;
> }
> @@ -400,7 +418,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
> }
>
> /* Configure the tracer based on the session's specifics */
> - ret = etm4_parse_event_config(drvdata, event);
> + ret = etm4_parse_event_config(csdev, event);
> if (ret)
> goto out;
> /* And enable it */
> @@ -416,6 +434,8 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
> struct etm4_enable_arg arg = { };
> int ret;
>
> + cscfg_csdev_set_enabled_feats(csdev);
> +
> spin_lock(&drvdata->spinlock);
>
> /*
> @@ -530,11 +550,14 @@ static int etm4_disable_perf(struct coresight_device *csdev,
> u32 control;
> struct etm_filters *filters = event->hw.addr_filters;
> struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> + struct perf_event_attr *attr = &event->attr;
>
> if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
> return -EINVAL;
>
> etm4_disable_hw(drvdata);
> + if (attr->config2 & GENMASK_ULL(63, 32))
Here too.
I will continue tomorrow.
Thanks,
Mathieu
> + cscfg_csdev_disable_config(csdev);
>
> /*
> * Check if the start/stop logic was active when the unit was stopped.
> @@ -569,6 +592,7 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
> smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
>
> spin_unlock(&drvdata->spinlock);
> + cscfg_csdev_save_enabled_feats(csdev);
> cpus_read_unlock();
>
> dev_dbg(&csdev->dev, "ETM tracing disabled\n");
> @@ -1536,6 +1560,13 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> return ret;
> }
>
> + /* register with config infrastructure & load any current features */
> + ret = etm4_cs_cfg_register(drvdata->csdev, dev_name(dev));
> + if (ret) {
> + coresight_unregister(drvdata->csdev);
> + return ret;
> + }
> +
> etmdrvdata[drvdata->cpu] = drvdata;
>
> pm_runtime_put(&adev->dev);
> @@ -1588,6 +1619,7 @@ static int __exit etm4_remove(struct amba_device *adev)
>
> cpus_read_unlock();
>
> + cscfg_unregister_csdev(drvdata->csdev);
> coresight_unregister(drvdata->csdev);
>
> return 0;
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index 989ce7b8ade7..78e68f3032d5 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -9,6 +9,7 @@
> #include <linux/sysfs.h>
> #include "coresight-etm4x.h"
> #include "coresight-priv.h"
> +#include "coresight-config.h"
>
> static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
> {
> @@ -269,6 +270,8 @@ static ssize_t reset_store(struct device *dev,
>
> spin_unlock(&drvdata->spinlock);
>
> + cscfg_csdev_reset_feats(to_coresight_device(dev));
> +
> return size;
> }
> static DEVICE_ATTR_WO(reset);
> --
> 2.17.1
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-11-23 22:00 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-30 17:56 [RFC PATCH v3 0/9] CoreSight complex config support; ETM strobing Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 1/9] coresight: syscfg: Initial coresight system configuration Mike Leach
2020-11-12 22:09 ` Mathieu Poirier
2020-11-13 17:27 ` Mathieu Poirier
2020-11-16 18:32 ` Mathieu Poirier
2020-11-26 18:35 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 2/9] coresight: syscfg: Add registration and feature loading for cs devices Mike Leach
2020-11-16 18:47 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 3/9] coresight: config: Add configuration and feature generic functions Mike Leach
2020-11-17 19:00 ` Mathieu Poirier
2020-11-19 22:29 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 4/9] coresight: etm-perf: update to handle configuration selection Mike Leach
2020-11-20 18:52 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 5/9] coresight: etm4x: Add complex configuration handlers to etmv4 Mike Leach
2020-11-23 21:58 ` Mathieu Poirier [this message]
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 6/9] coresight: config: Add preloaded configurations Mike Leach
2020-11-24 17:51 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 7/9] coresight: syscfg: Add initial configfs support Mike Leach
2020-11-24 20:57 ` Mathieu Poirier
2020-11-25 21:52 ` Mathieu Poirier
2020-11-26 16:51 ` Mathieu Poirier
2020-10-30 17:56 ` [RFC PATCH v3 8/9] coresight: syscfg: Allow update of feature params from configfs Mike Leach
2020-11-26 17:17 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-10-30 17:56 ` [RFC PATCH v3 9/9] coresight: docs: Add documentation for CoreSight config Mike Leach
2020-11-26 17:52 ` Mathieu Poirier
2020-12-24 19:21 ` Mike Leach
2020-11-26 18:52 ` [RFC PATCH v3 0/9] CoreSight complex config support; ETM strobing Mathieu Poirier
2020-12-24 19:20 ` Mike Leach
2021-01-06 21:15 ` Mathieu Poirier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201123215820.GD104873@xps15 \
--to=mathieu.poirier@linaro.org \
--cc=coresight@lists.linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=mike.leach@linaro.org \
--cc=suzuki.poulose@arm.com \
--cc=yabinc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.