mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
coresight: etm4x: fix underflow for usage of (nrseqstate - 1)
According to IHI006H Embedded Trace Macrocell Architecture
Specification[0], TRCSEQEVR<n> is implemented only when
TRCIDR5.NUMSEQSTATE is 0b100, in which case n ranges from 0 to 2;
otherwise, TRCIDR5.NUMSEQSTATE is 0b000.
IOW, the number of usage in the initialisation or setting
TRCSEQEVR<n> with drvdata->nrseqstate - 1 in the loop could make
underflow issue when TRCIDR5.NUMSEQSTATE is 0b000.
Therefore, introduce nr_seq_ctrls field and untie it from nrseqstate.
As part of this introduce ETM_MAX_SEQ_TRANSITIONS macro and
apply nr_seq_ctrls and above macro to TRCSEQEVR<n> relevant fields setup.
Link: https://developer.arm.com/documentation/ihi0064/latest/ [0]
Fixes: 2e1cdfe184 ("coresight-etm4x: Adding CoreSight ETM4x driver")
Suggested-by: Leo Yan <leo.yan@arm.com>
Suggested-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20260725113645.57519-3-yeoreum.yun@arm.com
This commit is contained in:
parent
0e1cd4270b
commit
1674d9bff8
|
|
@ -76,7 +76,7 @@ static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
|
|||
} else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) {
|
||||
/* sequencer state control registers */
|
||||
idx = (offset & GENMASK(3, 0)) / 4;
|
||||
if (idx < ETM_MAX_SEQ_STATES) {
|
||||
if (idx < ETM_MAX_SEQ_TRANSITIONS) {
|
||||
reg_csdev->driver_regval = &drvcfg->seq_ctrl[idx];
|
||||
err = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -542,7 +542,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
|
|||
etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR);
|
||||
if (drvdata->nr_pe_cmp)
|
||||
etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR);
|
||||
for (i = 0; i < drvdata->nrseqstate - 1; i++)
|
||||
|
||||
for (i = 0; i < drvdata->nr_seq_ctrls; i++)
|
||||
etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i));
|
||||
if (drvdata->nrseqstate) {
|
||||
etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR);
|
||||
|
|
@ -1508,6 +1509,8 @@ static void etm4_init_arch_data(void *info)
|
|||
drvdata->lpoverride = (etmidr5 & TRCIDR5_LPOVERRIDE) && (!drvdata->skip_power_up);
|
||||
/* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */
|
||||
drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
|
||||
if (drvdata->nrseqstate)
|
||||
drvdata->nr_seq_ctrls = ETM_MAX_SEQ_TRANSITIONS;
|
||||
/* NUMCNTR, bits[30:28] number of counters available for tracing */
|
||||
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
|
||||
|
||||
|
|
@ -1896,7 +1899,7 @@ static int etm4_cpu_save(struct coresight_device *csdev)
|
|||
if (drvdata->nr_pe_cmp)
|
||||
state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
|
||||
|
||||
for (i = 0; i < drvdata->nrseqstate - 1; i++)
|
||||
for (i = 0; i < drvdata->nr_seq_ctrls; i++)
|
||||
state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
|
||||
|
||||
if (drvdata->nrseqstate) {
|
||||
|
|
@ -2009,7 +2012,7 @@ static void etm4_cpu_restore(struct coresight_device *csdev)
|
|||
if (drvdata->nr_pe_cmp)
|
||||
etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
|
||||
|
||||
for (i = 0; i < drvdata->nrseqstate - 1; i++)
|
||||
for (i = 0; i < drvdata->nr_seq_ctrls; i++)
|
||||
etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
|
||||
|
||||
if (drvdata->nrseqstate) {
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ static ssize_t reset_store(struct device *dev,
|
|||
config->vipcssctlr = 0x0;
|
||||
|
||||
/* Disable seq events */
|
||||
for (i = 0; i < drvdata->nrseqstate-1; i++)
|
||||
for (i = 0; i < drvdata->nr_seq_ctrls; i++)
|
||||
config->seq_ctrl[i] = 0x0;
|
||||
config->seq_rst = 0x0;
|
||||
config->seq_state = 0x0;
|
||||
|
|
@ -1395,9 +1395,11 @@ static ssize_t seq_idx_store(struct device *dev,
|
|||
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct etmv4_config *config = &drvdata->config;
|
||||
|
||||
if (!drvdata->nr_seq_ctrls)
|
||||
return -ENOTSUPP;
|
||||
if (kstrtoul(buf, 16, &val))
|
||||
return -EINVAL;
|
||||
if (val >= drvdata->nrseqstate - 1)
|
||||
if (val >= drvdata->nr_seq_ctrls)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -614,6 +614,7 @@ static inline u32 etm4_res_sel_pair(u8 res_sel_idx)
|
|||
#define ETM_MAX_NR_PE 8
|
||||
#define ETMv4_MAX_CNTR 4
|
||||
#define ETM_MAX_SEQ_STATES 4
|
||||
#define ETM_MAX_SEQ_TRANSITIONS 3
|
||||
#define ETM_MAX_EXT_INP_SEL 4
|
||||
#define ETM_MAX_EXT_INP 256
|
||||
#define ETM_MAX_EXT_OUT 4
|
||||
|
|
@ -877,7 +878,7 @@ struct etmv4_config {
|
|||
u32 vipcssctlr;
|
||||
u8 seq_idx;
|
||||
u8 syncfreq;
|
||||
u32 seq_ctrl[ETM_MAX_SEQ_STATES];
|
||||
u32 seq_ctrl[ETM_MAX_SEQ_TRANSITIONS];
|
||||
u32 seq_rst;
|
||||
u32 seq_state;
|
||||
u8 cntr_idx;
|
||||
|
|
@ -928,7 +929,7 @@ struct etmv4_save_state {
|
|||
u32 trcvissctlr;
|
||||
u32 trcvipcssctlr;
|
||||
|
||||
u32 trcseqevr[ETM_MAX_SEQ_STATES];
|
||||
u32 trcseqevr[ETM_MAX_SEQ_TRANSITIONS];
|
||||
u32 trcseqrstevr;
|
||||
u32 trcseqstr;
|
||||
u32 trcextinselr;
|
||||
|
|
@ -981,6 +982,7 @@ struct etmv4_save_state {
|
|||
* @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.
|
||||
|
|
@ -1046,6 +1048,7 @@ struct etmv4_drvdata {
|
|||
u8 numextinsel;
|
||||
u8 numvmidc;
|
||||
u8 nrseqstate;
|
||||
u8 nr_seq_ctrls;
|
||||
u8 nr_event;
|
||||
u8 nr_resource;
|
||||
u8 nr_ss_cmp;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user