coresight: updates for Linux v7.4

CoreSight selfhosted tracing subsystem updates for Linux v7.4, includes:
  - Separating the ETM configurations for sysfs and perf to avoid corrupting
    each other while in use
  - Hide sysfs control for TRBE as it is not supported
  - Constify Amba device table for tnoc
 
 Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmrMsJUACgkQxcXRZPKy
 BqGxABAAp+H5TEr7RR18tQ/cUF2uvU5DhiCLwvdY8Fc6cJezGcYvmblBshPgvQ68
 GxDJJp8q4mr5hNhYyCq3amjQdESb8qof1fgqQpTtkv3bTLCdd5PbtzBr4bwIKhJx
 y1UIhH200zWN4RbpvosFwt+HmyQf3gQfQDRIjmeJqb3mKv50NBFttRBPHR7EysXn
 /6rqifEgwUt6wbwnGu2YncrcYwme4z349o62WFovGESaiAseUre6PGGxwrFWEUqC
 nl4gDvDxmnYeNnwQAX/ucXSjjR5kj0dIuNGz4ry6emG2I/7WRJKJXaii2/+YXpKp
 0zh10LiMtryIpuzgZFmO+7tWwqauNdaGKhocceERDulikjvwdDCBTwHsitYSY8iS
 D5axCpzQ+Jgfq0IQGjlSv0T57DKYKn0E/+unhuHrQ4XgLPg85THuSn4LRJj3MPnX
 bNhiNGeNuRze9PIZYSU8i48VlBYlX2UwWN3I/sU2j/GtYWpJdwL+ePeq0dQtK7gP
 FaG/52vOrV4+HubufFuh0/2ctuwFINGU8xwTCqdzMoqX5OYzxRIydKq9JEiRemSa
 SaP/GUQE+BakFbCs51TzBYmHq6/0Y88pKlzX4jtfnrsFNgN/UkmrlAH5HMk1bcqf
 p+dis3jjXE74fbFyKjTQk5VoIFTEkjeKVDo0jK2GGPikM6OVwOI=
 =LS3q
 -----END PGP SIGNATURE-----

Merge tag 'coresight-next-v7.4' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Suzuki writes:

coresight: updates for Linux v7.4

CoreSight selfhosted tracing subsystem updates for Linux v7.4, includes:
 - Separating the ETM configurations for sysfs and perf to avoid corrupting
   each other while in use
 - Hide sysfs control for TRBE as it is not supported
 - Constify Amba device table for tnoc

Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

* tag 'coresight-next-v7.4' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux:
  coresight: tnoc: Constify amba_id table
  coresight: etm3x: rename drvdata->config to sysfs_config
  coresight: etm3x: rename local config as curr_config referring drvdata->curr_config
  coresight: etm3x: introduce struct etm_caps
  coresight: etm4x: rename drvdata->config to sysfs_config
  coresight: etm4x: rename local config as curr_config referring drvdata->curr_config
  coresight: etm4x: remove s_ex_level from config
  coresight: etm4x: exclude ss_status from drvdata->config
  coresight: etm4x: introduce struct etm4_caps
  coresight: etm3x: remove redundant cpu online check on etm_enable_sysfs()
  coresight: etm3x: fix inconsistencies with sysfs configuration
  coresight: etm4x: fix inconsistencies with sysfs configuration
  coresight: etm3x: Prohibit modifying cntr_val while session is enabled
  coresight: etm4x: prohibit modifying cntr_val while session is enabled
  coresight: etm4x: Prohibit TRCSEQSTR modifications while tracing enabled
  coresight: trbe: Hide enable_sink sysfs file
This commit is contained in:
Greg Kroah-Hartman 2026-10-13 15:53:14 +02:00
commit 7e170600b3
14 changed files with 1359 additions and 1150 deletions

View File

@ -73,13 +73,12 @@ static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
/* set values into the driver locations referenced in cscfg_reg_csdev */
static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
{
unsigned long flags;
int i;
raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_set_reg(&feat_csdev->regs_csdev[i]);
raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
scoped_guard(feat_csdev_lock, feat_csdev) {
for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_set_reg(&feat_csdev->regs_csdev[i]);
}
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "set on enable");
return 0;
@ -88,13 +87,12 @@ static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
/* copy back values from the driver locations referenced in cscfg_reg_csdev */
static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
{
unsigned long flags;
int i;
raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_save_reg(&feat_csdev->regs_csdev[i]);
raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
scoped_guard(feat_csdev_lock, feat_csdev) {
for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_save_reg(&feat_csdev->regs_csdev[i]);
}
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "save on disable");
}

View File

