Coresight changes for v5.19

This pull request includes:
 
 - Work to uniformise access to the ETMv4 registers, making it easier to
 look for and change register accesses.
 
 - A correction to a probing failure when looking for links between devices.
 
 - The replacement of a call to mutex_lock() with a mutex_trylock() in the panic
 notifier of the cpu-debug infrastructure to avoid a possible deadlock.
 
 Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQFPBAABCgA5FiEEeTrpXvBwUkra1RYWo5FxFnwrV6EFAmJ+iwMbHG1hdGhpZXUu
 cG9pcmllckBsaW5hcm8ub3JnAAoJEKORcRZ8K1ehNv8IAIM/3MxCM4hk/quuzGEy
 L1unk2tQRcn1KoCSjYV4InODf84oBuIIhw24vL1Eh/XaTkv0lg1uy253MgAep7ck
 DdpikxUnEJE+tkfvqzjIrIThSV4ybRMVEIWcx8AkLD0T3KjKFnmoNmsuwOe4N0BK
 ME8HfCyRfdzkEVT8FtGpXPQl4EO+PtOa9TdHNCWNC5/abRJFGDXH0IaPVYouC/Zc
 7YO7s9ANdw+vYYDHAUjE59jv8UjeaOeA5YLzDRnUjREwe1ylW9agjToWotk3sTKV
 p6iznyFodw4Tfjp3I38tCouL+lLEV3OOzDxRT0oa4npJUjY/SyO+RXmvZ0qEMnev
 BjE=
 =v5uO
 -----END PGP SIGNATURE-----

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

Mathieu writes:

Coresight changes for v5.19

This pull request includes:

- Work to uniformise access to the ETMv4 registers, making it easier to
look for and change register accesses.

- A correction to a probing failure when looking for links between devices.

- The replacement of a call to mutex_lock() with a mutex_trylock() in the panic
notifier of the cpu-debug infrastructure to avoid a possible deadlock.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

* tag 'coresight-next-v5.19' of gitolite.kernel.org:pub/scm/linux/kernel/git/coresight/linux:
  coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
  coresight: core: Fix coresight device probe failure issue
  coresight: etm4x: Cleanup TRCRSCTLRn register accesses
  coresight: etm4x: Cleanup TRCBBCTLR register accesses
  coresight: etm4x: Cleanup TRCSSPCICRn register accesses
  coresight: etm4x: Cleanup TRCSSCCRn and TRCSSCSRn register accesses
  coresight: etm4x: Cleanup TRCACATRn register accesses
  coresight: etm3x: Cleanup ETMTECR1 register accesses
  coresight: etm4x: Cleanup TRCVICTLR register accesses
  coresight: etm4x: Cleanup TRCSTALLCTLR register accesses
  coresight: etm4x: Cleanup TRCEVENTCTL1R register accesses
  coresight: etm4x: Cleanup TRCCONFIGR register accesses
  coresight: etm4x: Cleanup TRCIDR5 register accesses
  coresight: etm4x: Cleanup TRCIDR4 register accesses
  coresight: etm4x: Cleanup TRCIDR3 register accesses
  coresight: etm4x: Cleanup TRCIDR2 register accesses
  coresight: etm4x: Cleanup TRCIDR0 register accesses
This commit is contained in:
Greg Kroah-Hartman 2022-05-19 17:16:37 +02:00
commit 9c518db640
7 changed files with 268 additions and 212 deletions

View File