@ -7,6 +7,7 @@
#ifndef _CORESIGHT_CORESIGHT_CONFIG_H
#define _CORESIGHT_CORESIGHT_CONFIG_H
#include <linux/cleanup.h>
#include <linux/coresight.h>
#include <linux/types.h>
@ -259,4 +260,25 @@ void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev);
/* reset a feature to default values */
void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev);
#define feat_csdev_lock(feat_csdev, flags) \
do { \
raw_spinlock_t *__lock = feat_csdev->drv_spinlock; \
typecheck(unsigned long, flags); \
if (__lock) \
raw_spin_lock_irqsave(__lock, flags); \
} while (0)
#define feat_csdev_unlock(feat_csdev, flags) \
do { \
raw_spinlock_t *__lock = feat_csdev->drv_spinlock; \
typecheck(unsigned long, flags); \
if (__lock) \
raw_spin_unlock_irqrestore(__lock, flags); \
} while (0)
DEFINE_LOCK_GUARD_1(feat_csdev_lock, struct cscfg_feature_csdev,
feat_csdev_lock(_T->lock, _T->flags),
feat_csdev_unlock(_T->lock, _T->flags),
unsigned long flags)
#endif /* _CORESIGHT_CORESIGHT_CONFIG_H */

View File

@ -1543,6 +1543,7 @@ coresight_init_device(struct coresight_desc *desc)
csdev->ops = desc->ops;
csdev->access = desc->access;
csdev->orphan = true;
csdev->flags = desc->flags;
if (desc->flags & CORESIGHT_DESC_CPU_BOUND) {
csdev->cpu = desc->cpu;

View File

@ -140,6 +140,30 @@
ETM_ADD_COMP_0 | \
ETM_EVENT_NOT_A)
/**
* struct etm_caps - specifics ETM capabilities
* @port_size: port size as reported by ETMCR bit 4-6 and 21.
* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
* @nr_cntr: Number of counters as found in ETMCCR bit 13-15.
* @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19.
* @nr_ext_out: Number of external output as found in ETMCCR bit 20-22.
* @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25.
* @fifofull: FIFOFULL logic is present.
* @timestamp: Timestamping is implemented.
* @retstack: Return stack is implemented.
*/
struct etm_caps {
int port_size;
u8 nr_addr_cmp;
u8 nr_cntr;
u8 nr_ext_inp;
u8 nr_ext_out;
u8 nr_ctxid_cmp;
bool fifofull : 1;
bool timestamp : 1;
bool retstack : 1;
};
/**
* struct etm_config - configuration information related to an ETM
* @mode: controls various modes supported by this ETM/PTM.
@ -212,21 +236,15 @@ struct etm_config {
* @csdev: component vitals needed by the framework.
* @spinlock: only one at a time pls.
* @cpu: the cpu this component is affined to.
* @port_size: port size as reported by ETMCR bit 4-6 and 21.
* @arch: ETM/PTM version number.
* @caps: ETM capabilities.
* @use_cpu14: true if management registers need to be accessed via CP14.
* @sticky_enable: true if ETM base configuration has been done.
* @boot_enable:true if we should start tracing at boot time.
* @os_unlock: true if access to management registers is allowed.
* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
* @nr_cntr: Number of counters as found in ETMCCR bit 13-15.
* @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19.
* @nr_ext_out: Number of external output as found in ETMCCR bit 20-22.
* @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25.
* @etmccr: value of register ETMCCR.
* @etmccer: value of register ETMCCER.
* @traceid: value of the current ID for this component.
* @config: structure holding configuration parameters.
* @curr_config: structure holding current running configuration.
* @sysfs_config: structure holding sysfs mode configuration.
*/
struct etm_drvdata {
struct csdev_access csa;
@ -234,21 +252,15 @@ struct etm_drvdata {
struct coresight_device *csdev;
spinlock_t spinlock;
int cpu;
int port_size;
u8 arch;
struct etm_caps caps;
bool use_cp14;
bool sticky_enable;
bool boot_enable;
bool os_unlock;
u8 nr_addr_cmp;
u8 nr_cntr;
u8 nr_ext_inp;
u8 nr_ext_out;
u8 nr_ctxid_cmp;
u32 etmccr;
u32 etmccer;
u32 traceid;
struct etm_config config;
struct etm_config curr_config;
struct etm_config sysfs_config;
};
static inline void etm_writel(struct etm_drvdata *drvdata,

View File

@ -308,7 +308,8 @@ void etm_config_trace_mode(struct etm_config *config)
static int etm_parse_event_config(struct etm_drvdata *drvdata,
struct perf_event *event)
{
struct etm_config *config = &drvdata->config;
const struct etm_caps *caps = &drvdata->caps;
struct etm_config *curr_config = &drvdata->curr_config;
struct perf_event_attr *attr = &event->attr;
u8 ts_level;
@ -316,28 +317,28 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
return -EINVAL;
/* Clear configuration from previous run */
memset(config, 0, sizeof(struct etm_config));
memset(curr_config, 0, sizeof(struct etm_config));
if (attr->exclude_kernel)
config->mode = ETM_MODE_EXCL_KERN;
curr_config->mode = ETM_MODE_EXCL_KERN;
if (attr->exclude_user)
config->mode = ETM_MODE_EXCL_USER;
curr_config->mode = ETM_MODE_EXCL_USER;
/* Always start from the default config */
etm_set_default(config);
etm_set_default(curr_config);
/*
* By default the tracers are configured to trace the whole address
* range. Narrow the field only if requested by user space.
*/
if (config->mode)
etm_config_trace_mode(config);
if (curr_config->mode)
etm_config_trace_mode(curr_config);
config->ctrl = 0;
curr_config->ctrl = 0;
if (ATTR_CFG_GET_FLD(attr, cycacc))
config->ctrl |= ETMCR_CYC_ACC;
curr_config->ctrl |= ETMCR_CYC_ACC;
ts_level = max(ATTR_CFG_GET_FLD(attr, timestamp),
ATTR_CFG_GET_FLD(attr, deprecated_timestamp));
@ -349,16 +350,15 @@ static int etm_parse_event_config(struct etm_drvdata *drvdata,
}
if (ts_level)
config->ctrl |= ETMCR_TIMESTAMP_EN;
curr_config->ctrl |= ETMCR_TIMESTAMP_EN;
/*
* Possible to have cores with PTM (supports ret stack) and ETM (never
* has ret stack) on the same SoC. So only enable when it can be honored
* - trace will still continue normally otherwise.
*/
if (ATTR_CFG_GET_FLD(attr, retstack) &&
(drvdata->etmccer & ETMCCER_RETSTACK))
config->ctrl |= ETMCR_RETURN_STACK;
if (ATTR_CFG_GET_FLD(attr, retstack) && (caps->retstack))
curr_config->ctrl |= ETMCR_RETURN_STACK;
return 0;
}
@ -367,7 +367,8 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
{
int i, rc;
u32 etmcr;
struct etm_config *config = &drvdata->config;
const struct etm_caps *caps = &drvdata->caps;
struct etm_config *curr_config = &drvdata->curr_config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->csa.base);
@ -388,41 +389,41 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
etmcr = etm_readl(drvdata, ETMCR);
/* Clear setting from a previous run if need be */
etmcr &= ~ETM3X_SUPPORTED_OPTIONS;
etmcr |= drvdata->port_size;
etmcr |= caps->port_size;
etmcr |= ETMCR_ETM_EN;
etm_writel(drvdata, config->ctrl | etmcr, ETMCR);
etm_writel(drvdata, config->trigger_event, ETMTRIGGER);
etm_writel(drvdata, config->startstop_ctrl, ETMTSSCR);
etm_writel(drvdata, config->enable_event, ETMTEEVR);
etm_writel(drvdata, config->enable_ctrl1, ETMTECR1);
etm_writel(drvdata, config->fifofull_level, ETMFFLR);
for (i = 0; i < drvdata->nr_addr_cmp; i++) {
etm_writel(drvdata, config->addr_val[i], ETMACVRn(i));
etm_writel(drvdata, config->addr_acctype[i], ETMACTRn(i));
etm_writel(drvdata, curr_config->ctrl | etmcr, ETMCR);
etm_writel(drvdata, curr_config->trigger_event, ETMTRIGGER);
etm_writel(drvdata, curr_config->startstop_ctrl, ETMTSSCR);
etm_writel(drvdata, curr_config->enable_event, ETMTEEVR);
etm_writel(drvdata, curr_config->enable_ctrl1, ETMTECR1);
etm_writel(drvdata, curr_config->fifofull_level, ETMFFLR);
for (i = 0; i < caps->nr_addr_cmp; i++) {
etm_writel(drvdata, curr_config->addr_val[i], ETMACVRn(i));
etm_writel(drvdata, curr_config->addr_acctype[i], ETMACTRn(i));
}
for (i = 0; i < drvdata->nr_cntr; i++) {
etm_writel(drvdata, config->cntr_rld_val[i], ETMCNTRLDVRn(i));
etm_writel(drvdata, config->cntr_event[i], ETMCNTENRn(i));
etm_writel(drvdata, config->cntr_rld_event[i],
for (i = 0; i < caps->nr_cntr; i++) {
etm_writel(drvdata, curr_config->cntr_rld_val[i], ETMCNTRLDVRn(i));
etm_writel(drvdata, curr_config->cntr_event[i], ETMCNTENRn(i));
etm_writel(drvdata, curr_config->cntr_rld_event[i],
ETMCNTRLDEVRn(i));
etm_writel(drvdata, config->cntr_val[i], ETMCNTVRn(i));
etm_writel(drvdata, curr_config->cntr_val[i], ETMCNTVRn(i));
}
etm_writel(drvdata, config->seq_12_event, ETMSQ12EVR);
etm_writel(drvdata, config->seq_21_event, ETMSQ21EVR);
etm_writel(drvdata, config->seq_23_event, ETMSQ23EVR);
etm_writel(drvdata, config->seq_31_event, ETMSQ31EVR);
etm_writel(drvdata, config->seq_32_event, ETMSQ32EVR);
etm_writel(drvdata, config->seq_13_event, ETMSQ13EVR);
etm_writel(drvdata, config->seq_curr_state, ETMSQR);
for (i = 0; i < drvdata->nr_ext_out; i++)
etm_writel(drvdata, curr_config->seq_12_event, ETMSQ12EVR);
etm_writel(drvdata, curr_config->seq_21_event, ETMSQ21EVR);
etm_writel(drvdata, curr_config->seq_23_event, ETMSQ23EVR);
etm_writel(drvdata, curr_config->seq_31_event, ETMSQ31EVR);
etm_writel(drvdata, curr_config->seq_32_event, ETMSQ32EVR);
etm_writel(drvdata, curr_config->seq_13_event, ETMSQ13EVR);
etm_writel(drvdata, curr_config->seq_curr_state, ETMSQR);
for (i = 0; i < caps->nr_ext_out; i++)
etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));
for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
etm_writel(drvdata, config->ctxid_pid[i], ETMCIDCVRn(i));
etm_writel(drvdata, config->ctxid_mask, ETMCIDCMR);
etm_writel(drvdata, config->sync_freq, ETMSYNCFR);
for (i = 0; i < caps->nr_ctxid_cmp; i++)
etm_writel(drvdata, curr_config->ctxid_pid[i], ETMCIDCVRn(i));
etm_writel(drvdata, curr_config->ctxid_mask, ETMCIDCMR);
etm_writel(drvdata, curr_config->sync_freq, ETMSYNCFR);
/* No external input selected */
etm_writel(drvdata, 0x0, ETMEXTINSELR);
etm_writel(drvdata, config->timestamp_event, ETMTSEVR);
etm_writel(drvdata, curr_config->timestamp_event, ETMTSEVR);
/* No auxiliary control selected */
etm_writel(drvdata, 0x0, ETMAUXCR);
etm_writel(drvdata, drvdata->traceid, ETMTRACEIDR);
@ -448,26 +449,22 @@ struct etm_enable_arg {
static void etm_enable_sysfs_smp_call(void *info)
{
struct etm_enable_arg *arg = info;
struct etm_drvdata *drvdata;
struct coresight_device *csdev;
if (WARN_ON(!arg))
return;
csdev = arg->drvdata->csdev;
if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
/* Someone is already using the tracer */
arg->rc = -EBUSY;
return;
}
drvdata = arg->drvdata;
csdev = drvdata->csdev;
drvdata->traceid = arg->path->trace_id;
arg->rc = etm_enable_hw(arg->drvdata);
/* The tracer didn't start */
if (arg->rc) {
coresight_set_mode(csdev, CS_MODE_DISABLED);
if (arg->rc)
return;
}
drvdata->sticky_enable = true;
csdev->path = arg->path;
}
@ -512,34 +509,33 @@ static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_pat
struct etm_enable_arg arg = { };
int ret;
spin_lock(&drvdata->spinlock);
drvdata->traceid = path->trace_id;
/*
* Configure the ETM only if the CPU is online. If it isn't online
* hw configuration will take place on the local CPU during bring up.
*/
if (cpu_online(drvdata->cpu)) {
arg.drvdata = drvdata;
arg.path = path;
ret = smp_call_function_single(drvdata->cpu,
etm_enable_sysfs_smp_call, &arg, 1);
if (!ret)
ret = arg.rc;
if (!ret)
drvdata->sticky_enable = true;
} else {
ret = -ENODEV;
if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
/* Someone is already using the tracer */
return -EBUSY;
}
if (ret)
etm_release_trace_id(drvdata);
arg.drvdata = drvdata;
arg.path = path;
spin_unlock(&drvdata->spinlock);
scoped_guard(spinlock, &drvdata->spinlock) {
drvdata->curr_config = drvdata->sysfs_config;
}
ret = smp_call_function_single(drvdata->cpu,
etm_enable_sysfs_smp_call, &arg, 1);
if (!ret)
ret = arg.rc;
else
ret = -ENODEV;
if (!ret) {
dev_dbg(&csdev->dev, "ETM tracing enabled\n");
} else {
etm_release_trace_id(drvdata);
/* The tracer didn't start */
coresight_set_mode(csdev, CS_MODE_DISABLED);
}
return ret;
}
@ -565,17 +561,18 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
static void etm_disable_hw(struct etm_drvdata *drvdata)
{
int i;
struct etm_config *config = &drvdata->config;
const struct etm_caps *caps = &drvdata->caps;
struct etm_config *curr_config = &drvdata->curr_config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->csa.base);
etm_set_prog(drvdata);
/* Read back sequencer and counters for post trace analysis */
config->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
curr_config->seq_curr_state = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
for (i = 0; i < drvdata->nr_cntr; i++)
config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
for (i = 0; i < caps->nr_cntr; i++)
curr_config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(csdev);
@ -593,7 +590,6 @@ static void etm_disable_sysfs_smp_call(void *info)
etm_disable_hw(drvdata);
drvdata->csdev->path = NULL;
coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
}
static void etm_disable_perf(struct coresight_device *csdev)
@ -630,8 +626,10 @@ static void etm_disable_perf(struct coresight_device *csdev)
static void etm_disable_sysfs(struct coresight_device *csdev)
{
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock(&drvdata->spinlock);
const struct etm_caps *caps = &drvdata->caps;
struct etm_config *sysfs_config = &drvdata->sysfs_config;
const struct etm_config *curr_config = &drvdata->curr_config;
int i;
/*
* Executing etm_disable_hw on the cpu whose ETM is being disabled
@ -640,7 +638,14 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
smp_call_function_single(drvdata->cpu, etm_disable_sysfs_smp_call,
drvdata, 1);
spin_unlock(&drvdata->spinlock);
/*
* Userspace may read seq_curr_state and cntr_val through sysfs
* after the sysfs-session has been disabled.
*/
for (i = 0; i < caps->nr_cntr; i++)
sysfs_config->cntr_val[i] = curr_config->cntr_val[i];
sysfs_config->seq_curr_state = curr_config->seq_curr_state;
/*
* we only release trace IDs when resetting sysfs.
@ -649,6 +654,8 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
* prior trace id allocation method
*/
coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
dev_dbg(&csdev->dev, "ETM tracing disabled\n");
}
@ -720,7 +727,9 @@ static void etm_init_arch_data(void *info)
{
u32 etmidr;
u32 etmccr;
u32 etmccer;
struct etm_drvdata *drvdata = info;
struct etm_caps *caps = &drvdata->caps;
/* Make sure all registers are accessible */
etm_os_unlock(drvdata);
@ -745,16 +754,19 @@ static void etm_init_arch_data(void *info)
/* Find all capabilities */
etmidr = etm_readl(drvdata, ETMIDR);
drvdata->arch = BMVAL(etmidr, 4, 11);
drvdata->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK;
caps->port_size = etm_readl(drvdata, ETMCR) & PORT_SIZE_MASK;
etmccer = etm_readl(drvdata, ETMCCER);
caps->timestamp = !!(etmccer & ETMCCER_TIMESTAMP);
caps->retstack = !!(etmccer & ETMCCER_RETSTACK);
drvdata->etmccer = etm_readl(drvdata, ETMCCER);
etmccr = etm_readl(drvdata, ETMCCR);
drvdata->etmccr = etmccr;
drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
caps->fifofull = !!(etmccr & ETMCCR_FIFOFULL);
caps->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
caps->nr_cntr = BMVAL(etmccr, 13, 15);
caps->nr_ext_inp = BMVAL(etmccr, 17, 19);
caps->nr_ext_out = BMVAL(etmccr, 20, 22);
caps->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
etm_set_pwrdwn(drvdata);
@ -832,7 +844,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
if (etm_arch_supported(drvdata->arch) == false)
return -EINVAL;
etm_set_default(&drvdata->config);
etm_set_default(&drvdata->sysfs_config);
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata))

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
struct cscfg_regval_csdev *reg_csdev, u32 offset)
{
int err = -EINVAL, idx;
struct etmv4_config *drvcfg = &drvdata->config;
struct etmv4_config *drvcfg = &drvdata->curr_config;
u32 off_mask;
if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
@ -86,7 +86,6 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
off_mask = (offset & GENMASK(11, 5));
do {
CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
} while (0);
} else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
@ -154,11 +153,14 @@ static int etm4_cfg_load_feature(struct coresight_device *csdev,
int i = 0, err = 0;
/*
* essential we set the device spinlock - this is used in the generic
* programming routines when copying values into the drvdata structures
* via the pointers setup in etm4_cfg_map_reg_offset().
* drvdata structure of etm4 for configfs is curr_config and
* this curr_config is protected with csdev->mode by restricting
* access to curr_config after mode changed to PERF or SYSFS.
*
* Therefore, it doesn't need to protected with etmv4_drvdata->spinlock
* to feature applying and set the NULL.
*/
feat_csdev->drv_spinlock = &drvdata->spinlock;
feat_csdev->drv_spinlock = NULL;
/* process the register descriptions */
for (i = 0; i < feat_csdev->nr_regs && !err; i++) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -213,6 +213,11 @@
#define TRCACATRn_EXLEVEL_MASK GENMASK(14, 8)
#define TRCSSCSRn_STATUS BIT(31)
/*
* TRCSSCSR.PENDING is only implemented by ETE and is therefore not
* described in DEN0117. See Arm ARM (DDI0487) M.c, section D24.4.59.
*/
#define TRCSSCSRn_PENDING BIT(30)
#define TRCSSCCRn_SAC_ARC_RST_MASK GENMASK(24, 0)
#define TRCSSPCICRn_PC_MASK GENMASK(7, 0)
@ -813,6 +818,97 @@ enum etm_impdef_type {
ETM4_IMPDEF_FEATURE_MAX,
};
/**
* struct etmv4_caps - specifics ETM capabilities
* @nr_pe: The number of processing entity available for tracing.
* @nr_pe_cmp: The number of processing entity comparator inputs that are
* available for tracing.
* @nr_addr_cmp:Number of pairs of address comparators available
* as found in ETMIDR4 0-3.
* @nr_cntr: Number of counters as found in ETMIDR5 bit 28-30.
* @nr_ext_inp: Number of external input.
* @numcidc: Number of contextID comparators.
* @numextinsel: Number of external input selector resources.
* @numvmidc: Number of VMID comparators.
* @nrseqstate: The number of sequencer states that are implemented.
* @nr_seq_ctrls: The number of sequence state transition control registers.
* @nr_event: Indicates how many events the trace unit support.
* @nr_resource:The number of resource selection pairs available for tracing.
* @nr_ss_cmp: Number of single-shot comparator controls that are available.
* @trcid_size: Indicates the trace ID width.
* @ts_size: Global timestamp size field.
* @ctxid_size: Size of the context ID field to consider.
* @vmid_size: Size of the VM ID comparator to consider.
* @ccsize: Indicates the size of the cycle counter in bits.
* @ccitmin: minimum value that can be programmed in
* @s_ex_level: In secure state, indicates whether instruction tracing is
* supported for the corresponding Exception level.
* @ns_ex_level:In non-secure state, indicates whether instruction tracing is
* supported for the corresponding Exception level.
* @q_support: Q element support characteristics.
* @os_lock_model: OSLock model.
* @instrp0: Tracing of load and store instructions
* as P0 elements is supported.
* @q_filt: Q element filtering support, if Q elements are supported.
* @trcbb: Indicates if the trace unit supports branch broadcast tracing.
* @trccond: If the trace unit supports conditional
* instruction tracing.
* @retstack: Indicates if the implementation supports a return stack.
* @trccci: Indicates if the trace unit supports cycle counting
* for instruction.
* @trc_error: Whether a trace unit can trace a system
* error exception.
* @syncpr: Indicates if an implementation has a fixed
* synchronization period.
* @stallctl: If functionality that prevents trace unit buffer overflows
* is available.
* @sysstall: Does the system support stall control of the PE?
* @nooverflow: Indicate if overflow prevention is supported.
* @atbtrig: If the implementation can support ATB triggers
* @lpoverride: If the implementation can support low-power state over.
* @skip_power_up: Indicates if an implementation can skip powering up
* the trace unit.
*/
struct etmv4_caps {
u8 nr_pe;
u8 nr_pe_cmp;
u8 nr_addr_cmp;
u8 nr_cntr;
u8 nr_ext_inp;
u8 numcidc;
u8 numextinsel;
u8 numvmidc;
u8 nrseqstate;
u8 nr_seq_ctrls;
u8 nr_event;
u8 nr_resource;
u8 nr_ss_cmp;
u8 trcid_size;
u8 ts_size;
u8 ctxid_size;
u8 vmid_size;
u8 ccsize;
u16 ccitmin;
u8 s_ex_level;
u8 ns_ex_level;
u8 q_support;
u8 os_lock_model;
bool instrp0 : 1;
bool q_filt : 1;
bool trcbb : 1;
bool trccond : 1;
bool retstack : 1;
bool trccci : 1;
bool trc_error : 1;
bool syncpr : 1;
bool stallctl : 1;
bool sysstall : 1;
bool nooverflow : 1;
bool atbtrig : 1;
bool lpoverride : 1;
bool skip_power_up : 1;
};
/**
* struct etmv4_config - configuration information related to an ETMv4
* @mode: Controls various modes supported by this ETM.
@ -820,8 +916,8 @@ enum etm_impdef_type {
* @cfg: Controls the tracing options.
* @eventctrl0: Controls the tracing of arbitrary events.
* @eventctrl1: Controls the behavior of the events that @event_ctrl0 selects.
* @stallctl: If functionality that prevents trace unit buffer overflows
* is available.
* @stall_ctrl: Enables trace unit functionality that prevents trace
* unit buffer overflows.
* @ts_ctrl: Controls the insertion of global timestamps in the
* trace streams.
* @syncfreq: Controls how often trace synchronization requests occur.
@ -860,7 +956,6 @@ enum etm_impdef_type {
* @vmid_mask0: VM ID comparator mask for comparator 0-3.
* @vmid_mask1: VM ID comparator mask for comparator 4-7.
* @ext_inp: External input selection.
* @s_ex_level: Secure ELs where tracing is supported.
*/
struct etmv4_config {
u64 mode;
@ -889,7 +984,6 @@ struct etmv4_config {
u32 res_ctrl[ETM_MAX_RES_SEL]; /* TRCRSCTLRn */
u8 ss_idx;
u32 ss_ctrl[ETM_MAX_SS_CMP];
u32 ss_status[ETM_MAX_SS_CMP];
u32 ss_pe_cmp[ETM_MAX_SS_CMP];
u8 addr_idx;
u64 addr_val[ETM_MAX_SINGLE_ADDR_CMP];
@ -904,7 +998,6 @@ struct etmv4_config {
u32 vmid_mask0;
u32 vmid_mask1;
u32 ext_inp;
u8 s_ex_level;
};
/**
@ -967,63 +1060,20 @@ struct etmv4_save_state {
* @mode: This tracer's mode, i.e sysFS, Perf or disabled.
* @cpu: The cpu this component is affined to.
* @arch: ETM architecture version.
* @nr_pe: The number of processing entity available for tracing.
* @nr_pe_cmp: The number of processing entity comparator inputs that are
* available for tracing.
* @nr_addr_cmp:Number of pairs of address comparators available
* as found in ETMIDR4 0-3.
* @nr_cntr: Number of counters as found in ETMIDR5 bit 28-30.
* @nr_ext_inp: Number of external input.
* @numcidc: Number of contextID comparators.
* @numvmidc: Number of VMID comparators.
* @nrseqstate: The number of sequencer states that are implemented.
* @nr_seq_ctrls: The number of sequence state transition control registers.
* @nr_event: Indicates how many events the trace unit support.
* @nr_resource:The number of resource selection pairs available for tracing.
* @nr_ss_cmp: Number of single-shot comparator controls that are available.
* @caps: ETM capabilities.
* @trcid: value of the current ID for this component.
* @trcid_size: Indicates the trace ID width.
* @ts_size: Global timestamp size field.
* @ctxid_size: Size of the context ID field to consider.
* @vmid_size: Size of the VM ID comparator to consider.
* @ccsize: Indicates the size of the cycle counter in bits.
* @ccitmin: minimum value that can be programmed in
* @s_ex_level: In secure state, indicates whether instruction tracing is
* supported for the corresponding Exception level.
* @ns_ex_level:In non-secure state, indicates whether instruction tracing is
* supported for the corresponding Exception level.
* @sticky_enable: true if ETM base configuration has been done.
* @boot_enable:True if we should start tracing at boot time.
* @os_unlock: True if access to management registers is allowed.
* @instrp0: Tracing of load and store instructions
* as P0 elements is supported.
* @q_filt: Q element filtering support, if Q elements are supported.
* @trcbb: Indicates if the trace unit supports branch broadcast tracing.
* @trccond: If the trace unit supports conditional
* instruction tracing.
* @retstack: Indicates if the implementation supports a return stack.
* @trccci: Indicates if the trace unit supports cycle counting
* for instruction.
* @q_support: Q element support characteristics.
* @trc_error: Whether a trace unit can trace a system
* error exception.
* @syncpr: Indicates if an implementation has a fixed
* synchronization period.
* @stall_ctrl: Enables trace unit functionality that prevents trace
* unit buffer overflows.
* @sysstall: Does the system support stall control of the PE?
* @nooverflow: Indicate if overflow prevention is supported.
* @atbtrig: If the implementation can support ATB triggers
* @lpoverride: If the implementation can support low-power state over.
* @trfcr: If the CPU supports FEAT_TRF, value of the TRFCR_ELx that
* allows tracing at all ELs. We don't want to compute this
* at runtime, due to the additional setting of TRFCR_CX when
* in EL2. Otherwise, 0.
* @config: structure holding configuration parameters.
* @curr_config: structure holding current applied configuration.
* @sysfs_config: structure holding sysfs mode configuration.
* @save_state: State to be preserved across power loss
* @skip_power_up: Indicates if an implementation can skip powering up
* the trace unit.
* @paused: Indicates if the trace unit is paused.
* @ss_status: The status of the corresponding single-shot comparator.
* @arch_features: Bitmap of arch features of etmv4 devices.
*/
struct etmv4_drvdata {
@ -1034,51 +1084,17 @@ struct etmv4_drvdata {
raw_spinlock_t spinlock;
int cpu;
u8 arch;
u8 nr_pe;
u8 nr_pe_cmp;
u8 nr_addr_cmp;
u8 nr_cntr;
u8 nr_ext_inp;
u8 numcidc;
u8 numextinsel;
u8 numvmidc;
u8 nrseqstate;
u8 nr_seq_ctrls;
u8 nr_event;
u8 nr_resource;
u8 nr_ss_cmp;
struct etmv4_caps caps;
u8 trcid;
u8 trcid_size;
u8 ts_size;
u8 ctxid_size;
u8 vmid_size;
u8 ccsize;
u16 ccitmin;
u8 s_ex_level;
u8 ns_ex_level;
u8 q_support;
u8 os_lock_model;
bool sticky_enable : 1;
bool boot_enable : 1;
bool os_unlock : 1;
bool instrp0 : 1;
bool q_filt : 1;
bool trcbb : 1;
bool trccond : 1;
bool retstack : 1;
bool trccci : 1;
bool trc_error : 1;
bool syncpr : 1;
bool stallctl : 1;
bool sysstall : 1;
bool nooverflow : 1;
bool atbtrig : 1;
bool lpoverride : 1;
bool skip_power_up : 1;
bool paused : 1;
u64 trfcr;
struct etmv4_config config;
struct etmv4_config curr_config;
struct etmv4_config sysfs_config;
struct etmv4_save_state *save_state;
u32 ss_status[ETM_MAX_SS_CMP];
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
};
@ -1099,7 +1115,8 @@ enum etm_addr_ctxtype {
};
extern const struct attribute_group *coresight_etmv4_groups[];
void etm4_config_trace_mode(struct etmv4_config *config);
void etm4_config_trace_mode(struct etmv4_config *config,
const struct etmv4_caps *caps);
u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit);
void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit);

View File

@ -346,16 +346,19 @@ static ssize_t label_show(struct device *dev,
}
static DEVICE_ATTR_RO(label);
static umode_t label_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
static umode_t coresight_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
struct coresight_device *csdev = to_coresight_device(dev);
if (attr == &dev_attr_label.attr) {
if (fwnode_property_present(dev_fwnode(dev), "label"))
return attr->mode;
else
return 0;
} else if (csdev->flags & CORESIGHT_DESC_NO_SYSFS_MODE) {
return 0;
}
return attr->mode;
@ -369,7 +372,7 @@ static struct attribute *coresight_sink_attrs[] = {
static struct attribute_group coresight_sink_group = {
.attrs = coresight_sink_attrs,
.is_visible = label_is_visible,
.is_visible = coresight_attr_is_visible,
};
__ATTRIBUTE_GROUPS(coresight_sink);
@ -381,7 +384,7 @@ static struct attribute *coresight_source_attrs[] = {
static struct attribute_group coresight_source_group = {
.attrs = coresight_source_attrs,
.is_visible = label_is_visible,
.is_visible = coresight_attr_is_visible,
};
__ATTRIBUTE_GROUPS(coresight_source);
@ -392,7 +395,7 @@ static struct attribute *coresight_link_attrs[] = {
static struct attribute_group coresight_link_group = {
.attrs = coresight_link_attrs,
.is_visible = label_is_visible,
.is_visible = coresight_attr_is_visible,
};
__ATTRIBUTE_GROUPS(coresight_link);
@ -403,7 +406,7 @@ static struct attribute *coresight_helper_attrs[] = {
static struct attribute_group coresight_helper_group = {
.attrs = coresight_helper_attrs,
.is_visible = label_is_visible,
.is_visible = coresight_attr_is_visible,
};
__ATTRIBUTE_GROUPS(coresight_helper);

View File

@ -255,7 +255,7 @@ static void trace_noc_remove(struct amba_device *adev)
coresight_trace_id_put_system_id(drvdata->atid);
}
static struct amba_id trace_noc_ids[] = {
static const struct amba_id trace_noc_ids[] = {
{
.id = 0x000f0c00,
.mask = 0x00ffff00,

View File

@ -1348,6 +1348,13 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp
desc.dev = dev;
desc.cpu = cpu;
desc.flags = CORESIGHT_DESC_CPU_BOUND;
/*
* ETE isn't connected to TRBE with a link like other Coresight devices
* and the TRBE driver has been written to always assume Perf mode, so
* Prevent sysfs from being used.
*/
desc.flags |= CORESIGHT_DESC_NO_SYSFS_MODE;
trbe_csdev = coresight_register(&desc);
if (IS_ERR(trbe_csdev))
goto cpu_clear;

View File

@ -142,6 +142,8 @@ struct csdev_access {
})
#define CORESIGHT_DESC_CPU_BOUND BIT(0)
/* Device can't be activated from sysfs, only via Perf. */
#define CORESIGHT_DESC_NO_SYSFS_MODE BIT(1)
/**
* struct coresight_desc - description of a component required from drivers
@ -310,6 +312,8 @@ struct coresight_device {
struct list_head config_csdev_list;
raw_spinlock_t cscfg_csdev_lock;
void *active_cscfg_ctxt;
/* CORESIGHT_DESC_[x] flags */
u32 flags;
};
/*