@ -1379,7 +1379,7 @@ static int coresight_fixup_device_conns(struct coresight_device *csdev)
continue; continue;
conn->child_dev = conn->child_dev =
coresight_find_csdev_by_fwnode(conn->child_fwnode); coresight_find_csdev_by_fwnode(conn->child_fwnode);
if (conn->child_dev) { if (conn->child_dev && conn->child_dev->has_conns_grp) {
ret = coresight_make_links(csdev, conn, ret = coresight_make_links(csdev, conn,
conn->child_dev); conn->child_dev);
if (ret) if (ret)
@ -1571,6 +1571,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
int nr_refcnts = 1; int nr_refcnts = 1;
atomic_t *refcnts = NULL; atomic_t *refcnts = NULL;
struct coresight_device *csdev; struct coresight_device *csdev;
bool registered = false;
csdev = kzalloc(sizeof(*csdev), GFP_KERNEL); csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
if (!csdev) { if (!csdev) {
@ -1591,7 +1592,8 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL); refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
if (!refcnts) { if (!refcnts) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_csdev; kfree(csdev);
goto err_out;
} }
csdev->refcnt = refcnts; csdev->refcnt = refcnts;
@ -1616,6 +1618,13 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev)); csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
dev_set_name(&csdev->dev, "%s", desc->name); dev_set_name(&csdev->dev, "%s", desc->name);
/*
* Make sure the device registration and the connection fixup
* are synchronised, so that we don't see uninitialised devices
* on the coresight bus while trying to resolve the connections.
*/
mutex_lock(&coresight_mutex);
ret = device_register(&csdev->dev); ret = device_register(&csdev->dev);
if (ret) { if (ret) {
put_device(&csdev->dev); put_device(&csdev->dev);
@ -1623,7 +1632,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
* All resources are free'd explicitly via * All resources are free'd explicitly via
* coresight_device_release(), triggered from put_device(). * coresight_device_release(), triggered from put_device().
*/ */
goto err_out; goto out_unlock;
} }
if (csdev->type == CORESIGHT_DEV_TYPE_SINK || if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@ -1638,11 +1647,11 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
* from put_device(), which is in turn called from * from put_device(), which is in turn called from
* function device_unregister(). * function device_unregister().
*/ */
goto err_out; goto out_unlock;
} }
} }
/* Device is now registered */
mutex_lock(&coresight_mutex); registered = true;
ret = coresight_create_conns_sysfs_group(csdev); ret = coresight_create_conns_sysfs_group(csdev);
if (!ret) if (!ret)
@ -1652,16 +1661,18 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
if (!ret && cti_assoc_ops && cti_assoc_ops->add) if (!ret && cti_assoc_ops && cti_assoc_ops->add)
cti_assoc_ops->add(csdev); cti_assoc_ops->add(csdev);
out_unlock:
mutex_unlock(&coresight_mutex); mutex_unlock(&coresight_mutex);
if (ret) { /* Success */
if (!ret)
return csdev;
/* Unregister the device if needed */
if (registered) {
coresight_unregister(csdev); coresight_unregister(csdev);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
return csdev;
err_free_csdev:
kfree(csdev);
err_out: err_out:
/* Cleanup the connection information */ /* Cleanup the connection information */
coresight_release_platform_data(NULL, desc->pdata); coresight_release_platform_data(NULL, desc->pdata);

View File

@ -380,9 +380,10 @@ static int debug_notifier_call(struct notifier_block *self,
int cpu; int cpu;
struct debug_drvdata *drvdata; struct debug_drvdata *drvdata;
mutex_lock(&debug_lock); /* Bail out if we can't acquire the mutex or the functionality is off */
if (!mutex_trylock(&debug_lock))
return NOTIFY_DONE;
/* Bail out if the functionality is disabled */
if (!debug_enable) if (!debug_enable)
goto skip_dump; goto skip_dump;
@ -401,7 +402,7 @@ static int debug_notifier_call(struct notifier_block *self,
skip_dump: skip_dump:
mutex_unlock(&debug_lock); mutex_unlock(&debug_lock);
return 0; return NOTIFY_DONE;
} }
static struct notifier_block debug_notifier = { static struct notifier_block debug_notifier = {

View File

@ -204,7 +204,7 @@ void etm_set_default(struct etm_config *config)
* set all bits in register 0x007, the ETMTECR2, to 0 * set all bits in register 0x007, the ETMTECR2, to 0
* set register 0x008, the ETMTEEVR, to 0x6F (TRUE). * set register 0x008, the ETMTEEVR, to 0x6F (TRUE).
*/ */
config->enable_ctrl1 = BIT(24); config->enable_ctrl1 = ETMTECR1_INC_EXC;
config->enable_ctrl2 = 0x0; config->enable_ctrl2 = 0x0;
config->enable_event = ETM_HARD_WIRE_RES_A; config->enable_event = ETM_HARD_WIRE_RES_A;

View File

@ -474,7 +474,7 @@ static ssize_t addr_start_store(struct device *dev,
config->addr_val[idx] = val; config->addr_val[idx] = val;
config->addr_type[idx] = ETM_ADDR_TYPE_START; config->addr_type[idx] = ETM_ADDR_TYPE_START;
config->startstop_ctrl |= (1 << idx); config->startstop_ctrl |= (1 << idx);
config->enable_ctrl1 |= BIT(25); config->enable_ctrl1 |= ETMTECR1_START_STOP;
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;

View File

@ -443,7 +443,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
for (i = 0; i < drvdata->nr_ss_cmp; i++) { for (i = 0; i < drvdata->nr_ss_cmp; i++) {
/* always clear status bit on restart if using single-shot */ /* always clear status bit on restart if using single-shot */
if (config->ss_ctrl[i] || config->ss_pe_cmp[i]) if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
config->ss_status[i] &= ~BIT(31); config->ss_status[i] &= ~TRCSSCSRn_STATUS;
etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i)); etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i)); etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
if (etm4x_sspcicrn_present(drvdata, i)) if (etm4x_sspcicrn_present(drvdata, i))
@ -633,7 +633,7 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
/* Go from generic option to ETMv4 specifics */ /* Go from generic option to ETMv4 specifics */
if (attr->config & BIT(ETM_OPT_CYCACC)) { if (attr->config & BIT(ETM_OPT_CYCACC)) {
config->cfg |= BIT(4); config->cfg |= TRCCONFIGR_CCI;
/* TRM: Must program this for cycacc to work */ /* TRM: Must program this for cycacc to work */
config->ccctlr = ETM_CYC_THRESHOLD_DEFAULT; config->ccctlr = ETM_CYC_THRESHOLD_DEFAULT;
} }
@ -653,14 +653,14 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
goto out; goto out;
/* bit[11], Global timestamp tracing bit */ /* bit[11], Global timestamp tracing bit */
config->cfg |= BIT(11); config->cfg |= TRCCONFIGR_TS;
} }
/* Only trace contextID when runs in root PID namespace */ /* Only trace contextID when runs in root PID namespace */
if ((attr->config & BIT(ETM_OPT_CTXTID)) && if ((attr->config & BIT(ETM_OPT_CTXTID)) &&
task_is_in_init_pid_ns(current)) task_is_in_init_pid_ns(current))
/* bit[6], Context ID tracing bit */ /* bit[6], Context ID tracing bit */
config->cfg |= BIT(ETM4_CFG_BIT_CTXTID); config->cfg |= TRCCONFIGR_CID;
/* /*
* If set bit ETM_OPT_CTXTID2 in perf config, this asks to trace VMID * If set bit ETM_OPT_CTXTID2 in perf config, this asks to trace VMID
@ -672,17 +672,15 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
/* Only trace virtual contextID when runs in root PID namespace */ /* Only trace virtual contextID when runs in root PID namespace */
if (task_is_in_init_pid_ns(current)) if (task_is_in_init_pid_ns(current))
config->cfg |= BIT(ETM4_CFG_BIT_VMID) | config->cfg |= TRCCONFIGR_VMID | TRCCONFIGR_VMIDOPT;
BIT(ETM4_CFG_BIT_VMID_OPT);
} }
/* return stack - enable if selected and supported */ /* return stack - enable if selected and supported */
if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack) if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack)
/* bit[12], Return stack enable bit */ /* bit[12], Return stack enable bit */
config->cfg |= BIT(12); config->cfg |= TRCCONFIGR_RS;
/* /*
* Set any selected configuration and preset. * Set any selected configuration and preset.
@ -1097,107 +1095,67 @@ static void etm4_init_arch_data(void *info)
etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0); etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
/* INSTP0, bits[2:1] P0 tracing support field */ /* INSTP0, bits[2:1] P0 tracing support field */
if (BMVAL(etmidr0, 1, 2) == 0b11) drvdata->instrp0 = !!(FIELD_GET(TRCIDR0_INSTP0_MASK, etmidr0) == 0b11);
drvdata->instrp0 = true;
else
drvdata->instrp0 = false;
/* TRCBB, bit[5] Branch broadcast tracing support bit */ /* TRCBB, bit[5] Branch broadcast tracing support bit */
if (BMVAL(etmidr0, 5, 5)) drvdata->trcbb = !!(etmidr0 & TRCIDR0_TRCBB);
drvdata->trcbb = true;
else
drvdata->trcbb = false;
/* TRCCOND, bit[6] Conditional instruction tracing support bit */ /* TRCCOND, bit[6] Conditional instruction tracing support bit */
if (BMVAL(etmidr0, 6, 6)) drvdata->trccond = !!(etmidr0 & TRCIDR0_TRCCOND);
drvdata->trccond = true;
else
drvdata->trccond = false;
/* TRCCCI, bit[7] Cycle counting instruction bit */ /* TRCCCI, bit[7] Cycle counting instruction bit */
if (BMVAL(etmidr0, 7, 7)) drvdata->trccci = !!(etmidr0 & TRCIDR0_TRCCCI);
drvdata->trccci = true;
else
drvdata->trccci = false;
/* RETSTACK, bit[9] Return stack bit */ /* RETSTACK, bit[9] Return stack bit */
if (BMVAL(etmidr0, 9, 9)) drvdata->retstack = !!(etmidr0 & TRCIDR0_RETSTACK);
drvdata->retstack = true;
else
drvdata->retstack = false;
/* NUMEVENT, bits[11:10] Number of events field */ /* NUMEVENT, bits[11:10] Number of events field */
drvdata->nr_event = BMVAL(etmidr0, 10, 11); drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
/* QSUPP, bits[16:15] Q element support field */ /* QSUPP, bits[16:15] Q element support field */
drvdata->q_support = BMVAL(etmidr0, 15, 16); drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
/* TSSIZE, bits[28:24] Global timestamp size field */ /* TSSIZE, bits[28:24] Global timestamp size field */
drvdata->ts_size = BMVAL(etmidr0, 24, 28); drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0);
/* maximum size of resources */ /* maximum size of resources */
etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2); etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
/* CIDSIZE, bits[9:5] Indicates the Context ID size */ /* CIDSIZE, bits[9:5] Indicates the Context ID size */
drvdata->ctxid_size = BMVAL(etmidr2, 5, 9); drvdata->ctxid_size = FIELD_GET(TRCIDR2_CIDSIZE_MASK, etmidr2);
/* VMIDSIZE, bits[14:10] Indicates the VMID size */ /* VMIDSIZE, bits[14:10] Indicates the VMID size */
drvdata->vmid_size = BMVAL(etmidr2, 10, 14); drvdata->vmid_size = FIELD_GET(TRCIDR2_VMIDSIZE_MASK, etmidr2);
/* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */
drvdata->ccsize = BMVAL(etmidr2, 25, 28); drvdata->ccsize = FIELD_GET(TRCIDR2_CCSIZE_MASK, etmidr2);
etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3); etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3);
/* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */
drvdata->ccitmin = BMVAL(etmidr3, 0, 11); drvdata->ccitmin = FIELD_GET(TRCIDR3_CCITMIN_MASK, etmidr3);
/* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
drvdata->s_ex_level = BMVAL(etmidr3, 16, 19); drvdata->s_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_S_MASK, etmidr3);
drvdata->config.s_ex_level = drvdata->s_ex_level; drvdata->config.s_ex_level = drvdata->s_ex_level;
/* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23); drvdata->ns_ex_level = FIELD_GET(TRCIDR3_EXLEVEL_NS_MASK, etmidr3);
/* /*
* TRCERR, bit[24] whether a trace unit can trace a * TRCERR, bit[24] whether a trace unit can trace a
* system error exception. * system error exception.
*/ */
if (BMVAL(etmidr3, 24, 24)) drvdata->trc_error = !!(etmidr3 & TRCIDR3_TRCERR);
drvdata->trc_error = true;
else
drvdata->trc_error = false;
/* SYNCPR, bit[25] implementation has a fixed synchronization period? */ /* SYNCPR, bit[25] implementation has a fixed synchronization period? */
if (BMVAL(etmidr3, 25, 25)) drvdata->syncpr = !!(etmidr3 & TRCIDR3_SYNCPR);
drvdata->syncpr = true;
else
drvdata->syncpr = false;
/* STALLCTL, bit[26] is stall control implemented? */ /* STALLCTL, bit[26] is stall control implemented? */
if (BMVAL(etmidr3, 26, 26)) drvdata->stallctl = !!(etmidr3 & TRCIDR3_STALLCTL);
drvdata->stallctl = true;
else
drvdata->stallctl = false;
/* SYSSTALL, bit[27] implementation can support stall control? */ /* SYSSTALL, bit[27] implementation can support stall control? */
if (BMVAL(etmidr3, 27, 27)) drvdata->sysstall = !!(etmidr3 & TRCIDR3_SYSSTALL);
drvdata->sysstall = true;
else
drvdata->sysstall = false;
/* /*
* NUMPROC - the number of PEs available for tracing, 5bits * NUMPROC - the number of PEs available for tracing, 5bits
* = TRCIDR3.bits[13:12]bits[30:28] * = TRCIDR3.bits[13:12]bits[30:28]
* bits[4:3] = TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0) * bits[4:3] = TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0)
* bits[3:0] = TRCIDR3.bits[30:28] * bits[3:0] = TRCIDR3.bits[30:28]
*/ */
drvdata->nr_pe = (BMVAL(etmidr3, 12, 13) << 3) | BMVAL(etmidr3, 28, 30); drvdata->nr_pe = (FIELD_GET(TRCIDR3_NUMPROC_HI_MASK, etmidr3) << 3) |
FIELD_GET(TRCIDR3_NUMPROC_LO_MASK, etmidr3);
/* NOOVERFLOW, bit[31] is trace overflow prevention supported */ /* NOOVERFLOW, bit[31] is trace overflow prevention supported */
if (BMVAL(etmidr3, 31, 31)) drvdata->nooverflow = !!(etmidr3 & TRCIDR3_NOOVERFLOW);
drvdata->nooverflow = true;
else
drvdata->nooverflow = false;
/* number of resources trace unit supports */ /* number of resources trace unit supports */
etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4); etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4);
/* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */
drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3); drvdata->nr_addr_cmp = FIELD_GET(TRCIDR4_NUMACPAIRS_MASK, etmidr4);
/* NUMPC, bits[15:12] number of PE comparator inputs for tracing */ /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
drvdata->nr_pe_cmp = BMVAL(etmidr4, 12, 15); drvdata->nr_pe_cmp = FIELD_GET(TRCIDR4_NUMPC_MASK, etmidr4);
/* /*
* NUMRSPAIR, bits[19:16] * NUMRSPAIR, bits[19:16]
* The number of resource pairs conveyed by the HW starts at 0, i.e a * The number of resource pairs conveyed by the HW starts at 0, i.e a
@ -1208,7 +1166,7 @@ static void etm4_init_arch_data(void *info)
* the default TRUE and FALSE resource selectors are omitted. * the default TRUE and FALSE resource selectors are omitted.
* Otherwise for values 0x1 and above the number is N + 1 as per v4.2. * Otherwise for values 0x1 and above the number is N + 1 as per v4.2.
*/ */
drvdata->nr_resource = BMVAL(etmidr4, 16, 19); drvdata->nr_resource = FIELD_GET(TRCIDR4_NUMRSPAIR_MASK, etmidr4);
if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0)) if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0))
drvdata->nr_resource += 1; drvdata->nr_resource += 1;
/* /*
@ -1216,45 +1174,39 @@ static void etm4_init_arch_data(void *info)
* comparator control for tracing. Read any status regs as these * comparator control for tracing. Read any status regs as these
* also contain RO capability data. * also contain RO capability data.
*/ */
drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23); drvdata->nr_ss_cmp = FIELD_GET(TRCIDR4_NUMSSCC_MASK, etmidr4);
for (i = 0; i < drvdata->nr_ss_cmp; i++) { for (i = 0; i < drvdata->nr_ss_cmp; i++) {
drvdata->config.ss_status[i] = drvdata->config.ss_status[i] =
etm4x_relaxed_read32(csa, TRCSSCSRn(i)); etm4x_relaxed_read32(csa, TRCSSCSRn(i));
} }
/* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */ /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
drvdata->numcidc = BMVAL(etmidr4, 24, 27); drvdata->numcidc = FIELD_GET(TRCIDR4_NUMCIDC_MASK, etmidr4);
/* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */ /* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */
drvdata->numvmidc = BMVAL(etmidr4, 28, 31); drvdata->numvmidc = FIELD_GET(TRCIDR4_NUMVMIDC_MASK, etmidr4);
etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5); etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5);
/* NUMEXTIN, bits[8:0] number of external inputs implemented */ /* NUMEXTIN, bits[8:0] number of external inputs implemented */
drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8); drvdata->nr_ext_inp = FIELD_GET(TRCIDR5_NUMEXTIN_MASK, etmidr5);
/* TRACEIDSIZE, bits[21:16] indicates the trace ID width */ /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */
drvdata->trcid_size = BMVAL(etmidr5, 16, 21); drvdata->trcid_size = FIELD_GET(TRCIDR5_TRACEIDSIZE_MASK, etmidr5);
/* ATBTRIG, bit[22] implementation can support ATB triggers? */ /* ATBTRIG, bit[22] implementation can support ATB triggers? */
if (BMVAL(etmidr5, 22, 22)) drvdata->atbtrig = !!(etmidr5 & TRCIDR5_ATBTRIG);
drvdata->atbtrig = true;
else
drvdata->atbtrig = false;
/* /*
* LPOVERRIDE, bit[23] implementation supports * LPOVERRIDE, bit[23] implementation supports
* low-power state override * low-power state override
*/ */
if (BMVAL(etmidr5, 23, 23) && (!drvdata->skip_power_up)) drvdata->lpoverride = (etmidr5 & TRCIDR5_LPOVERRIDE) && (!drvdata->skip_power_up);
drvdata->lpoverride = true;
else
drvdata->lpoverride = false;
/* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */ /* NUMSEQSTATE, bits[27:25] number of sequencer states implemented */
drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
/* NUMCNTR, bits[30:28] number of counters available for tracing */ /* NUMCNTR, bits[30:28] number of counters available for tracing */
drvdata->nr_cntr = BMVAL(etmidr5, 28, 30); drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
etm4_cs_lock(drvdata, csa); etm4_cs_lock(drvdata, csa);
cpu_detect_trace_filtering(drvdata); cpu_detect_trace_filtering(drvdata);
} }
static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config) static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
{ {
return etm4_get_access_type(config) << TRCVICTLR_EXLEVEL_SHIFT; return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
} }
/* Set ELx trace filter access in the TRCVICTLR register */ /* Set ELx trace filter access in the TRCVICTLR register */
@ -1280,7 +1232,7 @@ static void etm4_set_default_config(struct etmv4_config *config)
config->ts_ctrl = 0x0; config->ts_ctrl = 0x0;
/* TRCVICTLR::EVENT = 0x01, select the always on logic */ /* TRCVICTLR::EVENT = 0x01, select the always on logic */
config->vinst_ctrl = BIT(0); config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
/* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering */ /* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering */
etm4_set_victlr_access(config); etm4_set_victlr_access(config);
@ -1389,7 +1341,7 @@ static void etm4_set_default_filter(struct etmv4_config *config)
* TRCVICTLR::SSSTATUS == 1, the start-stop logic is * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
* in the started state * in the started state
*/ */
config->vinst_ctrl |= BIT(9); config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
config->mode |= ETM_MODE_VIEWINST_STARTSTOP; config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
/* No start-stop filtering for ViewInst */ /* No start-stop filtering for ViewInst */
@ -1493,7 +1445,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
* TRCVICTLR::SSSTATUS == 1, the start-stop logic is * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
* in the started state * in the started state
*/ */
config->vinst_ctrl |= BIT(9); config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
/* No start-stop filtering for ViewInst */ /* No start-stop filtering for ViewInst */
config->vissctlr = 0x0; config->vissctlr = 0x0;
@ -1521,7 +1473,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
* etm4_disable_perf(). * etm4_disable_perf().
*/ */
if (filters->ssstatus) if (filters->ssstatus)
config->vinst_ctrl |= BIT(9); config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
/* No include/exclude filtering for ViewInst */ /* No include/exclude filtering for ViewInst */
config->viiectlr = 0x0; config->viiectlr = 0x0;

View File

@ -22,7 +22,7 @@ static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
* TRCACATRn.TYPE bit[1:0]: type of comparison * TRCACATRn.TYPE bit[1:0]: type of comparison
* the trace unit performs * the trace unit performs
*/ */
if (BMVAL(config->addr_acc[idx], 0, 1) == ETM_INSTR_ADDR) { if (FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]) == TRCACATRn_TYPE_ADDR) {
if (idx % 2 != 0) if (idx % 2 != 0)
return -EINVAL; return -EINVAL;
@ -180,12 +180,12 @@ static ssize_t reset_store(struct device *dev,
/* Disable data tracing: do not trace load and store data transfers */ /* Disable data tracing: do not trace load and store data transfers */
config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE); config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
config->cfg &= ~(BIT(1) | BIT(2)); config->cfg &= ~(TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE);
/* Disable data value and data address tracing */ /* Disable data value and data address tracing */
config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR | config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
ETM_MODE_DATA_TRACE_VAL); ETM_MODE_DATA_TRACE_VAL);
config->cfg &= ~(BIT(16) | BIT(17)); config->cfg &= ~(TRCCONFIGR_DA | TRCCONFIGR_DV);
/* Disable all events tracing */ /* Disable all events tracing */
config->eventctrl0 = 0x0; config->eventctrl0 = 0x0;
@ -206,11 +206,11 @@ static ssize_t reset_store(struct device *dev,
* started state. ARM recommends start-stop logic is set before * started state. ARM recommends start-stop logic is set before
* each trace run. * each trace run.
*/ */
config->vinst_ctrl = BIT(0); config->vinst_ctrl = FIELD_PREP(TRCVICTLR_EVENT_MASK, 0x01);
if (drvdata->nr_addr_cmp > 0) { if (drvdata->nr_addr_cmp > 0) {
config->mode |= ETM_MODE_VIEWINST_STARTSTOP; config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
/* SSSTATUS, bit[9] */ /* SSSTATUS, bit[9] */
config->vinst_ctrl |= BIT(9); config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
} }
/* No address range filtering for ViewInst */ /* No address range filtering for ViewInst */
@ -304,134 +304,134 @@ static ssize_t mode_store(struct device *dev,
if (drvdata->instrp0 == true) { if (drvdata->instrp0 == true) {
/* start by clearing instruction P0 field */ /* start by clearing instruction P0 field */
config->cfg &= ~(BIT(1) | BIT(2)); config->cfg &= ~TRCCONFIGR_INSTP0_LOAD_STORE;
if (config->mode & ETM_MODE_LOAD) if (config->mode & ETM_MODE_LOAD)
/* 0b01 Trace load instructions as P0 instructions */ /* 0b01 Trace load instructions as P0 instructions */
config->cfg |= BIT(1); config->cfg |= TRCCONFIGR_INSTP0_LOAD;
if (config->mode & ETM_MODE_STORE) if (config->mode & ETM_MODE_STORE)
/* 0b10 Trace store instructions as P0 instructions */ /* 0b10 Trace store instructions as P0 instructions */
config->cfg |= BIT(2); config->cfg |= TRCCONFIGR_INSTP0_STORE;
if (config->mode & ETM_MODE_LOAD_STORE) if (config->mode & ETM_MODE_LOAD_STORE)
/* /*
* 0b11 Trace load and store instructions * 0b11 Trace load and store instructions
* as P0 instructions * as P0 instructions
*/ */
config->cfg |= BIT(1) | BIT(2); config->cfg |= TRCCONFIGR_INSTP0_LOAD_STORE;
} }
/* bit[3], Branch broadcast mode */ /* bit[3], Branch broadcast mode */
if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb == true)) if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb == true))
config->cfg |= BIT(3); config->cfg |= TRCCONFIGR_BB;
else else
config->cfg &= ~BIT(3); config->cfg &= ~TRCCONFIGR_BB;
/* bit[4], Cycle counting instruction trace bit */ /* bit[4], Cycle counting instruction trace bit */
if ((config->mode & ETMv4_MODE_CYCACC) && if ((config->mode & ETMv4_MODE_CYCACC) &&
(drvdata->trccci == true)) (drvdata->trccci == true))
config->cfg |= BIT(4); config->cfg |= TRCCONFIGR_CCI;
else else
config->cfg &= ~BIT(4); config->cfg &= ~TRCCONFIGR_CCI;
/* bit[6], Context ID tracing bit */ /* bit[6], Context ID tracing bit */
if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size)) if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size))
config->cfg |= BIT(6); config->cfg |= TRCCONFIGR_CID;
else else
config->cfg &= ~BIT(6); config->cfg &= ~TRCCONFIGR_CID;
if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size)) if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size))
config->cfg |= BIT(7); config->cfg |= TRCCONFIGR_VMID;
else else
config->cfg &= ~BIT(7); config->cfg &= ~TRCCONFIGR_VMID;
/* bits[10:8], Conditional instruction tracing bit */ /* bits[10:8], Conditional instruction tracing bit */
mode = ETM_MODE_COND(config->mode); mode = ETM_MODE_COND(config->mode);
if (drvdata->trccond == true) { if (drvdata->trccond == true) {
config->cfg &= ~(BIT(8) | BIT(9) | BIT(10)); config->cfg &= ~TRCCONFIGR_COND_MASK;
config->cfg |= mode << 8; config->cfg |= mode << __bf_shf(TRCCONFIGR_COND_MASK);
} }
/* bit[11], Global timestamp tracing bit */ /* bit[11], Global timestamp tracing bit */
if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size)) if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size))
config->cfg |= BIT(11); config->cfg |= TRCCONFIGR_TS;
else else
config->cfg &= ~BIT(11); config->cfg &= ~TRCCONFIGR_TS;
/* bit[12], Return stack enable bit */ /* bit[12], Return stack enable bit */
if ((config->mode & ETM_MODE_RETURNSTACK) && if ((config->mode & ETM_MODE_RETURNSTACK) &&
(drvdata->retstack == true)) (drvdata->retstack == true))
config->cfg |= BIT(12); config->cfg |= TRCCONFIGR_RS;
else else
config->cfg &= ~BIT(12); config->cfg &= ~TRCCONFIGR_RS;
/* bits[14:13], Q element enable field */ /* bits[14:13], Q element enable field */
mode = ETM_MODE_QELEM(config->mode); mode = ETM_MODE_QELEM(config->mode);
/* start by clearing QE bits */ /* start by clearing QE bits */
config->cfg &= ~(BIT(13) | BIT(14)); config->cfg &= ~(TRCCONFIGR_QE_W_COUNTS | TRCCONFIGR_QE_WO_COUNTS);
/* /*
* if supported, Q elements with instruction counts are enabled. * if supported, Q elements with instruction counts are enabled.
* Always set the low bit for any requested mode. Valid combos are * Always set the low bit for any requested mode. Valid combos are
* 0b00, 0b01 and 0b11. * 0b00, 0b01 and 0b11.
*/ */
if (mode && drvdata->q_support) if (mode && drvdata->q_support)
config->cfg |= BIT(13); config->cfg |= TRCCONFIGR_QE_W_COUNTS;
/* /*
* if supported, Q elements with and without instruction * if supported, Q elements with and without instruction
* counts are enabled * counts are enabled
*/ */
if ((mode & BIT(1)) && (drvdata->q_support & BIT(1))) if ((mode & BIT(1)) && (drvdata->q_support & BIT(1)))
config->cfg |= BIT(14); config->cfg |= TRCCONFIGR_QE_WO_COUNTS;
/* bit[11], AMBA Trace Bus (ATB) trigger enable bit */ /* bit[11], AMBA Trace Bus (ATB) trigger enable bit */
if ((config->mode & ETM_MODE_ATB_TRIGGER) && if ((config->mode & ETM_MODE_ATB_TRIGGER) &&
(drvdata->atbtrig == true)) (drvdata->atbtrig == true))
config->eventctrl1 |= BIT(11); config->eventctrl1 |= TRCEVENTCTL1R_ATB;
else else
config->eventctrl1 &= ~BIT(11); config->eventctrl1 &= ~TRCEVENTCTL1R_ATB;
/* bit[12], Low-power state behavior override bit */ /* bit[12], Low-power state behavior override bit */
if ((config->mode & ETM_MODE_LPOVERRIDE) && if ((config->mode & ETM_MODE_LPOVERRIDE) &&
(drvdata->lpoverride == true)) (drvdata->lpoverride == true))
config->eventctrl1 |= BIT(12); config->eventctrl1 |= TRCEVENTCTL1R_LPOVERRIDE;
else else
config->eventctrl1 &= ~BIT(12); config->eventctrl1 &= ~TRCEVENTCTL1R_LPOVERRIDE;
/* bit[8], Instruction stall bit */ /* bit[8], Instruction stall bit */
if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl == true)) if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl == true))
config->stall_ctrl |= BIT(8); config->stall_ctrl |= TRCSTALLCTLR_ISTALL;
else else
config->stall_ctrl &= ~BIT(8); config->stall_ctrl &= ~TRCSTALLCTLR_ISTALL;
/* bit[10], Prioritize instruction trace bit */ /* bit[10], Prioritize instruction trace bit */
if (config->mode & ETM_MODE_INSTPRIO) if (config->mode & ETM_MODE_INSTPRIO)
config->stall_ctrl |= BIT(10); config->stall_ctrl |= TRCSTALLCTLR_INSTPRIORITY;
else else
config->stall_ctrl &= ~BIT(10); config->stall_ctrl &= ~TRCSTALLCTLR_INSTPRIORITY;
/* bit[13], Trace overflow prevention bit */ /* bit[13], Trace overflow prevention bit */
if ((config->mode & ETM_MODE_NOOVERFLOW) && if ((config->mode & ETM_MODE_NOOVERFLOW) &&
(drvdata->nooverflow == true)) (drvdata->nooverflow == true))
config->stall_ctrl |= BIT(13); config->stall_ctrl |= TRCSTALLCTLR_NOOVERFLOW;
else else
config->stall_ctrl &= ~BIT(13); config->stall_ctrl &= ~TRCSTALLCTLR_NOOVERFLOW;
/* bit[9] Start/stop logic control bit */ /* bit[9] Start/stop logic control bit */
if (config->mode & ETM_MODE_VIEWINST_STARTSTOP) if (config->mode & ETM_MODE_VIEWINST_STARTSTOP)
config->vinst_ctrl |= BIT(9); config->vinst_ctrl |= TRCVICTLR_SSSTATUS;
else else
config->vinst_ctrl &= ~BIT(9); config->vinst_ctrl &= ~TRCVICTLR_SSSTATUS;
/* bit[10], Whether a trace unit must trace a Reset exception */ /* bit[10], Whether a trace unit must trace a Reset exception */
if (config->mode & ETM_MODE_TRACE_RESET) if (config->mode & ETM_MODE_TRACE_RESET)
config->vinst_ctrl |= BIT(10); config->vinst_ctrl |= TRCVICTLR_TRCRESET;
else else
config->vinst_ctrl &= ~BIT(10); config->vinst_ctrl &= ~TRCVICTLR_TRCRESET;
/* bit[11], Whether a trace unit must trace a system error exception */ /* bit[11], Whether a trace unit must trace a system error exception */
if ((config->mode & ETM_MODE_TRACE_ERR) && if ((config->mode & ETM_MODE_TRACE_ERR) &&
(drvdata->trc_error == true)) (drvdata->trc_error == true))
config->vinst_ctrl |= BIT(11); config->vinst_ctrl |= TRCVICTLR_TRCERR;
else else
config->vinst_ctrl &= ~BIT(11); config->vinst_ctrl &= ~TRCVICTLR_TRCERR;
if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER)) if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
etm4_config_trace_mode(config); etm4_config_trace_mode(config);
@ -534,7 +534,7 @@ static ssize_t event_instren_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config; struct etmv4_config *config = &drvdata->config;
val = BMVAL(config->eventctrl1, 0, 3); val = FIELD_GET(TRCEVENTCTL1R_INSTEN_MASK, config->eventctrl1);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -551,23 +551,28 @@ static ssize_t event_instren_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
/* start by clearing all instruction event enable bits */ /* start by clearing all instruction event enable bits */
config->eventctrl1 &= ~(BIT(0) | BIT(1) | BIT(2) | BIT(3)); config->eventctrl1 &= ~TRCEVENTCTL1R_INSTEN_MASK;
switch (drvdata->nr_event) { switch (drvdata->nr_event) {
case 0x0: case 0x0:
/* generate Event element for event 1 */ /* generate Event element for event 1 */
config->eventctrl1 |= val & BIT(1); config->eventctrl1 |= val & TRCEVENTCTL1R_INSTEN_1;
break; break;
case 0x1: case 0x1:
/* generate Event element for event 1 and 2 */ /* generate Event element for event 1 and 2 */
config->eventctrl1 |= val & (BIT(0) | BIT(1)); config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 | TRCEVENTCTL1R_INSTEN_1);
break; break;
case 0x2: case 0x2:
/* generate Event element for event 1, 2 and 3 */ /* generate Event element for event 1, 2 and 3 */
config->eventctrl1 |= val & (BIT(0) | BIT(1) | BIT(2)); config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
TRCEVENTCTL1R_INSTEN_1 |
TRCEVENTCTL1R_INSTEN_2);
break; break;
case 0x3: case 0x3:
/* generate Event element for all 4 events */ /* generate Event element for all 4 events */
config->eventctrl1 |= val & 0xF; config->eventctrl1 |= val & (TRCEVENTCTL1R_INSTEN_0 |
TRCEVENTCTL1R_INSTEN_1 |
TRCEVENTCTL1R_INSTEN_2 |
TRCEVENTCTL1R_INSTEN_3);
break; break;
default: default:
break; break;
@ -702,10 +707,10 @@ static ssize_t bb_ctrl_store(struct device *dev,
* individual range comparators. If include then at least 1 * individual range comparators. If include then at least 1
* range must be selected. * range must be selected.
*/ */
if ((val & BIT(8)) && (BMVAL(val, 0, 7) == 0)) if ((val & TRCBBCTLR_MODE) && (FIELD_GET(TRCBBCTLR_RANGE_MASK, val) == 0))
return -EINVAL; return -EINVAL;
config->bb_ctrl = val & GENMASK(8, 0); config->bb_ctrl = val & (TRCBBCTLR_MODE | TRCBBCTLR_RANGE_MASK);
return size; return size;
} }
static DEVICE_ATTR_RW(bb_ctrl); static DEVICE_ATTR_RW(bb_ctrl);
@ -718,7 +723,7 @@ static ssize_t event_vinst_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config; struct etmv4_config *config = &drvdata->config;
val = config->vinst_ctrl & ETMv4_EVENT_MASK; val = FIELD_GET(TRCVICTLR_EVENT_MASK, config->vinst_ctrl);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -734,9 +739,9 @@ static ssize_t event_vinst_store(struct device *dev,
return -EINVAL; return -EINVAL;
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
val &= ETMv4_EVENT_MASK; val &= TRCVICTLR_EVENT_MASK >> __bf_shf(TRCVICTLR_EVENT_MASK);
config->vinst_ctrl &= ~ETMv4_EVENT_MASK; config->vinst_ctrl &= ~TRCVICTLR_EVENT_MASK;
config->vinst_ctrl |= val; config->vinst_ctrl |= FIELD_PREP(TRCVICTLR_EVENT_MASK, val);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -750,7 +755,7 @@ static ssize_t s_exlevel_vinst_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config; struct etmv4_config *config = &drvdata->config;
val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_S_MASK) >> TRCVICTLR_EXLEVEL_S_SHIFT; val = FIELD_GET(TRCVICTLR_EXLEVEL_S_MASK, config->vinst_ctrl);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -767,10 +772,10 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
/* clear all EXLEVEL_S bits */ /* clear all EXLEVEL_S bits */
config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK); config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_S_MASK;
/* enable instruction tracing for corresponding exception level */ /* enable instruction tracing for corresponding exception level */
val &= drvdata->s_ex_level; val &= drvdata->s_ex_level;
config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_S_SHIFT); config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_S_MASK);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -785,7 +790,7 @@ static ssize_t ns_exlevel_vinst_show(struct device *dev,
struct etmv4_config *config = &drvdata->config; struct etmv4_config *config = &drvdata->config;
/* EXLEVEL_NS, bits[23:20] */ /* EXLEVEL_NS, bits[23:20] */
val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_NS_MASK) >> TRCVICTLR_EXLEVEL_NS_SHIFT; val = FIELD_GET(TRCVICTLR_EXLEVEL_NS_MASK, config->vinst_ctrl);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -802,10 +807,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
/* clear EXLEVEL_NS bits */ /* clear EXLEVEL_NS bits */
config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK); config->vinst_ctrl &= ~TRCVICTLR_EXLEVEL_NS_MASK;
/* enable instruction tracing for corresponding exception level */ /* enable instruction tracing for corresponding exception level */
val &= drvdata->ns_ex_level; val &= drvdata->ns_ex_level;
config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT); config->vinst_ctrl |= val << __bf_shf(TRCVICTLR_EXLEVEL_NS_MASK);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -858,11 +863,11 @@ static ssize_t addr_instdatatype_show(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
val = BMVAL(config->addr_acc[idx], 0, 1); val = FIELD_GET(TRCACATRn_TYPE_MASK, config->addr_acc[idx]);
len = scnprintf(buf, PAGE_SIZE, "%s\n", len = scnprintf(buf, PAGE_SIZE, "%s\n",
val == ETM_INSTR_ADDR ? "instr" : val == TRCACATRn_TYPE_ADDR ? "instr" :
(val == ETM_DATA_LOAD_ADDR ? "data_load" : (val == TRCACATRn_TYPE_DATA_LOAD_ADDR ? "data_load" :
(val == ETM_DATA_STORE_ADDR ? "data_store" : (val == TRCACATRn_TYPE_DATA_STORE_ADDR ? "data_store" :
"data_load_store"))); "data_load_store")));
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return len; return len;
@ -886,7 +891,7 @@ static ssize_t addr_instdatatype_store(struct device *dev,
idx = config->addr_idx; idx = config->addr_idx;
if (!strcmp(str, "instr")) if (!strcmp(str, "instr"))
/* TYPE, bits[1:0] */ /* TYPE, bits[1:0] */
config->addr_acc[idx] &= ~(BIT(0) | BIT(1)); config->addr_acc[idx] &= ~TRCACATRn_TYPE_MASK;
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
@ -1144,7 +1149,7 @@ static ssize_t addr_ctxtype_show(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
/* CONTEXTTYPE, bits[3:2] */ /* CONTEXTTYPE, bits[3:2] */
val = BMVAL(config->addr_acc[idx], 2, 3); val = FIELD_GET(TRCACATRn_CONTEXTTYPE_MASK, config->addr_acc[idx]);
len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" : len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
(val == ETM_CTX_CTXID ? "ctxid" : (val == ETM_CTX_CTXID ? "ctxid" :
(val == ETM_CTX_VMID ? "vmid" : "all"))); (val == ETM_CTX_VMID ? "vmid" : "all")));
@ -1170,18 +1175,18 @@ static ssize_t addr_ctxtype_store(struct device *dev,
idx = config->addr_idx; idx = config->addr_idx;
if (!strcmp(str, "none")) if (!strcmp(str, "none"))
/* start by clearing context type bits */ /* start by clearing context type bits */
config->addr_acc[idx] &= ~(BIT(2) | BIT(3)); config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_MASK;
else if (!strcmp(str, "ctxid")) { else if (!strcmp(str, "ctxid")) {
/* 0b01 The trace unit performs a Context ID */ /* 0b01 The trace unit performs a Context ID */
if (drvdata->numcidc) { if (drvdata->numcidc) {
config->addr_acc[idx] |= BIT(2); config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_CTXID;
config->addr_acc[idx] &= ~BIT(3); config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_VMID;
} }
} else if (!strcmp(str, "vmid")) { } else if (!strcmp(str, "vmid")) {
/* 0b10 The trace unit performs a VMID */ /* 0b10 The trace unit performs a VMID */
if (drvdata->numvmidc) { if (drvdata->numvmidc) {
config->addr_acc[idx] &= ~BIT(2); config->addr_acc[idx] &= ~TRCACATRn_CONTEXTTYPE_CTXID;
config->addr_acc[idx] |= BIT(3); config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
} }
} else if (!strcmp(str, "all")) { } else if (!strcmp(str, "all")) {
/* /*
@ -1189,9 +1194,9 @@ static ssize_t addr_ctxtype_store(struct device *dev,
* comparison and a VMID * comparison and a VMID
*/ */
if (drvdata->numcidc) if (drvdata->numcidc)
config->addr_acc[idx] |= BIT(2); config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_CTXID;
if (drvdata->numvmidc) if (drvdata->numvmidc)
config->addr_acc[idx] |= BIT(3); config->addr_acc[idx] |= TRCACATRn_CONTEXTTYPE_VMID;
} }
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
@ -1210,7 +1215,7 @@ static ssize_t addr_context_show(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
/* context ID comparator bits[6:4] */ /* context ID comparator bits[6:4] */
val = BMVAL(config->addr_acc[idx], 4, 6); val = FIELD_GET(TRCACATRn_CONTEXT_MASK, config->addr_acc[idx]);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -1235,8 +1240,8 @@ static ssize_t addr_context_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
/* clear context ID comparator bits[6:4] */ /* clear context ID comparator bits[6:4] */
config->addr_acc[idx] &= ~(BIT(4) | BIT(5) | BIT(6)); config->addr_acc[idx] &= ~TRCACATRn_CONTEXT_MASK;
config->addr_acc[idx] |= (val << 4); config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_CONTEXT_MASK);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -1253,7 +1258,7 @@ static ssize_t addr_exlevel_s_ns_show(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
val = BMVAL(config->addr_acc[idx], 8, 14); val = FIELD_GET(TRCACATRn_EXLEVEL_MASK, config->addr_acc[idx]);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
} }
@ -1270,14 +1275,14 @@ static ssize_t addr_exlevel_s_ns_store(struct device *dev,
if (kstrtoul(buf, 0, &val)) if (kstrtoul(buf, 0, &val))
return -EINVAL; return -EINVAL;
if (val & ~((GENMASK(14, 8) >> 8))) if (val & ~(TRCACATRn_EXLEVEL_MASK >> __bf_shf(TRCACATRn_EXLEVEL_MASK)))
return -EINVAL; return -EINVAL;
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->addr_idx; idx = config->addr_idx;
/* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */ /* clear Exlevel_ns & Exlevel_s bits[14:12, 11:8], bit[15] is res0 */
config->addr_acc[idx] &= ~(GENMASK(14, 8)); config->addr_acc[idx] &= ~TRCACATRn_EXLEVEL_MASK;
config->addr_acc[idx] |= (val << 8); config->addr_acc[idx] |= val << __bf_shf(TRCACATRn_EXLEVEL_MASK);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -1721,8 +1726,11 @@ static ssize_t res_ctrl_store(struct device *dev,
/* For odd idx pair inversal bit is RES0 */ /* For odd idx pair inversal bit is RES0 */
if (idx % 2 != 0) if (idx % 2 != 0)
/* PAIRINV, bit[21] */ /* PAIRINV, bit[21] */
val &= ~BIT(21); val &= ~TRCRSCTLRn_PAIRINV;
config->res_ctrl[idx] = val & GENMASK(21, 0); config->res_ctrl[idx] = val & (TRCRSCTLRn_PAIRINV |
TRCRSCTLRn_INV |
TRCRSCTLRn_GROUP_MASK |
TRCRSCTLRn_SELECT_MASK);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -1787,9 +1795,9 @@ static ssize_t sshot_ctrl_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->ss_idx; idx = config->ss_idx;
config->ss_ctrl[idx] = val & GENMASK(24, 0); config->ss_ctrl[idx] = FIELD_PREP(TRCSSCCRn_SAC_ARC_RST_MASK, val);
/* must clear bit 31 in related status register on programming */ /* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~BIT(31); config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }
@ -1837,9 +1845,9 @@ static ssize_t sshot_pe_ctrl_store(struct device *dev,
spin_lock(&drvdata->spinlock); spin_lock(&drvdata->spinlock);
idx = config->ss_idx; idx = config->ss_idx;
config->ss_pe_cmp[idx] = val & GENMASK(7, 0); config->ss_pe_cmp[idx] = FIELD_PREP(TRCSSPCICRn_PC_MASK, val);
/* must clear bit 31 in related status register on programming */ /* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~BIT(31); config->ss_status[idx] &= ~TRCSSCSRn_STATUS;
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
return size; return size;
} }

View File

@ -130,6 +130,104 @@
#define TRCRSR_TA BIT(12) #define TRCRSR_TA BIT(12)
/*
* Bit positions of registers that are defined above, in the sysreg.h style
* of _MASK for multi bit fields and BIT() for single bits.
*/
#define TRCIDR0_INSTP0_MASK GENMASK(2, 1)
#define TRCIDR0_TRCBB BIT(5)
#define TRCIDR0_TRCCOND BIT(6)
#define TRCIDR0_TRCCCI BIT(7)
#define TRCIDR0_RETSTACK BIT(9)
#define TRCIDR0_NUMEVENT_MASK GENMASK(11, 10)
#define TRCIDR0_QSUPP_MASK GENMASK(16, 15)
#define TRCIDR0_TSSIZE_MASK GENMASK(28, 24)
#define TRCIDR2_CIDSIZE_MASK GENMASK(9, 5)
#define TRCIDR2_VMIDSIZE_MASK GENMASK(14, 10)
#define TRCIDR2_CCSIZE_MASK GENMASK(28, 25)
#define TRCIDR3_CCITMIN_MASK GENMASK(11, 0)
#define TRCIDR3_EXLEVEL_S_MASK GENMASK(19, 16)
#define TRCIDR3_EXLEVEL_NS_MASK GENMASK(23, 20)
#define TRCIDR3_TRCERR BIT(24)
#define TRCIDR3_SYNCPR BIT(25)
#define TRCIDR3_STALLCTL BIT(26)
#define TRCIDR3_SYSSTALL BIT(27)
#define TRCIDR3_NUMPROC_LO_MASK GENMASK(30, 28)
#define TRCIDR3_NUMPROC_HI_MASK GENMASK(13, 12)
#define TRCIDR3_NOOVERFLOW BIT(31)
#define TRCIDR4_NUMACPAIRS_MASK GENMASK(3, 0)
#define TRCIDR4_NUMPC_MASK GENMASK(15, 12)
#define TRCIDR4_NUMRSPAIR_MASK GENMASK(19, 16)
#define TRCIDR4_NUMSSCC_MASK GENMASK(23, 20)
#define TRCIDR4_NUMCIDC_MASK GENMASK(27, 24)
#define TRCIDR4_NUMVMIDC_MASK GENMASK(31, 28)
#define TRCIDR5_NUMEXTIN_MASK GENMASK(8, 0)
#define TRCIDR5_TRACEIDSIZE_MASK GENMASK(21, 16)
#define TRCIDR5_ATBTRIG BIT(22)
#define TRCIDR5_LPOVERRIDE BIT(23)
#define TRCIDR5_NUMSEQSTATE_MASK GENMASK(27, 25)
#define TRCIDR5_NUMCNTR_MASK GENMASK(30, 28)
#define TRCCONFIGR_INSTP0_LOAD BIT(1)
#define TRCCONFIGR_INSTP0_STORE BIT(2)
#define TRCCONFIGR_INSTP0_LOAD_STORE (TRCCONFIGR_INSTP0_LOAD | TRCCONFIGR_INSTP0_STORE)
#define TRCCONFIGR_BB BIT(3)
#define TRCCONFIGR_CCI BIT(4)
#define TRCCONFIGR_CID BIT(6)
#define TRCCONFIGR_VMID BIT(7)
#define TRCCONFIGR_COND_MASK GENMASK(10, 8)
#define TRCCONFIGR_TS BIT(11)
#define TRCCONFIGR_RS BIT(12)
#define TRCCONFIGR_QE_W_COUNTS BIT(13)
#define TRCCONFIGR_QE_WO_COUNTS BIT(14)
#define TRCCONFIGR_VMIDOPT BIT(15)
#define TRCCONFIGR_DA BIT(16)
#define TRCCONFIGR_DV BIT(17)
#define TRCEVENTCTL1R_INSTEN_MASK GENMASK(3, 0)
#define TRCEVENTCTL1R_INSTEN_0 BIT(0)
#define TRCEVENTCTL1R_INSTEN_1 BIT(1)
#define TRCEVENTCTL1R_INSTEN_2 BIT(2)
#define TRCEVENTCTL1R_INSTEN_3 BIT(3)
#define TRCEVENTCTL1R_ATB BIT(11)
#define TRCEVENTCTL1R_LPOVERRIDE BIT(12)
#define TRCSTALLCTLR_ISTALL BIT(8)
#define TRCSTALLCTLR_INSTPRIORITY BIT(10)
#define TRCSTALLCTLR_NOOVERFLOW BIT(13)
#define TRCVICTLR_EVENT_MASK GENMASK(7, 0)
#define TRCVICTLR_SSSTATUS BIT(9)
#define TRCVICTLR_TRCRESET BIT(10)
#define TRCVICTLR_TRCERR BIT(11)
#define TRCVICTLR_EXLEVEL_MASK GENMASK(22, 16)
#define TRCVICTLR_EXLEVEL_S_MASK GENMASK(19, 16)
#define TRCVICTLR_EXLEVEL_NS_MASK GENMASK(22, 20)
#define TRCACATRn_TYPE_MASK GENMASK(1, 0)
#define TRCACATRn_CONTEXTTYPE_MASK GENMASK(3, 2)
#define TRCACATRn_CONTEXTTYPE_CTXID BIT(2)
#define TRCACATRn_CONTEXTTYPE_VMID BIT(3)
#define TRCACATRn_CONTEXT_MASK GENMASK(6, 4)
#define TRCACATRn_EXLEVEL_MASK GENMASK(14, 8)
#define TRCSSCSRn_STATUS BIT(31)
#define TRCSSCCRn_SAC_ARC_RST_MASK GENMASK(24, 0)
#define TRCSSPCICRn_PC_MASK GENMASK(7, 0)
#define TRCBBCTLR_MODE BIT(8)
#define TRCBBCTLR_RANGE_MASK GENMASK(7, 0)
#define TRCRSCTLRn_PAIRINV BIT(21)
#define TRCRSCTLRn_INV BIT(20)
#define TRCRSCTLRn_GROUP_MASK GENMASK(19, 16)
#define TRCRSCTLRn_SELECT_MASK GENMASK(15, 0)
/* /*
* System instructions to access ETM registers. * System instructions to access ETM registers.
* See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
@ -630,23 +728,9 @@
#define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */ #define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */
#define ETM_EXLEVEL_NS_HYP BIT(6) /* NonSecure EL2 */ #define ETM_EXLEVEL_NS_HYP BIT(6) /* NonSecure EL2 */
#define ETM_EXLEVEL_MASK (GENMASK(6, 0))
#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0))
#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4))
/* access level controls in TRCACATRn */ /* access level controls in TRCACATRn */
#define TRCACATR_EXLEVEL_SHIFT 8 #define TRCACATR_EXLEVEL_SHIFT 8
/* access level control in TRCVICTLR */
#define TRCVICTLR_EXLEVEL_SHIFT 16
#define TRCVICTLR_EXLEVEL_S_SHIFT 16
#define TRCVICTLR_EXLEVEL_NS_SHIFT 20
/* secure / non secure masks - TRCVICTLR, IDR3 */
#define TRCVICTLR_EXLEVEL_MASK (ETM_EXLEVEL_MASK << TRCVICTLR_EXLEVEL_SHIFT)
#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_SHIFT)
#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_SHIFT)
#define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8 #define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8
#define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT) #define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
#define ETM_TRCIDR1_ARCH_MAJOR(x) \ #define ETM_TRCIDR1_ARCH_MAJOR(x) \
@ -986,10 +1070,10 @@ struct etmv4_drvdata {
/* Address comparator access types */ /* Address comparator access types */
enum etm_addr_acctype { enum etm_addr_acctype {
ETM_INSTR_ADDR, TRCACATRn_TYPE_ADDR,
ETM_DATA_LOAD_ADDR, TRCACATRn_TYPE_DATA_LOAD_ADDR,
ETM_DATA_STORE_ADDR, TRCACATRn_TYPE_DATA_STORE_ADDR,
ETM_DATA_LOAD_STORE_ADDR, TRCACATRn_TYPE_DATA_LOAD_STORE_ADDR,
}; };
/* Address comparator context types */ /* Address comparator context types */