2020-10-28 22:13:58

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 00/26] coresight: Support for ETM system instructions

CoreSight ETMv4.4 obsoletes memory mapped access to ETM and
mandates the system instructions for registers.
This also implies that they may not be on the amba bus.
Right now all the CoreSight components are accessed via memory
map. Also, we have some common routines in coresight generic
code driver (e.g, CS_LOCK, claim/disclaim), which assume the
mmio. In order to preserve the generic algorithms at a single
place and to allow dynamic switch for ETMs, this series introduces
an abstraction layer for accessing a coresight device. It is
designed such that the mmio access are fast tracked (i.e, without
an indirect function call).

This will also help us to get rid of the driver+attribute specific
sysfs show/store routines and replace them with a single routine
to access a given register offset (which can be embedded in the
dev_ext_attribute). This is not currently implemented in the series,
but can be achieved.

Further we switch the generic routines to work with the abstraction.
With this in place, we refactor the etm4x code a bit to allow for
supporting the system instructions with very little new code. The
changes also switch to using the system instructions by default
even when we may have an MMIO.

We use TRCDEVARCH for the detection of the ETM component, which
is a standard register as per CoreSight architecture, rather than
the etm specific id register TRCIDR1. This is for making sure
that we are able to detect the ETM via system instructions accurately,
when the the trace unit could be anything (etm or a custom trace unit).
To keep the backward compatibility for any existing broken impelementation
which may not implement TRCDEVARCH, we fall back to TRCIDR1. Also
this covers us for the changes in the future architecture [0].

The series has been mildly tested on a model for system instructions.
I would really appreciate any testing on real hardware.

Applies on coresight/next.

[0] https://developer.arm.com/docs/ddi0601/g/aarch64-system-registers/trcidr1

Known issues:
Checkpatch failure for "coresight: etm4x: Add sysreg access helpers" :

ERROR: Macros with complex values should be enclosed in parentheses
#121: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:153:
+#define CASE_READ(res, x) \
+ case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }


I don't know how to fix that without breaking the build ! Suggestions
welcome.


Changes since V2:
- Several fixes to the ETM register accesses. Access a register
when it is present.
- Add support for TRCIDR3.NUMPROCS for v4.2+
- Drop OS lock detection. Use software lock only in case of mmio.
- Fix issues with the Exception level masks (Mike Leach)
- Fall back to using TRCIDR1 when TRCDEVARCH is not "present"
- Use a generic notion of ETM architecture (rather than using
the encoding as in registers)
- Fixed some checkpatch issues.
- Add support for Self Hosted tracing Arm v8.4 extensions. (Mike
Leach)
Originally written by Jonathan, refactored and cleaned up.
- Changed the dts compatible string to "arm,coresight-etm-sysreg"
(Mike Leach)

Changes since V1:
- Flip the switch for iomem from no_iomem to io_mem in csdev_access.
- Split patches for claim/disclaim and CS_LOCK/UNLOCK conversions.
- Move device access initialisation for etm4x to the target CPU
- Cleanup secure exception level mask handling.
- Switch to use TRCDEVARCH for ETM component discovery. This
is for making
- Check the availability of OS/Software Locks before using them.


Suzuki K Poulose (26):
coresight: etm4x: Fix accesses to TRCVMIDCTLR1
coresight: etm4x: Fix accesses to TRCCIDCTLR1
coresight: etm4x: Update TRCIDR3.NUMPROCS handling to match v4.2
coresight: etm4x: Fix accesses to TRCPROCSELR
coresight: etm4x: Handle TRCVIPCSSCTLR accesses
coresight: etm4x: Handle access to TRCSSPCICRn
coresight: Introduce device access abstraction
coresight: tpiu: Prepare for using coresight device access abstraction
coresight: Convert coresight_timeout to use access abstraction
coresight: Convert claim/disclaim operations to use access wrappers
coresight: etm4x: Always read the registers on the host CPU
coresight: etm4x: Convert all register accesses
coresight: etm4x: Add commentary on the registers
coresight: etm4x: Add sysreg access helpers
coresight: etm4x: Define DEVARCH register fields
coresight: etm4x: Check for Software Lock
coresight: etm4x: Cleanup secure exception level masks
coresight: etm4x: Clean up exception level masks
coresight: etm4x: Detect access early on the target CPU
coresight: etm4x: Handle ETM architecture version
coresight: etm4x: Use TRCDEVARCH for component discovery
coresight: etm4x: Add necessary synchronization for sysreg access
coresight: etm4x: Detect system instructions support
coresight: etm4x: Refactor probing routine
coresight: etm4x: Add support for sysreg only devices
dts: bindings: coresight: ETM system register access only units

.../devicetree/bindings/arm/coresight.txt | 5 +-
drivers/hwtracing/coresight/coresight-catu.c | 12 +-
drivers/hwtracing/coresight/coresight-core.c | 130 ++-
.../hwtracing/coresight/coresight-cti-core.c | 18 +-
drivers/hwtracing/coresight/coresight-etb10.c | 10 +-
.../coresight/coresight-etm3x-core.c | 9 +-
.../coresight/coresight-etm4x-core.c | 758 +++++++++++-------
.../coresight/coresight-etm4x-sysfs.c | 44 +-
drivers/hwtracing/coresight/coresight-etm4x.h | 501 +++++++++++-
.../hwtracing/coresight/coresight-funnel.c | 7 +-
.../coresight/coresight-replicator.c | 17 +-
drivers/hwtracing/coresight/coresight-stm.c | 4 +-
.../hwtracing/coresight/coresight-tmc-core.c | 16 +-
.../hwtracing/coresight/coresight-tmc-etf.c | 10 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
drivers/hwtracing/coresight/coresight-tpiu.c | 31 +-
include/linux/coresight.h | 230 +++++-
17 files changed, 1376 insertions(+), 430 deletions(-)

--
2.24.1


2020-10-29 00:37:11

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 16/26] coresight: etm4x: Check for Software Lock

The Software lock is not implemented for system instructions
based accesses. So, skip the lock register access in such
cases.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 40 ++++++++++++-------
1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index a5c914b16e59..a12d58a04c5d 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -121,6 +121,21 @@ static void etm4_os_lock(struct etmv4_drvdata *drvdata)
isb();
}

+static void etm4_cs_lock(struct etmv4_drvdata *drvdata,
+ struct csdev_access *csa)
+{
+ /* Software Lock is only accessible via memory mapped interface */
+ if (csa->io_mem)
+ CS_LOCK(csa->base);
+}
+
+static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
+ struct csdev_access *csa)
+{
+ if (csa->io_mem)
+ CS_UNLOCK(csa->base);
+}
+
static bool etm4_arch_supported(u8 arch)
{
/* Mask out the minor version number */
@@ -160,8 +175,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
struct device *etm_dev = &csdev->dev;
struct csdev_access *csa = &csdev->access;

- CS_UNLOCK(drvdata->base);
-
+ etm4_cs_unlock(drvdata, csa);
etm4_os_unlock(drvdata);

rc = coresight_claim_device_unlocked(csdev);
@@ -262,7 +276,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
isb();

done:
- CS_LOCK(drvdata->base);
+ etm4_cs_lock(drvdata, csa);

dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n",
drvdata->cpu, rc);
@@ -519,7 +533,7 @@ static void etm4_disable_hw(void *info)
struct csdev_access *csa = &csdev->access;
int i;

- CS_UNLOCK(drvdata->base);
+ etm4_cs_unlock(drvdata, csa);

if (!drvdata->skip_power_up) {
/* power can be removed from the trace unit now */
@@ -560,8 +574,7 @@ static void etm4_disable_hw(void *info)
}

coresight_disclaim_device_unlocked(csdev);
-
- CS_LOCK(drvdata->base);
+ etm4_cs_lock(drvdata, csa);

dev_dbg(&drvdata->csdev->dev,
"cpu: %d disable smp call done\n", drvdata->cpu);
@@ -671,8 +684,7 @@ static void etm4_init_arch_data(void *info)

/* Make sure all registers are accessible */
etm4_os_unlock_csa(drvdata, csa);
-
- CS_UNLOCK(drvdata->base);
+ etm4_cs_unlock(drvdata, csa);

/* find all capabilities of the tracing unit */
etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
@@ -837,7 +849,7 @@ static void etm4_init_arch_data(void *info)
drvdata->nrseqstate = BMVAL(etmidr5, 25, 27);
/* NUMCNTR, bits[30:28] number of counters available for tracing */
drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
- CS_LOCK(drvdata->base);
+ etm4_cs_lock(drvdata, csa);
}

/* Set ELx trace filter access in the TRCVICTLR register */
@@ -1218,8 +1230,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
dsb(sy);
isb();

- CS_UNLOCK(drvdata->base);
-
+ etm4_cs_unlock(drvdata, csa);
/* Lock the OS lock to disable trace and external debugger access */
etm4_os_lock(drvdata);

@@ -1330,7 +1341,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);

out:
- CS_LOCK(drvdata->base);
+ etm4_cs_lock(drvdata, csa);
return ret;
}

@@ -1341,8 +1352,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
struct csdev_access *csa = &tmp_csa;

- CS_UNLOCK(drvdata->base);
-
+ etm4_cs_unlock(drvdata, csa);
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);

etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
@@ -1426,7 +1436,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)

/* Unlock the OS lock to re-enable trace and external debug access */
etm4_os_unlock(drvdata);
- CS_LOCK(drvdata->base);
+ etm4_cs_lock(drvdata, csa);
}

static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
--
2.24.1

2020-10-29 01:00:51

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 04/26] coresight: etm4x: Fix accesses to TRCPROCSELR

TRCPROCSELR is not implemented if the TRCIDR3.NUMPROC == 0. Skip
accessing the register in such cases.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index cbbe755d1d16..28dd278f6d47 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -124,8 +124,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
-
- writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
/* nothing specific implemented */
writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
@@ -1185,7 +1185,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state = drvdata->save_state;

state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR);
- state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
state->trcconfigr = readl(drvdata->base + TRCCONFIGR);
state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR);
state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R);
@@ -1292,7 +1293,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);

writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR);
- writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
+ if (drvdata->nr_pe)
+ writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR);
writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR);
writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R);
--
2.24.1

2020-10-29 01:00:54

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 08/26] coresight: tpiu: Prepare for using coresight device access abstraction

Prepare the TPIU driver to make use of the CoreSight device access
abstraction layer. The driver touches the device even before the
coresight device is registered. Thus we could be accessing the
devices without a csdev. As we are about to use the abstraction
layer for accessing the device, pass in the access directly
to avoid having to deal with the un-initialised csdev.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-tpiu.c | 30 +++++++++-----------
1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index dfa3b91d0281..98c4a029854c 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -60,49 +60,45 @@ struct tpiu_drvdata {
struct coresight_device *csdev;
};

-static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
+static void tpiu_enable_hw(struct csdev_access *csa)
{
- CS_UNLOCK(drvdata->base);
+ CS_UNLOCK(csa->base);

/* TODO: fill this up */

- CS_LOCK(drvdata->base);
+ CS_LOCK(csa->base);
}

static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
{
- struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- tpiu_enable_hw(drvdata);
+ tpiu_enable_hw(&csdev->access);
atomic_inc(csdev->refcnt);
dev_dbg(&csdev->dev, "TPIU enabled\n");
return 0;
}

-static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
+static void tpiu_disable_hw(struct csdev_access *csa)
{
- CS_UNLOCK(drvdata->base);
+ CS_UNLOCK(csa->base);

/* Clear formatter and stop on flush */
- writel_relaxed(FFCR_STOP_FI, drvdata->base + TPIU_FFCR);
+ csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR);
/* Generate manual flush */
- writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
+ csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR);
/* Wait for flush to complete */
- coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
+ coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
/* Wait for formatter to stop */
- coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
+ coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);

- CS_LOCK(drvdata->base);
+ CS_LOCK(csa->base);
}

static int tpiu_disable(struct coresight_device *csdev)
{
- struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
if (atomic_dec_return(csdev->refcnt))
return -EBUSY;

- tpiu_disable_hw(drvdata);
+ tpiu_disable_hw(&csdev->access);

dev_dbg(&csdev->dev, "TPIU disabled\n");
return 0;
@@ -152,7 +148,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
desc.access = CSDEV_ACCESS_IOMEM(base);

/* Disable tpiu to support older devices */
- tpiu_disable_hw(drvdata);
+ tpiu_disable_hw(&desc.access);

pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata))
--
2.24.1

2020-10-29 01:00:56

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 14/26] coresight: etm4x: Add sysreg access helpers

ETMv4.4 architecture defines the system instructions for accessing
ETM via register accesses. Add basic support for accessing a given
register via system instructions.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 39 ++
drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++--
2 files changed, 365 insertions(+), 22 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 4af7d45dfe63..90b80982c615 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);

static enum cpuhp_state hp_online;

+u64 etm4x_sysreg_read(struct csdev_access *csa,
+ u32 offset,
+ bool _relaxed,
+ bool _64bit)
+{
+ u64 res = 0;
+
+ switch (offset) {
+ ETM4x_READ_CASES(res)
+ default :
+ WARN_ONCE(1, "etm4x: trying to read unsupported register @%x\n",
+ offset);
+ }
+
+ if (!_relaxed)
+ __iormb(res); /* Imitate the !relaxed I/O helpers */
+
+ return res;
+}
+
+void etm4x_sysreg_write(struct csdev_access *csa,
+ u64 val,
+ u32 offset,
+ bool _relaxed,
+ bool _64bit)
+{
+ if (!_relaxed)
+ __iowmb(); /* Imitate the !relaxed I/O helpers */
+ if (!_64bit)
+ val &= GENMASK(31, 0);
+
+ switch (offset) {
+ ETM4x_WRITE_CASES(val)
+ default :
+ WARN_ONCE(1, "etm4x: trying to write to unsupported register @%x\n",
+ offset);
+ }
+}
+
static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
{
/* Writing 0 to TRCOSLAR unlocks the trace registers */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 510828c73db6..5cf71b30a652 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -125,29 +125,323 @@
#define TRCCIDR2 0xFF8
#define TRCCIDR3 0xFFC

-#define etm4x_relaxed_read32(csa, offset) \
- readl_relaxed((csa)->base + (offset))
-
-#define etm4x_read32(csa, offset) \
- readl((csa)->base + (offset))
-
-#define etm4x_relaxed_write32(csa, val, offset) \
- writel_relaxed((val), (csa)->base + (offset))
-
-#define etm4x_write32(csa, val, offset) \
- writel((val), (csa)->base + (offset))
-
-#define etm4x_relaxed_read64(csa, offset) \
- readq_relaxed((csa)->base + (offset))
-
-#define etm4x_read64(csa, offset) \
- readq((csa)->base + (offset))
-
-#define etm4x_relaxed_write64(csa, val, offset) \
- writeq_relaxed((val), (csa)->base + (offset))
+/*
+ * System instructions to access ETM registers.
+ * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
+ */
+#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2)
+
+#define ETM4x_CRn(n) (((n) >> 7) & 0x7)
+#define ETM4x_Op2(n) (((n) >> 4) & 0x7)
+#define ETM4x_CRm(n) ((n) & 0xf)
+
+#include <asm/sysreg.h>
+#define ETM4x_REG_NUM_TO_SYSREG(n) \
+ sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n))
+
+#define READ_ETM4x_REG(reg) \
+ read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg)))
+#define WRITE_ETM4x_REG(val, reg) \
+ write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg)))
+
+#define read_etm4x_sysreg_const_offset(offset) \
+ READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset))
+
+#define write_etm4x_sysreg_const_offset(val, offset) \
+ WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset))
+
+#define CASE_READ(res, x) \
+ case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
+
+#define CASE_WRITE(val, x) \
+ case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; }
+
+#define CASE_LIST(op, val) \
+ CASE_##op((val), TRCPRGCTLR) \
+ CASE_##op((val), TRCPROCSELR) \
+ CASE_##op((val), TRCSTATR) \
+ CASE_##op((val), TRCCONFIGR) \
+ CASE_##op((val), TRCAUXCTLR) \
+ CASE_##op((val), TRCEVENTCTL0R) \
+ CASE_##op((val), TRCEVENTCTL1R) \
+ CASE_##op((val), TRCSTALLCTLR) \
+ CASE_##op((val), TRCTSCTLR) \
+ CASE_##op((val), TRCSYNCPR) \
+ CASE_##op((val), TRCCCCTLR) \
+ CASE_##op((val), TRCBBCTLR) \
+ CASE_##op((val), TRCTRACEIDR) \
+ CASE_##op((val), TRCQCTLR) \
+ CASE_##op((val), TRCVICTLR) \
+ CASE_##op((val), TRCVIIECTLR) \
+ CASE_##op((val), TRCVISSCTLR) \
+ CASE_##op((val), TRCVIPCSSCTLR) \
+ CASE_##op((val), TRCVDCTLR) \
+ CASE_##op((val), TRCVDSACCTLR) \
+ CASE_##op((val), TRCVDARCCTLR) \
+ CASE_##op((val), TRCSEQEVRn(0)) \
+ CASE_##op((val), TRCSEQEVRn(1)) \
+ CASE_##op((val), TRCSEQEVRn(2)) \
+ CASE_##op((val), TRCSEQRSTEVR) \
+ CASE_##op((val), TRCSEQSTR) \
+ CASE_##op((val), TRCEXTINSELR) \
+ CASE_##op((val), TRCCNTRLDVRn(0)) \
+ CASE_##op((val), TRCCNTRLDVRn(1)) \
+ CASE_##op((val), TRCCNTRLDVRn(2)) \
+ CASE_##op((val), TRCCNTRLDVRn(3)) \
+ CASE_##op((val), TRCCNTCTLRn(0)) \
+ CASE_##op((val), TRCCNTCTLRn(1)) \
+ CASE_##op((val), TRCCNTCTLRn(2)) \
+ CASE_##op((val), TRCCNTCTLRn(3)) \
+ CASE_##op((val), TRCCNTVRn(0)) \
+ CASE_##op((val), TRCCNTVRn(1)) \
+ CASE_##op((val), TRCCNTVRn(2)) \
+ CASE_##op((val), TRCCNTVRn(3)) \
+ CASE_##op((val), TRCIDR8) \
+ CASE_##op((val), TRCIDR9) \
+ CASE_##op((val), TRCIDR10) \
+ CASE_##op((val), TRCIDR11) \
+ CASE_##op((val), TRCIDR12) \
+ CASE_##op((val), TRCIDR13) \
+ CASE_##op((val), TRCIMSPECn(0)) \
+ CASE_##op((val), TRCIMSPECn(1)) \
+ CASE_##op((val), TRCIMSPECn(2)) \
+ CASE_##op((val), TRCIMSPECn(3)) \
+ CASE_##op((val), TRCIMSPECn(4)) \
+ CASE_##op((val), TRCIMSPECn(5)) \
+ CASE_##op((val), TRCIMSPECn(6)) \
+ CASE_##op((val), TRCIMSPECn(7)) \
+ CASE_##op((val), TRCIDR0) \
+ CASE_##op((val), TRCIDR1) \
+ CASE_##op((val), TRCIDR2) \
+ CASE_##op((val), TRCIDR3) \
+ CASE_##op((val), TRCIDR4) \
+ CASE_##op((val), TRCIDR5) \
+ CASE_##op((val), TRCIDR6) \
+ CASE_##op((val), TRCIDR7) \
+ CASE_##op((val), TRCRSCTLRn(2)) \
+ CASE_##op((val), TRCRSCTLRn(3)) \
+ CASE_##op((val), TRCRSCTLRn(4)) \
+ CASE_##op((val), TRCRSCTLRn(5)) \
+ CASE_##op((val), TRCRSCTLRn(6)) \
+ CASE_##op((val), TRCRSCTLRn(7)) \
+ CASE_##op((val), TRCRSCTLRn(8)) \
+ CASE_##op((val), TRCRSCTLRn(9)) \
+ CASE_##op((val), TRCRSCTLRn(10)) \
+ CASE_##op((val), TRCRSCTLRn(11)) \
+ CASE_##op((val), TRCRSCTLRn(12)) \
+ CASE_##op((val), TRCRSCTLRn(13)) \
+ CASE_##op((val), TRCRSCTLRn(14)) \
+ CASE_##op((val), TRCRSCTLRn(15)) \
+ CASE_##op((val), TRCRSCTLRn(16)) \
+ CASE_##op((val), TRCRSCTLRn(17)) \
+ CASE_##op((val), TRCRSCTLRn(18)) \
+ CASE_##op((val), TRCRSCTLRn(19)) \
+ CASE_##op((val), TRCRSCTLRn(20)) \
+ CASE_##op((val), TRCRSCTLRn(21)) \
+ CASE_##op((val), TRCRSCTLRn(22)) \
+ CASE_##op((val), TRCRSCTLRn(23)) \
+ CASE_##op((val), TRCRSCTLRn(24)) \
+ CASE_##op((val), TRCRSCTLRn(25)) \
+ CASE_##op((val), TRCRSCTLRn(26)) \
+ CASE_##op((val), TRCRSCTLRn(27)) \
+ CASE_##op((val), TRCRSCTLRn(28)) \
+ CASE_##op((val), TRCRSCTLRn(29)) \
+ CASE_##op((val), TRCRSCTLRn(30)) \
+ CASE_##op((val), TRCRSCTLRn(31)) \
+ CASE_##op((val), TRCSSCCRn(0)) \
+ CASE_##op((val), TRCSSCCRn(1)) \
+ CASE_##op((val), TRCSSCCRn(2)) \
+ CASE_##op((val), TRCSSCCRn(3)) \
+ CASE_##op((val), TRCSSCCRn(4)) \
+ CASE_##op((val), TRCSSCCRn(5)) \
+ CASE_##op((val), TRCSSCCRn(6)) \
+ CASE_##op((val), TRCSSCCRn(7)) \
+ CASE_##op((val), TRCSSCSRn(0)) \
+ CASE_##op((val), TRCSSCSRn(1)) \
+ CASE_##op((val), TRCSSCSRn(2)) \
+ CASE_##op((val), TRCSSCSRn(3)) \
+ CASE_##op((val), TRCSSCSRn(4)) \
+ CASE_##op((val), TRCSSCSRn(5)) \
+ CASE_##op((val), TRCSSCSRn(6)) \
+ CASE_##op((val), TRCSSCSRn(7)) \
+ CASE_##op((val), TRCSSPCICRn(0)) \
+ CASE_##op((val), TRCSSPCICRn(1)) \
+ CASE_##op((val), TRCSSPCICRn(2)) \
+ CASE_##op((val), TRCSSPCICRn(3)) \
+ CASE_##op((val), TRCSSPCICRn(4)) \
+ CASE_##op((val), TRCSSPCICRn(5)) \
+ CASE_##op((val), TRCSSPCICRn(6)) \
+ CASE_##op((val), TRCSSPCICRn(7)) \
+ CASE_##op((val), TRCOSLAR) \
+ CASE_##op((val), TRCOSLSR) \
+ CASE_##op((val), TRCPDCR) \
+ CASE_##op((val), TRCPDSR) \
+ CASE_##op((val), TRCACVRn(0)) \
+ CASE_##op((val), TRCACVRn(1)) \
+ CASE_##op((val), TRCACVRn(2)) \
+ CASE_##op((val), TRCACVRn(3)) \
+ CASE_##op((val), TRCACVRn(4)) \
+ CASE_##op((val), TRCACVRn(5)) \
+ CASE_##op((val), TRCACVRn(6)) \
+ CASE_##op((val), TRCACVRn(7)) \
+ CASE_##op((val), TRCACVRn(8)) \
+ CASE_##op((val), TRCACVRn(9)) \
+ CASE_##op((val), TRCACVRn(10)) \
+ CASE_##op((val), TRCACVRn(11)) \
+ CASE_##op((val), TRCACVRn(12)) \
+ CASE_##op((val), TRCACVRn(13)) \
+ CASE_##op((val), TRCACVRn(14)) \
+ CASE_##op((val), TRCACVRn(15)) \
+ CASE_##op((val), TRCACATRn(0)) \
+ CASE_##op((val), TRCACATRn(1)) \
+ CASE_##op((val), TRCACATRn(2)) \
+ CASE_##op((val), TRCACATRn(3)) \
+ CASE_##op((val), TRCACATRn(4)) \
+ CASE_##op((val), TRCACATRn(5)) \
+ CASE_##op((val), TRCACATRn(6)) \
+ CASE_##op((val), TRCACATRn(7)) \
+ CASE_##op((val), TRCACATRn(8)) \
+ CASE_##op((val), TRCACATRn(9)) \
+ CASE_##op((val), TRCACATRn(10)) \
+ CASE_##op((val), TRCACATRn(11)) \
+ CASE_##op((val), TRCACATRn(12)) \
+ CASE_##op((val), TRCACATRn(13)) \
+ CASE_##op((val), TRCACATRn(14)) \
+ CASE_##op((val), TRCACATRn(15)) \
+ CASE_##op((val), TRCDVCVRn(0)) \
+ CASE_##op((val), TRCDVCVRn(1)) \
+ CASE_##op((val), TRCDVCVRn(2)) \
+ CASE_##op((val), TRCDVCVRn(3)) \
+ CASE_##op((val), TRCDVCVRn(4)) \
+ CASE_##op((val), TRCDVCVRn(5)) \
+ CASE_##op((val), TRCDVCVRn(6)) \
+ CASE_##op((val), TRCDVCVRn(7)) \
+ CASE_##op((val), TRCDVCMRn(0)) \
+ CASE_##op((val), TRCDVCMRn(1)) \
+ CASE_##op((val), TRCDVCMRn(2)) \
+ CASE_##op((val), TRCDVCMRn(3)) \
+ CASE_##op((val), TRCDVCMRn(4)) \
+ CASE_##op((val), TRCDVCMRn(5)) \
+ CASE_##op((val), TRCDVCMRn(6)) \
+ CASE_##op((val), TRCDVCMRn(7)) \
+ CASE_##op((val), TRCCIDCVRn(0)) \
+ CASE_##op((val), TRCCIDCVRn(1)) \
+ CASE_##op((val), TRCCIDCVRn(2)) \
+ CASE_##op((val), TRCCIDCVRn(3)) \
+ CASE_##op((val), TRCCIDCVRn(4)) \
+ CASE_##op((val), TRCCIDCVRn(5)) \
+ CASE_##op((val), TRCCIDCVRn(6)) \
+ CASE_##op((val), TRCCIDCVRn(7)) \
+ CASE_##op((val), TRCVMIDCVRn(0)) \
+ CASE_##op((val), TRCVMIDCVRn(1)) \
+ CASE_##op((val), TRCVMIDCVRn(2)) \
+ CASE_##op((val), TRCVMIDCVRn(3)) \
+ CASE_##op((val), TRCVMIDCVRn(4)) \
+ CASE_##op((val), TRCVMIDCVRn(5)) \
+ CASE_##op((val), TRCVMIDCVRn(6)) \
+ CASE_##op((val), TRCVMIDCVRn(7)) \
+ CASE_##op((val), TRCCIDCCTLR0) \
+ CASE_##op((val), TRCCIDCCTLR1) \
+ CASE_##op((val), TRCVMIDCCTLR0) \
+ CASE_##op((val), TRCVMIDCCTLR1) \
+ CASE_##op((val), TRCITCTRL) \
+ CASE_##op((val), TRCCLAIMSET) \
+ CASE_##op((val), TRCCLAIMCLR) \
+ CASE_##op((val), TRCDEVAFF0) \
+ CASE_##op((val), TRCDEVAFF1) \
+ CASE_##op((val), TRCLAR) \
+ CASE_##op((val), TRCLSR) \
+ CASE_##op((val), TRCAUTHSTATUS) \
+ CASE_##op((val), TRCDEVARCH) \
+ CASE_##op((val), TRCDEVID) \
+ CASE_##op((val), TRCDEVTYPE) \
+ CASE_##op((val), TRCPIDR4) \
+ CASE_##op((val), TRCPIDR5) \
+ CASE_##op((val), TRCPIDR6) \
+ CASE_##op((val), TRCPIDR7) \
+ CASE_##op((val), TRCPIDR0) \
+ CASE_##op((val), TRCPIDR1) \
+ CASE_##op((val), TRCPIDR2) \
+ CASE_##op((val), TRCPIDR3)
+
+#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res))
+#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val))
+
+#define read_etm4x_sysreg_offset(csa, offset, _64bit) \
+ ({ \
+ u64 __val; \
+ \
+ if (__builtin_constant_p((offset))) \
+ __val = read_etm4x_sysreg_const_offset((offset)); \
+ else \
+ __val = etm4x_sysreg_read((csa), (offset), \
+ true, _64bit); \
+ __val; \
+ })
+
+#define write_etm4x_sysreg_offset(csa, val, offset, _64bit) \
+ do { \
+ if (__builtin_constant_p((offset))) \
+ write_etm4x_sysreg_const_offset((val), \
+ (offset)); \
+ else \
+ etm4x_sysreg_write((csa), (val), (offset), \
+ true, _64bit); \
+ } while (0)
+
+
+#define etm4x_relaxed_read32(csa, offset) \
+ ((u32)((csa)->io_mem ? \
+ readl_relaxed((csa)->base + (offset)) : \
+ read_etm4x_sysreg_offset((csa), (offset), false)))
+#define etm4x_relaxed_read64(csa, offset) \
+ ((u64)((csa)->io_mem ? \
+ readq_relaxed((csa)->base + (offset)) : \
+ read_etm4x_sysreg_offset((csa), (offset), true)))
+#define etm4x_read32(csa, offset) \
+ ({ \
+ u32 __val = etm4x_relaxed_read32((csa), (offset)); \
+ __iormb(__val); \
+ __val; \
+ })
+
+#define etm4x_read64(csa, offset) \
+ ({ \
+ u64 __val = etm4x_relaxed_read64((csa), (offset)); \
+ __iormb(__val); \
+ __val; \
+ })
+
+#define etm4x_relaxed_write32(csa, val, offset) \
+ do { \
+ if ((csa)->io_mem) \
+ writel_relaxed((val), (csa)->base + (offset)); \
+ else \
+ write_etm4x_sysreg_offset((csa), (val), \
+ (offset), false); \
+ } while (0)
+
+#define etm4x_relaxed_write64(csa, val, offset) \
+ do { \
+ if ((csa)->io_mem) \
+ writeq_relaxed((val), (csa)->base + (offset)); \
+ else \
+ write_etm4x_sysreg_offset((csa), (val), \
+ (offset), true); \
+ } while (0)
+
+#define etm4x_write32(csa, val, offset) \
+ do { \
+ __iowmb(); \
+ etm4x_relaxed_write32((csa), (val), (offset)); \
+ } while (0)
+
+#define etm4x_write64(csa, val, offset) \
+ do { \
+ __iowmb(); \
+ etm4x_relaxed_write64((csa), (val), (offset)); \
+ } while (0)

-#define etm4x_write64(csa, val, offset) \
- writeq((val), (csa)->base + (offset))

/* ETMv4 resources */
#define ETM_MAX_NR_PE 8
@@ -512,4 +806,14 @@ enum etm_addr_ctxtype {

extern const struct attribute_group *coresight_etmv4_groups[];
void etm4_config_trace_mode(struct etmv4_config *config);
+
+u64 etm4x_sysreg_read(struct csdev_access *csa,
+ u32 offset,
+ bool _relaxed,
+ bool _64bit);
+void etm4x_sysreg_write(struct csdev_access *csa,
+ u64 val,
+ u32 offset,
+ bool _relaxed,
+ bool _64bit);
#endif
--
2.24.1

2020-10-29 01:00:57

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 10/26] coresight: Convert claim/disclaim operations to use access wrappers

Convert the generic CLAIM tag management APIs to use the
device access layer abstraction.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-catu.c | 6 +-
drivers/hwtracing/coresight/coresight-core.c | 66 +++++++++++--------
.../hwtracing/coresight/coresight-cti-core.c | 17 +++--
drivers/hwtracing/coresight/coresight-etb10.c | 4 +-
.../coresight/coresight-etm3x-core.c | 8 ++-
.../coresight/coresight-etm4x-core.c | 4 +-
.../hwtracing/coresight/coresight-funnel.c | 6 +-
.../coresight/coresight-replicator.c | 16 +++--
.../hwtracing/coresight/coresight-tmc-etf.c | 10 +--
.../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
include/linux/coresight.h | 16 ++---
11 files changed, 95 insertions(+), 62 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index 34c74b05c542..438063523463 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -412,6 +412,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
u32 control, mode;
struct etr_buf *etr_buf = data;
struct device *dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;

if (catu_wait_for_ready(drvdata))
dev_warn(dev, "Timeout while waiting for READY\n");
@@ -422,7 +423,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
return -EBUSY;
}

- rc = coresight_claim_device_unlocked(drvdata->base);
+ rc = coresight_claim_device_unlocked(csdev);
if (rc)
return rc;

@@ -466,9 +467,10 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
{
int rc = 0;
struct device *dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;

catu_write_control(drvdata, 0);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
if (catu_wait_for_ready(drvdata)) {
dev_info(dev, "Timeout while waiting for READY\n");
rc = -EAGAIN;
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 42ba989a6b5e..4e7dd5941046 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -145,30 +145,32 @@ static int coresight_find_link_outport(struct coresight_device *csdev,
return -ENODEV;
}

-static inline u32 coresight_read_claim_tags(void __iomem *base)
+static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
{
- return readl_relaxed(base + CORESIGHT_CLAIMCLR);
+ return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
}

-static inline bool coresight_is_claimed_self_hosted(void __iomem *base)
+static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
{
- return coresight_read_claim_tags(base) == CORESIGHT_CLAIM_SELF_HOSTED;
+ return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
}

-static inline bool coresight_is_claimed_any(void __iomem *base)
+static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
{
- return coresight_read_claim_tags(base) != 0;
+ return coresight_read_claim_tags(csdev) != 0;
}

-static inline void coresight_set_claim_tags(void __iomem *base)
+static inline void coresight_set_claim_tags(struct coresight_device *csdev)
{
- writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET);
+ csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
+ CORESIGHT_CLAIMSET);
isb();
}

-static inline void coresight_clear_claim_tags(void __iomem *base)
+static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
{
- writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR);
+ csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
+ CORESIGHT_CLAIMCLR);
isb();
}

@@ -182,27 +184,33 @@ static inline void coresight_clear_claim_tags(void __iomem *base)
* Called with CS_UNLOCKed for the component.
* Returns : 0 on success
*/
-int coresight_claim_device_unlocked(void __iomem *base)
+int coresight_claim_device_unlocked(struct coresight_device *csdev)
{
- if (coresight_is_claimed_any(base))
+ if (WARN_ON(!csdev))
+ return -EINVAL;
+
+ if (coresight_is_claimed_any(csdev))
return -EBUSY;

- coresight_set_claim_tags(base);
- if (coresight_is_claimed_self_hosted(base))
+ coresight_set_claim_tags(csdev);
+ if (coresight_is_claimed_self_hosted(csdev))
return 0;
/* There was a race setting the tags, clean up and fail */
- coresight_clear_claim_tags(base);
+ coresight_clear_claim_tags(csdev);
return -EBUSY;
}
EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);

-int coresight_claim_device(void __iomem *base)
+int coresight_claim_device(struct coresight_device *csdev)
{
int rc;

- CS_UNLOCK(base);
- rc = coresight_claim_device_unlocked(base);
- CS_LOCK(base);
+ if (WARN_ON(!csdev))
+ return -EINVAL;
+
+ CS_UNLOCK(csdev->access.base);
+ rc = coresight_claim_device_unlocked(csdev);
+ CS_LOCK(csdev->access.base);

return rc;
}
@@ -212,11 +220,14 @@ EXPORT_SYMBOL_GPL(coresight_claim_device);
* coresight_disclaim_device_unlocked : Clear the claim tags for the device.
* Called with CS_UNLOCKed for the component.
*/
-void coresight_disclaim_device_unlocked(void __iomem *base)
+void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
{

- if (coresight_is_claimed_self_hosted(base))
- coresight_clear_claim_tags(base);
+ if (WARN_ON(!csdev))
+ return;
+
+ if (coresight_is_claimed_self_hosted(csdev))
+ coresight_clear_claim_tags(csdev);
else
/*
* The external agent may have not honoured our claim
@@ -227,11 +238,14 @@ void coresight_disclaim_device_unlocked(void __iomem *base)
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);

-void coresight_disclaim_device(void __iomem *base)
+void coresight_disclaim_device(struct coresight_device *csdev)
{
- CS_UNLOCK(base);
- coresight_disclaim_device_unlocked(base);
- CS_LOCK(base);
+ if (WARN_ON(!csdev))
+ return;
+
+ CS_UNLOCK(csdev->access.base);
+ coresight_disclaim_device_unlocked(csdev);
+ CS_LOCK(csdev->access.base);
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device);

diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 3bb0de97d66e..5651d7f61a70 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -102,7 +102,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
goto cti_state_unchanged;

/* claim the device */
- rc = coresight_claim_device(drvdata->base);
+ rc = coresight_claim_device(drvdata->csdev);
if (rc)
goto cti_err_not_enabled;

@@ -136,7 +136,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
goto cti_hp_not_enabled;

/* try to claim the device */
- if (coresight_claim_device(drvdata->base))
+ if (coresight_claim_device(drvdata->csdev))
goto cti_hp_not_enabled;

cti_write_all_hw_regs(drvdata);
@@ -154,6 +154,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
struct device *dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;

spin_lock(&drvdata->spinlock);

@@ -171,7 +172,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
writel_relaxed(0, drvdata->base + CTICONTROL);
config->hw_enabled = false;

- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
spin_unlock(&drvdata->spinlock);
pm_runtime_put(dev);
@@ -655,6 +656,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
void *v)
{
struct cti_drvdata *drvdata;
+ struct coresight_device *csdev;
unsigned int cpu = smp_processor_id();
int notify_res = NOTIFY_OK;

@@ -662,6 +664,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
return NOTIFY_OK;

drvdata = cti_cpu_drvdata[cpu];
+ csdev = drvdata->csdev;

if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
return NOTIFY_BAD;
@@ -673,13 +676,13 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
/* CTI regs all static - we have a copy & nothing to save */
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
- coresight_disclaim_device(drvdata->base);
+ coresight_disclaim_device(csdev);
break;

case CPU_PM_ENTER_FAILED:
drvdata->config.hw_powered = true;
if (drvdata->config.hw_enabled) {
- if (coresight_claim_device(drvdata->base))
+ if (coresight_claim_device(csdev))
drvdata->config.hw_enabled = false;
}
break;
@@ -692,7 +695,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
/* check enable reference count to enable HW */
if (atomic_read(&drvdata->config.enable_req_count)) {
/* check we can claim the device as we re-power */
- if (coresight_claim_device(drvdata->base))
+ if (coresight_claim_device(csdev))
goto cti_notify_exit;

drvdata->config.hw_enabled = true;
@@ -736,7 +739,7 @@ static int cti_dying_cpu(unsigned int cpu)
spin_lock(&drvdata->spinlock);
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
- coresight_disclaim_device(drvdata->base);
+ coresight_disclaim_device(drvdata->csdev);
spin_unlock(&drvdata->spinlock);
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index f994a22876d9..0a416883e012 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -132,7 +132,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata)

static int etb_enable_hw(struct etb_drvdata *drvdata)
{
- int rc = coresight_claim_device(drvdata->base);
+ int rc = coresight_claim_device(drvdata->csdev);

if (rc)
return rc;
@@ -344,7 +344,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
{
__etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
- coresight_disclaim_device(drvdata->base);
+ coresight_disclaim_device(drvdata->csdev);
}

static int etb_disable(struct coresight_device *csdev)
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index 36c5b0ae1b43..70d6d809cb47 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -358,10 +358,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
int i, rc;
u32 etmcr;
struct etm_config *config = &drvdata->config;
+ struct coresight_device *csdev = drvdata->csdev;

CS_UNLOCK(drvdata->base);

- rc = coresight_claim_device_unlocked(drvdata->base);
+ rc = coresight_claim_device_unlocked(csdev);
if (rc)
goto done;

@@ -566,6 +567,7 @@ static void etm_disable_hw(void *info)
int i;
struct etm_drvdata *drvdata = info;
struct etm_config *config = &drvdata->config;
+ struct coresight_device *csdev = drvdata->csdev;

CS_UNLOCK(drvdata->base);
etm_set_prog(drvdata);
@@ -577,7 +579,7 @@ static void etm_disable_hw(void *info)
config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));

etm_set_pwrdwn(drvdata);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);

CS_LOCK(drvdata->base);

@@ -602,7 +604,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
* power down the tracer.
*/
etm_set_pwrdwn(drvdata);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);

CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 2744aadaa5ec..4f1bcf98fefe 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -115,7 +115,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)

etm4_os_unlock(drvdata);

- rc = coresight_claim_device_unlocked(drvdata->base);
+ rc = coresight_claim_device_unlocked(csdev);
if (rc)
goto done;

@@ -523,7 +523,7 @@ static void etm4_disable_hw(void *info)
readl_relaxed(drvdata->base + TRCCNTVRn(i));
}

- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);

CS_LOCK(drvdata->base);

diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index f77466aea26f..2f8675c527bf 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -52,13 +52,14 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
{
u32 functl;
int rc = 0;
+ struct coresight_device *csdev = drvdata->csdev;

CS_UNLOCK(drvdata->base);

functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
/* Claim the device only when we enable the first slave */
if (!(functl & FUNNEL_ENSx_MASK)) {
- rc = coresight_claim_device_unlocked(drvdata->base);
+ rc = coresight_claim_device_unlocked(csdev);
if (rc)
goto done;
}
@@ -101,6 +102,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
int inport)
{
u32 functl;
+ struct coresight_device *csdev = drvdata->csdev;

CS_UNLOCK(drvdata->base);

@@ -110,7 +112,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,

/* Disclaim the device if none of the slaves are now active */
if (!(functl & FUNNEL_ENSx_MASK))
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);

CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index fcf25740116c..e35d79e74e30 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -45,12 +45,18 @@ struct replicator_drvdata {

static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
{
+ struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);

- if (!coresight_claim_device_unlocked(drvdata->base)) {
+ if (WARN_ON(!csdev))
+ return;
+
+ CS_UNLOCK(drvdata->base);
+
+ if (!coresight_claim_device_unlocked(csdev)) {
writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
}

CS_LOCK(drvdata->base);
@@ -70,6 +76,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
{
int rc = 0;
u32 id0val, id1val;
+ struct coresight_device *csdev = drvdata->csdev;

CS_UNLOCK(drvdata->base);

@@ -84,7 +91,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
id0val = id1val = 0xff;

if (id0val == 0xff && id1val == 0xff)
- rc = coresight_claim_device_unlocked(drvdata->base);
+ rc = coresight_claim_device_unlocked(csdev);

if (!rc) {
switch (outport) {
@@ -140,6 +147,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
int inport, int outport)
{
u32 reg;
+ struct coresight_device *csdev = drvdata->csdev;

switch (outport) {
case 0:
@@ -160,7 +168,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,

if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
(readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 44402d413ebb..3a5605eda68f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -37,7 +37,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata)

static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
{
- int rc = coresight_claim_device(drvdata->base);
+ int rc = coresight_claim_device(drvdata->csdev);

if (rc)
return rc;
@@ -88,7 +88,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
{
__tmc_etb_disable_hw(drvdata);
- coresight_disclaim_device(drvdata->base);
+ coresight_disclaim_device(drvdata->csdev);
}

static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
@@ -109,7 +109,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)

static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{
- int rc = coresight_claim_device(drvdata->base);
+ int rc = coresight_claim_device(drvdata->csdev);

if (rc)
return rc;
@@ -120,11 +120,13 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)

static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
{
+ struct coresight_device *csdev = drvdata->csdev;
+
CS_UNLOCK(drvdata->base);

tmc_flush_and_stop(drvdata);
tmc_disable_hw(drvdata);
- coresight_disclaim_device_unlocked(drvdata->base);
+ coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}

diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 714f9e867e5f..a8b1c49761c7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1038,7 +1038,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
rc = tmc_etr_enable_catu(drvdata, etr_buf);
if (rc)
return rc;
- rc = coresight_claim_device(drvdata->base);
+ rc = coresight_claim_device(drvdata->csdev);
if (!rc) {
drvdata->etr_buf = etr_buf;
__tmc_etr_enable_hw(drvdata);
@@ -1132,7 +1132,7 @@ void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
__tmc_etr_disable_hw(drvdata);
/* Disable CATU device if this ETR is connected to one */
tmc_etr_disable_catu(drvdata);
- coresight_disclaim_device(drvdata->base);
+ coresight_disclaim_device(drvdata->csdev);
/* Reset the ETR buf used by hardware */
drvdata->etr_buf = NULL;
}
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cefc8fe239e6..c2d0a2aea45f 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -474,11 +474,11 @@ extern int coresight_timeout(struct csdev_access *csa,
int position,
int value);

-extern int coresight_claim_device(void __iomem *base);
-extern int coresight_claim_device_unlocked(void __iomem *base);
+extern int coresight_claim_device(struct coresight_device *csdev);
+extern int coresight_claim_device_unlocked(struct coresight_device *csdev);

-extern void coresight_disclaim_device(void __iomem *base);
-extern void coresight_disclaim_device_unlocked(void __iomem *base);
+extern void coresight_disclaim_device(struct coresight_device *csdev);
+extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
struct device *dev);

@@ -513,18 +513,18 @@ static inline int coresight_timeout(struct csdev_access *csa,
return 1;
}

-static inline int coresight_claim_device_unlocked(void __iomem *base)
+static inline int coresight_claim_device_unlocked(struct coresight_device *csdev)
{
return -EINVAL;
}

-static inline int coresight_claim_device(void __iomem *base)
+static inline int coresight_claim_device(struct coresight_device *csdev)
{
return -EINVAL;
}

-static inline void coresight_disclaim_device(void __iomem *base) {}
-static inline void coresight_disclaim_device_unlocked(void __iomem *base) {}
+static inline void coresight_disclaim_device(struct coresight_device *csdev) {}
+static inline void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {}

static inline bool coresight_loses_context_with_cpu(struct device *dev)
{
--
2.24.1

2020-10-29 01:01:00

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 13/26] coresight: etm4x: Add commentary on the registers

As we are about define a switch..case table for individual register
access by offset for implementing the system instruction support,
document the possible set of registers for each group to make
it easier to co-relate.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x.h | 21 ++++++++++++-------
1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 14e0f29db6b3..510828c73db6 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -44,13 +44,13 @@
#define TRCVDSACCTLR 0x0A4
#define TRCVDARCCTLR 0x0A8
/* Derived resources registers */
-#define TRCSEQEVRn(n) (0x100 + (n * 4))
+#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */
#define TRCSEQRSTEVR 0x118
#define TRCSEQSTR 0x11C
#define TRCEXTINSELR 0x120
-#define TRCCNTRLDVRn(n) (0x140 + (n * 4))
-#define TRCCNTCTLRn(n) (0x150 + (n * 4))
-#define TRCCNTVRn(n) (0x160 + (n * 4))
+#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) /* n = 0-3 */
+#define TRCCNTCTLRn(n) (0x150 + (n * 4)) /* n = 0-3 */
+#define TRCCNTVRn(n) (0x160 + (n * 4)) /* n = 0-3 */
/* ID registers */
#define TRCIDR8 0x180
#define TRCIDR9 0x184
@@ -59,7 +59,7 @@
#define TRCIDR12 0x190
#define TRCIDR13 0x194
#define TRCIMSPEC0 0x1C0
-#define TRCIMSPECn(n) (0x1C0 + (n * 4))
+#define TRCIMSPECn(n) (0x1C0 + (n * 4)) /* n = 1-7 */
#define TRCIDR0 0x1E0
#define TRCIDR1 0x1E4
#define TRCIDR2 0x1E8
@@ -68,9 +68,12 @@
#define TRCIDR5 0x1F4
#define TRCIDR6 0x1F8
#define TRCIDR7 0x1FC
-/* Resource selection registers */
+/*
+ * Resource selection registers, n = 2-31.
+ * First pair (regs 0, 1) is always present and is reserved.
+ */
#define TRCRSCTLRn(n) (0x200 + (n * 4))
-/* Single-shot comparator registers */
+/* Single-shot comparator registers, n = 0-7 */
#define TRCSSCCRn(n) (0x280 + (n * 4))
#define TRCSSCSRn(n) (0x2A0 + (n * 4))
#define TRCSSPCICRn(n) (0x2C0 + (n * 4))
@@ -80,11 +83,13 @@
#define TRCPDCR 0x310
#define TRCPDSR 0x314
/* Trace registers (0x318-0xEFC) */
-/* Comparator registers */
+/* Address Comparator registers n = 0-15 */
#define TRCACVRn(n) (0x400 + (n * 8))
#define TRCACATRn(n) (0x480 + (n * 8))
+/* Data Value Comparator Value registers, n = 0-7 */
#define TRCDVCVRn(n) (0x500 + (n * 16))
#define TRCDVCMRn(n) (0x580 + (n * 16))
+/* ContextID/Virtual ContextID comparators, n = 0-7 */
#define TRCCIDCVRn(n) (0x600 + (n * 8))
#define TRCVMIDCVRn(n) (0x640 + (n * 8))
#define TRCCIDCCTLR0 0x680
--
2.24.1

2020-10-29 01:01:01

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 17/26] coresight: etm4x: Cleanup secure exception level masks

We rely on the ETM architecture version to decide whether
Secure EL2 is available on the CPU for excluding the level
for address comparators and viewinst main control register.
We must instead use the TRCDIDR3.EXLEVEL_S field to detect
the supported levels.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++----------
drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++--
2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index a12d58a04c5d..6e3f9cb7de3f 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -733,7 +733,6 @@ static void etm4_init_arch_data(void *info)
* TRCARCHMAJ, bits[11:8] architecture major versin number
*/
drvdata->arch = BMVAL(etmidr1, 4, 11);
- drvdata->config.arch = drvdata->arch;

/* maximum size of resources */
etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
@@ -749,6 +748,7 @@ static void etm4_init_arch_data(void *info)
drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
/* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
+ drvdata->config.s_ex_level = drvdata->s_ex_level;
/* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);

@@ -920,16 +920,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
static u64 etm4_get_access_type(struct etmv4_config *config)
{
u64 access_type = etm4_get_ns_access_type(config);
- u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;

- /*
- * EXLEVEL_S, bits[11:8], don't trace anything happening
- * in secure state.
- */
- access_type |= (ETM_EXLEVEL_S_APP |
- ETM_EXLEVEL_S_OS |
- s_hyp |
- ETM_EXLEVEL_S_MON);
+ /* All supported secure ELs are excluded */
+ access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;

return access_type;
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index e7f6b7b16fb7..2ac4ecb0af61 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -546,6 +546,8 @@
/* PowerDown Control Register bits */
#define TRCPDCR_PU BIT(3)

+#define TRCACATR_EXLEVEL_SHIFT 8
+
/* secure state access levels - TRCACATRn */
#define ETM_EXLEVEL_S_APP BIT(8)
#define ETM_EXLEVEL_S_OS BIT(9)
@@ -615,7 +617,7 @@
* @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.
- * @arch: ETM architecture version (for arch dependent config).
+ * @s_ex_level: Secure ELs where tracing is supported.
*/
struct etmv4_config {
u32 mode;
@@ -659,7 +661,7 @@ struct etmv4_config {
u32 vmid_mask0;
u32 vmid_mask1;
u32 ext_inp;
- u8 arch;
+ u8 s_ex_level;
};

/**
--
2.24.1

2020-10-29 01:01:03

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

In preparation to detect the support for system instruction
support, move the detection of the device access to the target
CPU.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index f038bb10bc78..308674ab746c 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);

static enum cpuhp_state hp_online;

+struct etm_init_arg {
+ struct etmv4_drvdata *drvdata;
+ struct csdev_access *csa;
+};
+
u64 etm4x_sysreg_read(struct csdev_access *csa,
u32 offset,
bool _relaxed,
@@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
.source_ops = &etm4_source_ops,
};

+static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
+ struct csdev_access *csa)
+{
+ *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
+ return true;
+}
+
+static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
+ struct csdev_access *csa)
+{
+ if (drvdata->base)
+ return etm_init_iomem_access(drvdata, csa);
+
+ return false;
+}
+
static void etm4_init_arch_data(void *info)
{
u32 etmidr0;
@@ -677,11 +698,22 @@ static void etm4_init_arch_data(void *info)
u32 etmidr3;
u32 etmidr4;
u32 etmidr5;
- struct etmv4_drvdata *drvdata = info;
- struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
- struct csdev_access *csa = &tmp_csa;
+ struct etm_init_arg *init_arg = info;
+ struct etmv4_drvdata *drvdata;
+ struct csdev_access *csa;
int i;

+ drvdata = init_arg->drvdata;
+ csa = init_arg->csa;
+
+ /*
+ * If we are unable to detect the access mechanism,
+ * or unable to detect the trace unit type, fail
+ * early.
+ */
+ if (!etm_init_csdev_access(drvdata, csa))
+ return;
+
/* Make sure all registers are accessible */
etm4_os_unlock_csa(drvdata, csa);
etm4_cs_unlock(drvdata, csa);
@@ -1524,6 +1556,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
struct etmv4_drvdata *drvdata;
struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
+ struct etm_init_arg init_arg = { 0 };

drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
@@ -1551,7 +1584,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);

drvdata->base = base;
- desc.access = CSDEV_ACCESS_IOMEM(base);

spin_lock_init(&drvdata->spinlock);

@@ -1563,8 +1595,11 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
if (!desc.name)
return -ENOMEM;

+ init_arg.drvdata = drvdata;
+ init_arg.csa = &desc.access;
+
if (smp_call_function_single(drvdata->cpu,
- etm4_init_arch_data, drvdata, 1))
+ etm4_init_arch_data, &init_arg, 1))
dev_err(dev, "ETM arch init failed\n");

if (etm4_arch_supported(drvdata->arch) == false)
--
2.24.1

2020-10-29 01:01:07

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 26/26] dts: bindings: coresight: ETM system register access only units

Document the bindings for ETMs with system register accesses.

Cc: [email protected]
Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Cc: Rob Herring <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
Documentation/devicetree/bindings/arm/coresight.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index d711676b4a51..bff96a550102 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -34,9 +34,12 @@ its hardware characteristcs.
Program Flow Trace Macrocell:
"arm,coresight-etm3x", "arm,primecell";

- - Embedded Trace Macrocell (version 4.x):
+ - Embedded Trace Macrocell (version 4.x), with memory mapped access.
"arm,coresight-etm4x", "arm,primecell";

+ - Embedded Trace Macrocell with system register access only.
+ "arm,coresight-etm-sysreg";
+
- Coresight programmable Replicator :
"arm,coresight-dynamic-replicator", "arm,primecell";

--
2.24.1

2020-10-29 01:01:09

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 24/26] coresight: etm4x: Refactor probing routine

CoreSight ETM with system register access may not have a
memory mapped i/o access. Refactor the ETM specific probing
into a common routine to allow reusing the code for such ETMs.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 48 +++++++++++--------
1 file changed, 29 insertions(+), 19 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index dc537b5612eb..25fab5513604 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1598,14 +1598,11 @@ static void etm4_pm_clear(void)
}
}

-static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
+static int etm4_probe(struct device *dev, void __iomem *base)
{
int ret;
- void __iomem *base;
- struct device *dev = &adev->dev;
struct coresight_platform_data *pdata = NULL;
struct etmv4_drvdata *drvdata;
- struct resource *res = &adev->res;
struct coresight_desc desc = { 0 };
struct etm_init_arg init_arg = { 0 };

@@ -1629,11 +1626,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
if (fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
drvdata->skip_power_up = true;

- /* Validity for the resource is already checked by the AMBA core */
- base = devm_ioremap_resource(dev, res);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
drvdata->base = base;

spin_lock_init(&drvdata->spinlock);
@@ -1663,7 +1655,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
if (IS_ERR(pdata))
return PTR_ERR(pdata);

- adev->dev.platform_data = pdata;
+ dev->platform_data = pdata;

desc.type = CORESIGHT_DEV_TYPE_SOURCE;
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
@@ -1683,7 +1675,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)

etmdrvdata[drvdata->cpu] = drvdata;

- pm_runtime_put(&adev->dev);
dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
drvdata->cpu, ETM_ARCH_MAJOR_VERSION(drvdata->arch),
ETM_ARCH_MINOR_VERSION(drvdata->arch));
@@ -1696,6 +1687,25 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
return 0;
}

+static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
+{
+ void __iomem *base;
+ struct device *dev = &adev->dev;
+ struct resource *res = &adev->res;
+ int ret;
+
+ /* Validity for the resource is already checked by the AMBA core */
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ ret = etm4_probe(dev, base);
+ if (!ret)
+ pm_runtime_put(&adev->dev);
+
+ return ret;
+}
+
static struct amba_cs_uci_id uci_id_etm4[] = {
{
/* ETMv4 UCI data */
@@ -1712,15 +1722,15 @@ static void __exit clear_etmdrvdata(void *info)
etmdrvdata[cpu] = NULL;
}

-static int __exit etm4_remove(struct amba_device *adev)
+static int __exit etm4_remove_amba(struct amba_device *adev)
{
struct etmv4_drvdata *drvdata = dev_get_drvdata(&adev->dev);

etm_perf_symlink(drvdata->csdev, false);

/*
- * Taking hotplug lock here to avoid racing between etm4_remove and
- * CPU hotplug call backs.
+ * Taking hotplug lock here to avoid racing between etm4_remove_amba()
+ * and CPU hotplug call backs.
*/
cpus_read_lock();
/*
@@ -1760,14 +1770,14 @@ static const struct amba_id etm4_ids[] = {

MODULE_DEVICE_TABLE(amba, etm4_ids);

-static struct amba_driver etm4x_driver = {
+static struct amba_driver etm4x_amba_driver = {
.drv = {
.name = "coresight-etm4x",
.owner = THIS_MODULE,
.suppress_bind_attrs = true,
},
- .probe = etm4_probe,
- .remove = etm4_remove,
+ .probe = etm4_probe_amba,
+ .remove = etm4_remove_amba,
.id_table = etm4_ids,
};

@@ -1781,7 +1791,7 @@ static int __init etm4x_init(void)
if (ret)
return ret;

- ret = amba_driver_register(&etm4x_driver);
+ ret = amba_driver_register(&etm4x_amba_driver);
if (ret) {
pr_err("Error registering etm4x driver\n");
etm4_pm_clear();
@@ -1792,7 +1802,7 @@ static int __init etm4x_init(void)

static void __exit etm4x_exit(void)
{
- amba_driver_unregister(&etm4x_driver);
+ amba_driver_unregister(&etm4x_amba_driver);
etm4_pm_clear();
}

--
2.24.1

2020-10-29 01:01:20

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 22/26] coresight: etm4x: Add necessary synchronization for sysreg access

As per the specification any update to the TRCPRGCTLR must be synchronized
by a context synchronization event (in our case an explicist ISB) before
the TRCSTATR is checked.

Cc: Mike Leach <[email protected]>
Cc: Mathieu Poirier <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e36bc1c722c7..4bc2f15b6332 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -178,6 +178,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
/* Disable the trace unit before programming trace registers */
etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);

+ /*
+ * If we use system instructions, we need to synchronize the
+ * write to the TRCPRGCTLR, before accessing the TRCSTATR.
+ * See ARM IHI0064F, section
+ * "4.3.7 Synchronization of register updates"
+ */
+ if (!csa->io_mem)
+ isb();
+
/* wait for TRCSTATR.IDLE to go up */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
dev_err(etm_dev,
@@ -256,6 +265,10 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
/* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);

+ /* Synchronize the register updates for sysreg access */
+ if (!csa->io_mem)
+ isb();
+
/* wait for TRCSTATR.IDLE to go back down to '0' */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
dev_err(etm_dev,
--
2.24.1

2020-10-29 01:01:21

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 20/26] coresight: etm4x: Handle ETM architecture version

We are about to rely on TRCDEVARCH for detecting the ETM
and its architecture version, falling back to TRCIDR1 if
the former is not implemented (in older broken implementations).

Also, we use the architecture version information to do
make some decisions. Streamline the architecture version
handling by adding helpers.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 2 +-
drivers/hwtracing/coresight/coresight-etm4x.h | 60 ++++++++++++++++++-
2 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 308674ab746c..4ef47a2946a4 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -842,7 +842,7 @@ static void etm4_init_arch_data(void *info)
* Otherwise for values 0x1 and above the number is N + 1 as per v4.2.
*/
drvdata->nr_resource = BMVAL(etmidr4, 16, 19);
- if ((drvdata->arch < ETM4X_ARCH_4V3) || (drvdata->nr_resource > 0))
+ if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0))
drvdata->nr_resource += 1;
/*
* NUMSSCC, bits[23:20] the number of single-shot
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index f1251ddf1984..fe7107282e54 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -459,7 +459,6 @@
#define ETM_MAX_RES_SEL 32
#define ETM_MAX_SS_CMP 8

-#define ETM_ARCH_V4 0x40
#define ETMv4_SYNC_MASK 0x1F
#define ETM_CYC_THRESHOLD_MASK 0xFFF
#define ETM_CYC_THRESHOLD_DEFAULT 0x100
@@ -581,8 +580,63 @@
#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)

+#define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8
+#define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
+#define ETM_TRCIDR1_ARCH_MAJOR(x) \
+ (((x) & ETM_TRCIDR1_ARCH_MAJOR_MASK) >> ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
+#define ETM_TRCIDR1_ARCH_MINOR_SHIFT 4
+#define ETM_TRCIDR1_ARCH_MINOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MINOR_SHIFT)
+#define ETM_TRCIDR1_ARCH_MINOR(x) \
+ (((x) & ETM_TRCIDR1_ARCH_MINOR_MASK) >> ETM_TRCIDR1_ARCH_MINOR_SHIFT)
+#define ETM_TRCIDR1_ARCH_SHIFT ETM_TRCIDR1_ARCH_MINOR_SHIFT
+#define ETM_TRCIDR1_ARCH_MASK \
+ (ETM_TRCIDR1_ARCH_MAJOR_MASK | ETM_TRCIDR1_ARCH_MINOR_MASK)
+
+#define ETM_TRCIDR1_ARCH_ETMv4 0x4
+
+/*
+ * Driver representation of the ETM architecture.
+ * The version of an ETM component can be detected from
+ *
+ * TRCDEVARCH - CoreSight architected register
+ * - Bits[15:12] - Major version
+ * - Bits[19:16] - Minor version
+ * TRCIDR1 - ETM architected register
+ * - Bits[12:8] - Major version
+ * - Bits[7:4] - Minor version
+ * We must rely on TRCDEVARCH for the version information,
+ * however we don't want to break the support for potential
+ * old implementations which might not implement it. Thus
+ * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
+ * for memory mapped components.
+ * Now to make certain decisions easier based on the version
+ * we use an internal representation of the version in the
+ * driver, as follows :
+ *
+ * ETM_ARCH_VERSION[7:0], where :
+ * Bits[7:4] - Major version
+ * Bits[3:0] - Minro version
+ */
+#define ETM_ARCH_VERSION(major, minor) \
+ ((((major) & 0xfU) << 4) | (((minor) & 0xfU)))
+#define ETM_ARCH_MAJOR_VERSION(arch) (((arch) >> 4) & 0xfU)
+#define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU)
+
+#define ETM_ARCH_V4 ETM_ARCH_VERSION(4, 0)
/* Interpretation of resource numbers change at ETM v4.3 architecture */
-#define ETM4X_ARCH_4V3 0x43
+#define ETM_ARCH_V4_3 ETM_ARCH_VERSION(4, 3)
+
+static inline u8 etm_devarch_to_arch(u32 devarch)
+{
+ return ETM_ARCH_VERSION(ETM_DEVARCH_ARCHID_ARCH_VER(devarch),
+ ETM_DEVARCH_REVISION(devarch));
+}
+
+static inline u8 etm_trcidr_to_arch(u32 trcidr1)
+{
+ return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
+ ETM_TRCIDR1_ARCH_MINOR(trcidr1));
+}

/**
* struct etmv4_config - configuration information related to an ETMv4
@@ -744,7 +798,7 @@ struct etmv4_save_state {
* @spinlock: Only one at a time pls.
* @mode: This tracer's mode, i.e sysFS, Perf or disabled.
* @cpu: The cpu this component is affined to.
- * @arch: ETM version number.
+ * @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.
--
2.24.1

2020-10-29 02:46:51

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 21/26] coresight: etm4x: Use TRCDEVARCH for component discovery

We have been using TRCIDR1 for detecting the ETM version. This
is in preparation for the future IP support.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 46 +++++++++----------
1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 4ef47a2946a4..e36bc1c722c7 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -141,18 +141,6 @@ static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
CS_UNLOCK(csa->base);
}

-static bool etm4_arch_supported(u8 arch)
-{
- /* Mask out the minor version number */
- switch (arch & 0xf0) {
- case ETM_ARCH_V4:
- break;
- default:
- return false;
- }
- return true;
-}
-
static int etm4_cpu_id(struct coresight_device *csdev)
{
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -677,6 +665,26 @@ static const struct coresight_ops etm4_cs_ops = {
static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
{
+ u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
+ u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);
+
+ /*
+ * All ETMs must implement TRCDEVARCH to indicate that
+ * the component is an ETMv4. To support any broken
+ * implementations we fall back to TRCIDR1 check, which
+ * is not really reliable.
+ */
+ if ((devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH) {
+ drvdata->arch = etm_devarch_to_arch(devarch);
+ } else {
+ pr_warn("CPU%d: ETM4x incompatible TRCDEVARCH: %x, falling back to TRCIDR1\n",
+ smp_processor_id(), devarch);
+
+ if (ETM_TRCIDR1_ARCH_MAJOR(idr1) != ETM_TRCIDR1_ARCH_ETMv4)
+ return false;
+ drvdata->arch = etm_trcidr_to_arch(idr1);
+ }
+
*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
return true;
}
@@ -693,7 +701,6 @@ static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
static void etm4_init_arch_data(void *info)
{
u32 etmidr0;
- u32 etmidr1;
u32 etmidr2;
u32 etmidr3;
u32 etmidr4;
@@ -758,14 +765,6 @@ static void etm4_init_arch_data(void *info)
/* TSSIZE, bits[28:24] Global timestamp size field */
drvdata->ts_size = BMVAL(etmidr0, 24, 28);

- /* base architecture of trace unit */
- etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1);
- /*
- * TRCARCHMIN, bits[7:4] architecture the minor version number
- * TRCARCHMAJ, bits[11:8] architecture major versin number
- */
- drvdata->arch = BMVAL(etmidr1, 4, 11);
-
/* maximum size of resources */
etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
/* CIDSIZE, bits[9:5] Indicates the Context ID size */
@@ -1602,7 +1601,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
etm4_init_arch_data, &init_arg, 1))
dev_err(dev, "ETM arch init failed\n");

- if (etm4_arch_supported(drvdata->arch) == false)
+ if (!drvdata->arch)
return -EINVAL;

etm4_init_trace_id(drvdata);
@@ -1634,7 +1633,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)

pm_runtime_put(&adev->dev);
dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
- drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf);
+ drvdata->cpu, ETM_ARCH_MAJOR_VERSION(drvdata->arch),
+ ETM_ARCH_MINOR_VERSION(drvdata->arch));

if (boot_enable) {
coresight_enable(drvdata->csdev);
--
2.24.1

2020-10-29 02:46:51

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 03/26] coresight: etm4x: Update TRCIDR3.NUMPROCS handling to match v4.2

Since ETMv4.2, TRCIDR3.NUMPROCS has been extended to a 5bit field
by encoding the top 2 bits[4:3] in TRCIDR3.[13:12], which were RES0.
Fix the driver to compute the field correctly for ETMv4.2+

Cc: Mike Leach <[email protected]>
Cc: Mathieu Poirier <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index af0ab2f44865..cbbe755d1d16 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -724,8 +724,13 @@ static void etm4_init_arch_data(void *info)
else
drvdata->sysstall = false;

- /* NUMPROC, bits[30:28] the number of PEs available for tracing */
- drvdata->nr_pe = BMVAL(etmidr3, 28, 30);
+ /*
+ * NUMPROC - the number of PEs available for tracing, 5bits
+ * = TRCIDR3.bits[13:12]bits[30:28]
+ * bits[4:3] = TRCIDR3.bits[13:12] (since etm-v4.2, otherwise RES0)
+ * bits[3:0] = TRCIDR3.bits[30:28]
+ */
+ drvdata->nr_pe = (BMVAL(etmidr3, 12, 13) << 3) | BMVAL(etmidr3, 28, 30);

/* NOOVERFLOW, bit[31] is trace overflow prevention supported */
if (BMVAL(etmidr3, 31, 31))
--
2.24.1

2020-10-29 08:43:44

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 18/26] coresight: etm4x: Clean up exception level masks

etm4_get_access_type() calculates the exception level bits
for use in address comparator registers. This is also used
by the TRCVICTLR register by shifting to the required position.

This patch cleans up the logic to make etm4_get_access_type()
calcualte a generic mask which can be used by all users by
shifting to their field.

No functional changes, only code cleanups.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
Changes since previous version:
- Fix the duplicate shift. More commentary
---
.../coresight/coresight-etm4x-core.c | 47 +++++++++----------
.../coresight/coresight-etm4x-sysfs.c | 12 ++---
drivers/hwtracing/coresight/coresight-etm4x.h | 46 +++++++++++-------
3 files changed, 59 insertions(+), 46 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 6e3f9cb7de3f..f038bb10bc78 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -852,20 +852,16 @@ static void etm4_init_arch_data(void *info)
etm4_cs_lock(drvdata, csa);
}

+static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
+{
+ return etm4_get_access_type(config) << TRCVICTLR_EXLEVEL_SHIFT;
+}
+
/* Set ELx trace filter access in the TRCVICTLR register */
static void etm4_set_victlr_access(struct etmv4_config *config)
{
- u64 access_type;
-
- config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK | ETM_EXLEVEL_NS_VICTLR_MASK);
-
- /*
- * TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering
- * bits in vinst_ctrl, same bit pattern as TRCACATRn values returned by
- * etm4_get_access_type() but with a relative shift in this register.
- */
- access_type = etm4_get_access_type(config) << ETM_EXLEVEL_LSHIFT_TRCVICTLR;
- config->vinst_ctrl |= (u32)access_type;
+ config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK | TRCVICTLR_EXLEVEL_NS_MASK);
+ config->vinst_ctrl |= etm4_get_victlr_access_type(config);
}

static void etm4_set_default_config(struct etmv4_config *config)
@@ -895,12 +891,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
u64 access_type = 0;

/*
- * EXLEVEL_NS, bits[15:12]
- * The Exception levels are:
- * Bit[12] Exception level 0 - Application
- * Bit[13] Exception level 1 - OS
- * Bit[14] Exception level 2 - Hypervisor
- * Bit[15] Never implemented
+ * EXLEVEL_NS, for NonSecure Exception levels.
+ * The mask here is a generic value and must be
+ * shifted to the corresponding field for the registers
*/
if (!is_kernel_in_hyp_mode()) {
/* Stay away from hypervisor mode for non-VHE */
@@ -917,20 +910,26 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
return access_type;
}

+/*
+ * Construct the exception level masks for a given config.
+ * This must be shifted to the corresponding register field
+ * for usage.
+ */
static u64 etm4_get_access_type(struct etmv4_config *config)
{
- u64 access_type = etm4_get_ns_access_type(config);
-
- /* All supported secure ELs are excluded */
- access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
+ /* All Secure exception levels are excluded from the trace */
+ return etm4_get_ns_access_type(config) | (u64)config->s_ex_level;
+}

- return access_type;
+static u64 etm4_get_comparator_access_type(struct etmv4_config *config)
+{
+ return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT;
}

static void etm4_set_comparator_filter(struct etmv4_config *config,
u64 start, u64 stop, int comparator)
{
- u64 access_type = etm4_get_access_type(config);
+ u64 access_type = etm4_get_comparator_access_type(config);

/* First half of default address comparator */
config->addr_val[comparator] = start;
@@ -965,7 +964,7 @@ static void etm4_set_start_stop_filter(struct etmv4_config *config,
enum etm_addr_type type)
{
int shift;
- u64 access_type = etm4_get_access_type(config);
+ u64 access_type = etm4_get_comparator_access_type(config);

/* Configure the comparator */
config->addr_val[comparator] = address;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index fce9df16bfb5..009818675928 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -743,7 +743,7 @@ static ssize_t s_exlevel_vinst_show(struct device *dev,
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;

- val = (config->vinst_ctrl & ETM_EXLEVEL_S_VICTLR_MASK) >> 16;
+ val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_S_MASK) >> TRCVICTLR_EXLEVEL_S_SHIFT;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -760,10 +760,10 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,

spin_lock(&drvdata->spinlock);
/* clear all EXLEVEL_S bits */
- config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK);
+ config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK);
/* enable instruction tracing for corresponding exception level */
val &= drvdata->s_ex_level;
- config->vinst_ctrl |= (val << 16);
+ config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_S_SHIFT);
spin_unlock(&drvdata->spinlock);
return size;
}
@@ -778,7 +778,7 @@ static ssize_t ns_exlevel_vinst_show(struct device *dev,
struct etmv4_config *config = &drvdata->config;

/* EXLEVEL_NS, bits[23:20] */
- val = (config->vinst_ctrl & ETM_EXLEVEL_NS_VICTLR_MASK) >> 20;
+ val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_NS_MASK) >> TRCVICTLR_EXLEVEL_NS_SHIFT;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}

@@ -795,10 +795,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,

spin_lock(&drvdata->spinlock);
/* clear EXLEVEL_NS bits */
- config->vinst_ctrl &= ~(ETM_EXLEVEL_NS_VICTLR_MASK);
+ config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK);
/* enable instruction tracing for corresponding exception level */
val &= drvdata->ns_ex_level;
- config->vinst_ctrl |= (val << 20);
+ config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT);
spin_unlock(&drvdata->spinlock);
return size;
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 2ac4ecb0af61..f1251ddf1984 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -548,24 +548,38 @@

#define TRCACATR_EXLEVEL_SHIFT 8

-/* secure state access levels - TRCACATRn */
-#define ETM_EXLEVEL_S_APP BIT(8)
-#define ETM_EXLEVEL_S_OS BIT(9)
-#define ETM_EXLEVEL_S_HYP BIT(10)
-#define ETM_EXLEVEL_S_MON BIT(11)
-/* non-secure state access levels - TRCACATRn */
-#define ETM_EXLEVEL_NS_APP BIT(12)
-#define ETM_EXLEVEL_NS_OS BIT(13)
-#define ETM_EXLEVEL_NS_HYP BIT(14)
-#define ETM_EXLEVEL_NS_NA BIT(15)
-
-/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */
-#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8
+/*
+ * Exception level mask for Secure and Non-Secure ELs.
+ * ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn).
+ * The Secure and Non-Secure ELs are always to gether.
+ * Non-secure EL3 is never implemented.
+ * We use the following generic mask as they appear in different
+ * registers and this can be shifted for the appropriate
+ * fields.
+ */
+#define ETM_EXLEVEL_S_APP BIT(0) /* Secure EL0 */
+#define ETM_EXLEVEL_S_OS BIT(1) /* Secure EL1 */
+#define ETM_EXLEVEL_S_HYP BIT(2) /* Secure EL2 */
+#define ETM_EXLEVEL_S_MON BIT(3) /* Secure EL3/Montor */
+#define ETM_EXLEVEL_NS_APP BIT(4) /* NonSecure EL0 */
+#define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */
+#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 */
+#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 ETM_EXLEVEL_S_VICTLR_MASK GENMASK(19, 16)
-/* NS MON (EL3) mode never implemented */
-#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
+#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
+#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)

/* Interpretation of resource numbers change at ETM v4.3 architecture */
#define ETM4X_ARCH_4V3 0x43
--
2.24.1

2020-10-29 08:43:46

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 12/26] coresight: etm4x: Convert all register accesses

Convert all register accesses from etm4x driver to use a wrapper
to allow switching the access at runtime with little overhead.

co-developed by sed tool ;-), mostly equivalent to :

s/readl\(_relaxed\)\?(drvdata->base + \(.*\))/etm4x_\1_read32(csdev, \2)
s/writel\(_relaxed\)\?(\(.*\), drvdata->base + \(.*\))/etm4x_\1_write32(csdev, \2, \3)

We don't want to replace them with the csdev_access_* to
avoid a function call for every register access for system
register access. This is a prepartory step to add system
register access later where the support is available.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 326 +++++++++---------
.../coresight/coresight-etm4x-sysfs.c | 9 +-
drivers/hwtracing/coresight/coresight-etm4x.h | 24 ++
3 files changed, 187 insertions(+), 172 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 4f1bcf98fefe..4af7d45dfe63 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -56,18 +56,28 @@ static u64 etm4_get_access_type(struct etmv4_config *config);

static enum cpuhp_state hp_online;

-static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
+static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
{
/* Writing 0 to TRCOSLAR unlocks the trace registers */
- writel_relaxed(0x0, drvdata->base + TRCOSLAR);
+ etm4x_relaxed_write32(csa, 0x0, TRCOSLAR);
drvdata->os_unlock = true;
isb();
}

+static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
+{
+ if (!WARN_ON(!drvdata->csdev))
+ etm4_os_unlock_csa(drvdata, &drvdata->csdev->access);
+
+}
+
static void etm4_os_lock(struct etmv4_drvdata *drvdata)
{
+ if (WARN_ON(!drvdata->csdev))
+ return;
+
/* Writing 0x1 to TRCOSLAR locks the trace registers */
- writel_relaxed(0x1, drvdata->base + TRCOSLAR);
+ etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR);
drvdata->os_unlock = false;
isb();
}
@@ -120,45 +130,39 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
goto done;

/* Disable the trace unit before programming trace registers */
- writel_relaxed(0, drvdata->base + TRCPRGCTLR);
+ etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);

/* wait for TRCSTATR.IDLE to go up */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
if (drvdata->nr_pe)
- writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
- writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
+ etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR);
+ etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR);
/* nothing specific implemented */
- writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
- writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R);
- writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R);
- writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR);
- writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR);
- writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR);
- writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR);
- writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR);
- writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR);
- writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR);
- writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
- writel_relaxed(config->vissctlr,
- drvdata->base + TRCVISSCTLR);
+ etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR);
+ etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R);
+ etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R);
+ etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR);
+ etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR);
+ etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR);
+ etm4x_relaxed_write32(csa, config->ccctlr, TRCCCCTLR);
+ etm4x_relaxed_write32(csa, config->bb_ctrl, TRCBBCTLR);
+ etm4x_relaxed_write32(csa, drvdata->trcid, TRCTRACEIDR);
+ etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR);
+ etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR);
+ etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR);
if (drvdata->nr_pe_cmp)
- writel_relaxed(config->vipcssctlr,
- drvdata->base + TRCVIPCSSCTLR);
+ etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR);
for (i = 0; i < drvdata->nrseqstate - 1; i++)
- writel_relaxed(config->seq_ctrl[i],
- drvdata->base + TRCSEQEVRn(i));
- writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR);
- writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR);
- writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR);
+ etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i));
+ etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR);
+ etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR);
+ etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR);
for (i = 0; i < drvdata->nr_cntr; i++) {
- writel_relaxed(config->cntrldvr[i],
- drvdata->base + TRCCNTRLDVRn(i));
- writel_relaxed(config->cntr_ctrl[i],
- drvdata->base + TRCCNTCTLRn(i));
- writel_relaxed(config->cntr_val[i],
- drvdata->base + TRCCNTVRn(i));
+ etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i));
+ etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i));
+ etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i));
}

/*
@@ -166,52 +170,45 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
* such start at 2.
*/
for (i = 2; i < drvdata->nr_resource * 2; i++)
- writel_relaxed(config->res_ctrl[i],
- drvdata->base + TRCRSCTLRn(i));
+ etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i));

for (i = 0; i < drvdata->nr_ss_cmp; i++) {
/* always clear status bit on restart if using single-shot */
if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
config->ss_status[i] &= ~BIT(31);
- writel_relaxed(config->ss_ctrl[i],
- drvdata->base + TRCSSCCRn(i));
- writel_relaxed(config->ss_status[i],
- drvdata->base + TRCSSCSRn(i));
+ etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
+ etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
if (drvdata->nr_pe)
- writel_relaxed(config->ss_pe_cmp[i],
- drvdata->base + TRCSSPCICRn(i));
+ etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
}
for (i = 0; i < drvdata->nr_addr_cmp; i++) {
- writeq_relaxed(config->addr_val[i],
- drvdata->base + TRCACVRn(i));
- writeq_relaxed(config->addr_acc[i],
- drvdata->base + TRCACATRn(i));
+ etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
+ etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
}
for (i = 0; i < drvdata->numcidc; i++)
- writeq_relaxed(config->ctxid_pid[i],
- drvdata->base + TRCCIDCVRn(i));
- writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
+ etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i));
+ etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0);
if (drvdata->numcidc > 4)
- writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
+ etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1);

for (i = 0; i < drvdata->numvmidc; i++)
- writeq_relaxed(config->vmid_val[i],
- drvdata->base + TRCVMIDCVRn(i));
- writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
+ etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i));
+ etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0);
if (drvdata->numvmidc > 4)
- writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
+ etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1);

if (!drvdata->skip_power_up) {
+ u32 trcpdcr = etm4x_relaxed_read32(csa, TRCPDCR);
+
/*
* Request to keep the trace unit powered and also
* emulation of powerdown
*/
- writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) |
- TRCPDCR_PU, drvdata->base + TRCPDCR);
+ etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
}

/* Enable the trace unit */
- writel_relaxed(1, drvdata->base + TRCPRGCTLR);
+ etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);

/* wait for TRCSTATR.IDLE to go back down to '0' */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
@@ -487,12 +484,12 @@ static void etm4_disable_hw(void *info)

if (!drvdata->skip_power_up) {
/* power can be removed from the trace unit now */
- control = readl_relaxed(drvdata->base + TRCPDCR);
+ control = etm4x_relaxed_read32(csa, TRCPDCR);
control &= ~TRCPDCR_PU;
- writel_relaxed(control, drvdata->base + TRCPDCR);
+ etm4x_relaxed_write32(csa, control, TRCPDCR);
}

- control = readl_relaxed(drvdata->base + TRCPRGCTLR);
+ control = etm4x_relaxed_read32(csa, TRCPRGCTLR);

/* EN, bit[0] Trace unit enable bit */
control &= ~0x1;
@@ -504,7 +501,7 @@ static void etm4_disable_hw(void *info)
*/
dsb(sy);
isb();
- writel_relaxed(control, drvdata->base + TRCPRGCTLR);
+ etm4x_relaxed_write32(csa, control, TRCPRGCTLR);

/* wait for TRCSTATR.PMSTABLE to go to '1' */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
@@ -514,13 +511,13 @@ static void etm4_disable_hw(void *info)
/* read the status of the single shot comparators */
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
config->ss_status[i] =
- readl_relaxed(drvdata->base + TRCSSCSRn(i));
+ etm4x_relaxed_read32(csa, TRCSSCSRn(i));
}

/* read back the current counter values */
for (i = 0; i < drvdata->nr_cntr; i++) {
config->cntr_val[i] =
- readl_relaxed(drvdata->base + TRCCNTVRn(i));
+ etm4x_relaxed_read32(csa, TRCCNTVRn(i));
}

coresight_disclaim_device_unlocked(csdev);
@@ -549,7 +546,7 @@ static int etm4_disable_perf(struct coresight_device *csdev,
* scheduled again. Configuration of the start/stop logic happens in
* function etm4_set_event_filters().
*/
- control = readl_relaxed(drvdata->base + TRCVICTLR);
+ control = etm4x_relaxed_read32(&csdev->access, TRCVICTLR);
/* TRCVICTLR::SSSTATUS, bit[9] */
filters->ssstatus = (control & BIT(9));

@@ -629,15 +626,17 @@ static void etm4_init_arch_data(void *info)
u32 etmidr4;
u32 etmidr5;
struct etmv4_drvdata *drvdata = info;
+ struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
+ struct csdev_access *csa = &tmp_csa;
int i;

/* Make sure all registers are accessible */
- etm4_os_unlock(drvdata);
+ etm4_os_unlock_csa(drvdata, csa);

CS_UNLOCK(drvdata->base);

/* find all capabilities of the tracing unit */
- etmidr0 = readl_relaxed(drvdata->base + TRCIDR0);
+ etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);

/* INSTP0, bits[2:1] P0 tracing support field */
if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2))
@@ -677,7 +676,7 @@ static void etm4_init_arch_data(void *info)
drvdata->ts_size = BMVAL(etmidr0, 24, 28);

/* base architecture of trace unit */
- etmidr1 = readl_relaxed(drvdata->base + TRCIDR1);
+ etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1);
/*
* TRCARCHMIN, bits[7:4] architecture the minor version number
* TRCARCHMAJ, bits[11:8] architecture major versin number
@@ -686,7 +685,7 @@ static void etm4_init_arch_data(void *info)
drvdata->config.arch = drvdata->arch;

/* maximum size of resources */
- etmidr2 = readl_relaxed(drvdata->base + TRCIDR2);
+ etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
/* CIDSIZE, bits[9:5] Indicates the Context ID size */
drvdata->ctxid_size = BMVAL(etmidr2, 5, 9);
/* VMIDSIZE, bits[14:10] Indicates the VMID size */
@@ -694,7 +693,7 @@ static void etm4_init_arch_data(void *info)
/* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */
drvdata->ccsize = BMVAL(etmidr2, 25, 28);

- etmidr3 = readl_relaxed(drvdata->base + TRCIDR3);
+ etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3);
/* CCITMIN, bits[11:0] minimum threshold value that can be programmed */
drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
/* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
@@ -744,7 +743,7 @@ static void etm4_init_arch_data(void *info)
drvdata->nooverflow = false;

/* number of resources trace unit supports */
- etmidr4 = readl_relaxed(drvdata->base + TRCIDR4);
+ etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4);
/* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */
drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3);
/* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
@@ -770,14 +769,14 @@ static void etm4_init_arch_data(void *info)
drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23);
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
drvdata->config.ss_status[i] =
- readl_relaxed(drvdata->base + TRCSSCSRn(i));
+ etm4x_relaxed_read32(csa, TRCSSCSRn(i));
}
/* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
drvdata->numcidc = BMVAL(etmidr4, 24, 27);
/* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */
drvdata->numvmidc = BMVAL(etmidr4, 28, 31);

- etmidr5 = readl_relaxed(drvdata->base + TRCIDR5);
+ etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5);
/* NUMEXTIN, bits[8:0] number of external inputs implemented */
drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8);
/* TRACEIDSIZE, bits[21:16] indicates the trace ID width */
@@ -1196,56 +1195,56 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)

state = drvdata->save_state;

- state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR);
+ state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR);
if (drvdata->nr_pe)
- state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
- state->trcconfigr = readl(drvdata->base + TRCCONFIGR);
- state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR);
- state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R);
- state->trceventctl1r = readl(drvdata->base + TRCEVENTCTL1R);
- state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR);
- state->trctsctlr = readl(drvdata->base + TRCTSCTLR);
- state->trcsyncpr = readl(drvdata->base + TRCSYNCPR);
- state->trcccctlr = readl(drvdata->base + TRCCCCTLR);
- state->trcbbctlr = readl(drvdata->base + TRCBBCTLR);
- state->trctraceidr = readl(drvdata->base + TRCTRACEIDR);
- state->trcqctlr = readl(drvdata->base + TRCQCTLR);
-
- state->trcvictlr = readl(drvdata->base + TRCVICTLR);
- state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR);
- state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR);
+ state->trcprocselr = etm4x_read32(csa, TRCPROCSELR);
+ state->trcconfigr = etm4x_read32(csa, TRCCONFIGR);
+ state->trcauxctlr = etm4x_read32(csa, TRCAUXCTLR);
+ state->trceventctl0r = etm4x_read32(csa, TRCEVENTCTL0R);
+ state->trceventctl1r = etm4x_read32(csa, TRCEVENTCTL1R);
+ state->trcstallctlr = etm4x_read32(csa, TRCSTALLCTLR);
+ state->trctsctlr = etm4x_read32(csa, TRCTSCTLR);
+ state->trcsyncpr = etm4x_read32(csa, TRCSYNCPR);
+ state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
+ state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
+ state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
+ state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
+
+ state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
+ state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
+ state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
if (drvdata->nr_pe_cmp)
- state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
- state->trcvdctlr = readl(drvdata->base + TRCVDCTLR);
- state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR);
- state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR);
+ state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
+ state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR);
+ state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR);
+ state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR);

for (i = 0; i < drvdata->nrseqstate - 1; i++)
- state->trcseqevr[i] = readl(drvdata->base + TRCSEQEVRn(i));
+ state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));

- state->trcseqrstevr = readl(drvdata->base + TRCSEQRSTEVR);
- state->trcseqstr = readl(drvdata->base + TRCSEQSTR);
- state->trcextinselr = readl(drvdata->base + TRCEXTINSELR);
+ state->trcseqrstevr = etm4x_read32(csa, TRCSEQRSTEVR);
+ state->trcseqstr = etm4x_read32(csa, TRCSEQSTR);
+ state->trcextinselr = etm4x_read32(csa, TRCEXTINSELR);

for (i = 0; i < drvdata->nr_cntr; i++) {
- state->trccntrldvr[i] = readl(drvdata->base + TRCCNTRLDVRn(i));
- state->trccntctlr[i] = readl(drvdata->base + TRCCNTCTLRn(i));
- state->trccntvr[i] = readl(drvdata->base + TRCCNTVRn(i));
+ state->trccntrldvr[i] = etm4x_read32(csa, TRCCNTRLDVRn(i));
+ state->trccntctlr[i] = etm4x_read32(csa, TRCCNTCTLRn(i));
+ state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i));
}

for (i = 0; i < drvdata->nr_resource * 2; i++)
- state->trcrsctlr[i] = readl(drvdata->base + TRCRSCTLRn(i));
+ state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));

for (i = 0; i < drvdata->nr_ss_cmp; i++) {
- state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i));
- state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i));
+ state->trcssccr[i] = etm4x_read32(csa, TRCSSCCRn(i));
+ state->trcsscsr[i] = etm4x_read32(csa, TRCSSCSRn(i));
if (drvdata->nr_pe)
- state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
+ state->trcsspcicr[i] = etm4x_read32(csa, TRCSSPCICRn(i));
}

for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
- state->trcacvr[i] = readq(drvdata->base + TRCACVRn(i));
- state->trcacatr[i] = readq(drvdata->base + TRCACATRn(i));
+ state->trcacvr[i] = etm4x_read64(csa, TRCACVRn(i));
+ state->trcacatr[i] = etm4x_read64(csa, TRCACATRn(i));
}

/*
@@ -1256,22 +1255,22 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
*/

for (i = 0; i < drvdata->numcidc; i++)
- state->trccidcvr[i] = readq(drvdata->base + TRCCIDCVRn(i));
+ state->trccidcvr[i] = etm4x_read64(csa, TRCCIDCVRn(i));

for (i = 0; i < drvdata->numvmidc; i++)
- state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i));
+ state->trcvmidcvr[i] = etm4x_read64(csa, TRCVMIDCVRn(i));

- state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0);
+ state->trccidcctlr0 = etm4x_read32(csa, TRCCIDCCTLR0);
if (drvdata->numcidc > 4)
- state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
+ state->trccidcctlr1 = etm4x_read32(csa, TRCCIDCCTLR1);

- state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
+ state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0);
if (drvdata->numvmidc > 4)
- state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);
+ state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1);

- state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);
+ state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR);

- state->trcpdcr = readl(drvdata->base + TRCPDCR);
+ state->trcpdcr = etm4x_read32(csa, TRCPDCR);

/* wait for TRCSTATR.IDLE to go up */
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
@@ -1289,8 +1288,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
* potentially save power on systems that respect the TRCPDCR_PU
* despite requesting software to save/restore state.
*/
- writel_relaxed((state->trcpdcr & ~TRCPDCR_PU),
- drvdata->base + TRCPDCR);
+ etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);

out:
CS_LOCK(drvdata->base);
@@ -1301,92 +1299,82 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
{
int i;
struct etmv4_save_state *state = drvdata->save_state;
+ struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
+ struct csdev_access *csa = &tmp_csa;

CS_UNLOCK(drvdata->base);

- writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
+ etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);

- writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR);
+ etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
if (drvdata->nr_pe)
- writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
- writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR);
- writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR);
- writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R);
- writel_relaxed(state->trceventctl1r, drvdata->base + TRCEVENTCTL1R);
- writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR);
- writel_relaxed(state->trctsctlr, drvdata->base + TRCTSCTLR);
- writel_relaxed(state->trcsyncpr, drvdata->base + TRCSYNCPR);
- writel_relaxed(state->trcccctlr, drvdata->base + TRCCCCTLR);
- writel_relaxed(state->trcbbctlr, drvdata->base + TRCBBCTLR);
- writel_relaxed(state->trctraceidr, drvdata->base + TRCTRACEIDR);
- writel_relaxed(state->trcqctlr, drvdata->base + TRCQCTLR);
-
- writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR);
- writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR);
- writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR);
+ etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR);
+ etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR);
+ etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR);
+ etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R);
+ etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R);
+ etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR);
+ etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR);
+ etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR);
+ etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
+ etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
+ etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
+ etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
+
+ etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
+ etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
+ etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
if (drvdata->nr_pe_cmp)
- writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
- writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR);
- writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR);
- writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR);
+ etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
+ etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR);
+ etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR);
+ etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR);

for (i = 0; i < drvdata->nrseqstate - 1; i++)
- writel_relaxed(state->trcseqevr[i],
- drvdata->base + TRCSEQEVRn(i));
+ etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));

- writel_relaxed(state->trcseqrstevr, drvdata->base + TRCSEQRSTEVR);
- writel_relaxed(state->trcseqstr, drvdata->base + TRCSEQSTR);
- writel_relaxed(state->trcextinselr, drvdata->base + TRCEXTINSELR);
+ etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR);
+ etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR);
+ etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR);

for (i = 0; i < drvdata->nr_cntr; i++) {
- writel_relaxed(state->trccntrldvr[i],
- drvdata->base + TRCCNTRLDVRn(i));
- writel_relaxed(state->trccntctlr[i],
- drvdata->base + TRCCNTCTLRn(i));
- writel_relaxed(state->trccntvr[i],
- drvdata->base + TRCCNTVRn(i));
+ etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i));
+ etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i));
+ etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i));
}

for (i = 0; i < drvdata->nr_resource * 2; i++)
- writel_relaxed(state->trcrsctlr[i],
- drvdata->base + TRCRSCTLRn(i));
+ etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));

for (i = 0; i < drvdata->nr_ss_cmp; i++) {
- writel_relaxed(state->trcssccr[i],
- drvdata->base + TRCSSCCRn(i));
- writel_relaxed(state->trcsscsr[i],
- drvdata->base + TRCSSCSRn(i));
+ etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i));
+ etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i));
if (drvdata->nr_pe)
- writel_relaxed(state->trcsspcicr[i],
- drvdata->base + TRCSSPCICRn(i));
+ etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i));
}

for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
- writeq_relaxed(state->trcacvr[i],
- drvdata->base + TRCACVRn(i));
- writeq_relaxed(state->trcacatr[i],
- drvdata->base + TRCACATRn(i));
+ etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i));
+ etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i));
}

for (i = 0; i < drvdata->numcidc; i++)
- writeq_relaxed(state->trccidcvr[i],
- drvdata->base + TRCCIDCVRn(i));
+ etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i));

for (i = 0; i < drvdata->numvmidc; i++)
- writeq_relaxed(state->trcvmidcvr[i],
- drvdata->base + TRCVMIDCVRn(i));
+ etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i));

- writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0);
+ etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0);
if (drvdata->numcidc > 4)
- writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
+ etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1);

- writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
+ etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0);
if (drvdata->numvmidc > 4)
- writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);
+ etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1);

- writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
+ etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);

- writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR);
+ etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR);

drvdata->state_needs_restore = false;

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index c4781d4e5886..fce9df16bfb5 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2319,7 +2319,8 @@ static struct attribute *coresight_etmv4_attrs[] = {
};

struct etmv4_reg {
- void __iomem *addr;
+ struct coresight_device *csdev;
+ u32 offset;
u32 data;
};

@@ -2327,7 +2328,7 @@ static void do_smp_cross_read(void *data)
{
struct etmv4_reg *reg = data;

- reg->data = readl_relaxed(reg->addr);
+ reg->data = etm4x_relaxed_read32(&reg->csdev->access, reg->offset);
}

static u32 etmv4_cross_read(const struct device *dev, u32 offset)
@@ -2335,7 +2336,9 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset)
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
struct etmv4_reg reg;

- reg.addr = drvdata->base + offset;
+ reg.offset = offset;
+ reg.csdev = drvdata->csdev;
+
/*
* smp cross call ensures the CPU will be powered up before
* accessing the ETMv4 trace core registers
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index eefc7371c6c4..14e0f29db6b3 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -120,6 +120,30 @@
#define TRCCIDR2 0xFF8
#define TRCCIDR3 0xFFC

+#define etm4x_relaxed_read32(csa, offset) \
+ readl_relaxed((csa)->base + (offset))
+
+#define etm4x_read32(csa, offset) \
+ readl((csa)->base + (offset))
+
+#define etm4x_relaxed_write32(csa, val, offset) \
+ writel_relaxed((val), (csa)->base + (offset))
+
+#define etm4x_write32(csa, val, offset) \
+ writel((val), (csa)->base + (offset))
+
+#define etm4x_relaxed_read64(csa, offset) \
+ readq_relaxed((csa)->base + (offset))
+
+#define etm4x_read64(csa, offset) \
+ readq((csa)->base + (offset))
+
+#define etm4x_relaxed_write64(csa, val, offset) \
+ writeq_relaxed((val), (csa)->base + (offset))
+
+#define etm4x_write64(csa, val, offset) \
+ writeq((val), (csa)->base + (offset))
+
/* ETMv4 resources */
#define ETM_MAX_NR_PE 8
#define ETMv4_MAX_CNTR 4
--
2.24.1

2020-10-29 08:43:51

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 09/26] coresight: Convert coresight_timeout to use access abstraction

Convert the generic routines to use the new access abstraction layer
gradually, starting with coresigth_timeout.

Cc: Mike Leach <[email protected]>
Reviewed-by: Mathieu Poirier <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-catu.c | 5 ++--
drivers/hwtracing/coresight/coresight-core.c | 15 ++++++----
drivers/hwtracing/coresight/coresight-etb10.c | 5 ++--
.../coresight/coresight-etm4x-core.c | 30 ++++++++++++-------
drivers/hwtracing/coresight/coresight-stm.c | 3 +-
.../hwtracing/coresight/coresight-tmc-core.c | 15 ++++++----
drivers/hwtracing/coresight/coresight-tpiu.c | 4 +--
include/linux/coresight.h | 17 ++++++++---
8 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index 5baf29510f1b..34c74b05c542 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {

static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
{
- return coresight_timeout(drvdata->base,
- CATU_STATUS, CATU_STATUS_READY, 1);
+ struct csdev_access *csa = &drvdata->csdev->access;
+
+ return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
}

static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index e96deaca8cab..42ba989a6b5e 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1412,23 +1412,26 @@ static void coresight_remove_conns(struct coresight_device *csdev)
}

/**
- * coresight_timeout - loop until a bit has changed to a specific state.
- * @addr: base address of the area of interest.
- * @offset: address of a register, starting from @addr.
+ * coresight_timeout - loop until a bit has changed to a specific register
+ * state.
+ * @csa: coresight device access for the device
+ * @offset: Offset of the register from the base of the device.
* @position: the position of the bit of interest.
* @value: the value the bit should have.
*
* Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
* TIMEOUT_US has elapsed, which ever happens first.
*/
-
-int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
+int coresight_timeout(struct csdev_access *csa,
+ u32 offset,
+ int position,
+ int value)
{
int i;
u32 val;

for (i = TIMEOUT_US; i > 0; i--) {
- val = __raw_readl(addr + offset);
+ val = csdev_access_read32(csa, offset);
/* waiting on the bit to go from 0 to 1 */
if (value) {
if (val & BIT(position))
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index b91633c6c9b4..f994a22876d9 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -251,6 +251,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
{
u32 ffcr;
struct device *dev = &drvdata->csdev->dev;
+ struct csdev_access *csa = &drvdata->csdev->access;

CS_UNLOCK(drvdata->base);

@@ -262,7 +263,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
ffcr |= ETB_FFCR_FON_MAN;
writel_relaxed(ffcr, drvdata->base + ETB_FFCR);

- if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
+ if (coresight_timeout(csa, ETB_FFCR, ETB_FFCR_BIT, 0)) {
dev_err(dev,
"timeout while waiting for completion of Manual Flush\n");
}
@@ -270,7 +271,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
/* disable trace capture */
writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);

- if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
+ if (coresight_timeout(csa, ETB_FFSR, ETB_FFSR_BIT, 1)) {
dev_err(dev,
"timeout while waiting for Formatter to Stop\n");
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index c5cb93f1b80c..2744aadaa5ec 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -107,7 +107,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
{
int i, rc;
struct etmv4_config *config = &drvdata->config;
- struct device *etm_dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;
+ struct device *etm_dev = &csdev->dev;
+ struct csdev_access *csa = &csdev->access;

CS_UNLOCK(drvdata->base);

@@ -121,7 +123,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writel_relaxed(0, drvdata->base + TRCPRGCTLR);

/* wait for TRCSTATR.IDLE to go up */
- if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
+ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
if (drvdata->nr_pe)
@@ -212,7 +214,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writel_relaxed(1, drvdata->base + TRCPRGCTLR);

/* wait for TRCSTATR.IDLE to go back down to '0' */
- if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
+ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");

@@ -476,7 +478,9 @@ static void etm4_disable_hw(void *info)
u32 control;
struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config;
- struct device *etm_dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;
+ struct device *etm_dev = &csdev->dev;
+ struct csdev_access *csa = &csdev->access;
int i;

CS_UNLOCK(drvdata->base);
@@ -503,8 +507,7 @@ static void etm4_disable_hw(void *info)
writel_relaxed(control, drvdata->base + TRCPRGCTLR);

/* wait for TRCSTATR.PMSTABLE to go to '1' */
- if (coresight_timeout(drvdata->base, TRCSTATR,
- TRCSTATR_PMSTABLE_BIT, 1))
+ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for PM stable Trace Status\n");

@@ -1160,7 +1163,15 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
{
int i, ret = 0;
struct etmv4_save_state *state;
- struct device *etm_dev = &drvdata->csdev->dev;
+ struct coresight_device *csdev = drvdata->csdev;
+ struct csdev_access *csa;
+ struct device *etm_dev;
+
+ if (WARN_ON(!csdev))
+ return -ENODEV;
+
+ etm_dev = &csdev->dev;
+ csa = &csdev->access;

/*
* As recommended by 3.4.1 ("The procedure when powering down the PE")
@@ -1175,8 +1186,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
etm4_os_lock(drvdata);

/* wait for TRCSTATR.PMSTABLE to go up */
- if (coresight_timeout(drvdata->base, TRCSTATR,
- TRCSTATR_PMSTABLE_BIT, 1)) {
+ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) {
dev_err(etm_dev,
"timeout while waiting for PM Stable Status\n");
etm4_os_unlock(drvdata);
@@ -1264,7 +1274,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcpdcr = readl(drvdata->base + TRCPDCR);

/* wait for TRCSTATR.IDLE to go up */
- if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
+ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
etm4_os_unlock(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index 315500b7763f..9cba67b27586 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -258,6 +258,7 @@ static void stm_disable(struct coresight_device *csdev,
struct perf_event *event)
{
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ struct csdev_access *csa = &csdev->access;

/*
* For as long as the tracer isn't disabled another entity can't
@@ -270,7 +271,7 @@ static void stm_disable(struct coresight_device *csdev,
spin_unlock(&drvdata->spinlock);

/* Wait until the engine has completely stopped */
- coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0);
+ coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0);

pm_runtime_put(csdev->dev.parent);

diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 8fd640d41e1b..572f4b316798 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -33,16 +33,20 @@ DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");

void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
+ struct coresight_device *csdev = drvdata->csdev;
+ struct csdev_access *csa = &csdev->access;
+
/* Ensure formatter, unformatter and hardware fifo are empty */
- if (coresight_timeout(drvdata->base,
- TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
- dev_err(&drvdata->csdev->dev,
+ if (coresight_timeout(csa, TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
+ dev_err(&csdev->dev,
"timeout while waiting for TMC to be Ready\n");
}
}

void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
{
+ struct coresight_device *csdev = drvdata->csdev;
+ struct csdev_access *csa = &csdev->access;
u32 ffcr;

ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
@@ -51,9 +55,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
/* Ensure flush completes */
- if (coresight_timeout(drvdata->base,
- TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
- dev_err(&drvdata->csdev->dev,
+ if (coresight_timeout(csa, TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
+ dev_err(&csdev->dev,
"timeout while waiting for completion of Manual Flush\n");
}

diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 98c4a029854c..1e92c76d9656 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -86,9 +86,9 @@ static void tpiu_disable_hw(struct csdev_access *csa)
/* Generate manual flush */
csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR);
/* Wait for flush to complete */
- coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
+ coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
/* Wait for formatter to stop */
- coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
+ coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);

CS_LOCK(csa->base);
}
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 5a34c2f2debc..cefc8fe239e6 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -469,8 +469,10 @@ coresight_register(struct coresight_desc *desc);
extern void coresight_unregister(struct coresight_device *csdev);
extern int coresight_enable(struct coresight_device *csdev);
extern void coresight_disable(struct coresight_device *csdev);
-extern int coresight_timeout(void __iomem *addr, u32 offset,
- int position, int value);
+extern int coresight_timeout(struct csdev_access *csa,
+ u32 offset,
+ int position,
+ int value);

extern int coresight_claim_device(void __iomem *base);
extern int coresight_claim_device_unlocked(void __iomem *base);
@@ -502,8 +504,15 @@ static inline void coresight_unregister(struct coresight_device *csdev) {}
static inline int
coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
static inline void coresight_disable(struct coresight_device *csdev) {}
-static inline int coresight_timeout(void __iomem *addr, u32 offset,
- int position, int value) { return 1; }
+
+static inline int coresight_timeout(struct csdev_access *csa,
+ u32 offset,
+ int position,
+ int value)
+{
+ return 1;
+}
+
static inline int coresight_claim_device_unlocked(void __iomem *base)
{
return -EINVAL;
--
2.24.1

2020-10-29 08:44:00

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 06/26] coresight: etm4x: Handle access to TRCSSPCICRn

TRCSSPCICR<n> is present only if all of the following are true:
TRCIDR4.NUMSSCC > n.
TRCIDR4.NUMPC > 0b0000 .
TRCSSCSR<n>.PC == 0b1

Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index d78a37b6592c..0310eac9dc16 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -175,8 +175,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
drvdata->base + TRCSSCCRn(i));
writel_relaxed(config->ss_status[i],
drvdata->base + TRCSSCSRn(i));
- writel_relaxed(config->ss_pe_cmp[i],
- drvdata->base + TRCSSPCICRn(i));
+ if (drvdata->nr_pe)
+ writel_relaxed(config->ss_pe_cmp[i],
+ drvdata->base + TRCSSPCICRn(i));
}
for (i = 0; i < drvdata->nr_addr_cmp; i++) {
writeq_relaxed(config->addr_val[i],
@@ -1228,7 +1229,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i));
state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i));
- state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
+ if (drvdata->nr_pe)
+ state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
}

for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
@@ -1344,8 +1346,9 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
drvdata->base + TRCSSCCRn(i));
writel_relaxed(state->trcsscsr[i],
drvdata->base + TRCSSCSRn(i));
- writel_relaxed(state->trcsspcicr[i],
- drvdata->base + TRCSSPCICRn(i));
+ if (drvdata->nr_pe)
+ writel_relaxed(state->trcsspcicr[i],
+ drvdata->base + TRCSSPCICRn(i));
}

for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
--
2.24.1

2020-10-29 08:44:14

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 02/26] coresight: etm4x: Fix accesses to TRCCIDCTLR1

The TRCCIDCTLR1 is only implemented if TRCIDR4.NUMCIDC > 4.
Don't touch the register if it is not implemented.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index e67365d1ce28..af0ab2f44865 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -187,7 +187,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writeq_relaxed(config->ctxid_pid[i],
drvdata->base + TRCCIDCVRn(i));
writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
- writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);

for (i = 0; i < drvdata->numvmidc; i++)
writeq_relaxed(config->vmid_val[i],
@@ -1241,7 +1242,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i));

state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0);
- state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);

state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
if (drvdata->numvmidc > 4)
@@ -1352,7 +1354,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
drvdata->base + TRCVMIDCVRn(i));

writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0);
- writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
+ if (drvdata->numcidc > 4)
+ writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);

writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
if (drvdata->numvmidc > 4)
--
2.24.1

2020-10-29 08:45:12

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 00/26] coresight: Support for ETM system instructions

CoreSight ETMv4.4 obsoletes memory mapped access to ETM and
mandates the system instructions for registers.
This also implies that they may not be on the amba bus.
Right now all the CoreSight components are accessed via memory
map. Also, we have some common routines in coresight generic
code driver (e.g, CS_LOCK, claim/disclaim), which assume the
mmio. In order to preserve the generic algorithms at a single
place and to allow dynamic switch for ETMs, this series introduces
an abstraction layer for accessing a coresight device. It is
designed such that the mmio access are fast tracked (i.e, without
an indirect function call).

This will also help us to get rid of the driver+attribute specific
sysfs show/store routines and replace them with a single routine
to access a given register offset (which can be embedded in the
dev_ext_attribute). This is not currently implemented in the series,
but can be achieved.

Further we switch the generic routines to work with the abstraction.
With this in place, we refactor the etm4x code a bit to allow for
supporting the system instructions with very little new code. The
changes also switch to using the system instructions by default
even when we may have an MMIO.

We use TRCDEVARCH for the detection of the ETM component, which
is a standard register as per CoreSight architecture, rather than
the etm specific id register TRCIDR1. This is for making sure
that we are able to detect the ETM via system instructions accurately,
when the the trace unit could be anything (etm or a custom trace unit).
To keep the backward compatibility for any existing broken impelementation
which may not implement TRCDEVARCH, we fall back to TRCIDR1. Also
this covers us for the changes in the future architecture [0].

The series has been mildly tested on a model for system instructions.
I would really appreciate any testing on real hardware.

Applies on coresight/next.

[0] https://developer.arm.com/docs/ddi0601/g/aarch64-system-registers/trcidr1

Known issues:
Checkpatch failure for "coresight: etm4x: Add sysreg access helpers" :

ERROR: Macros with complex values should be enclosed in parentheses
#121: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:153:
+#define CASE_READ(res, x) \
+ case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }


I don't know how to fix that without breaking the build ! Suggestions
welcome.


Changes since V2:
- Several fixes to the ETM register accesses. Access a register
when it is present.
- Add support for TRCIDR3.NUMPROCS for v4.2+
- Drop OS lock detection. Use software lock only in case of mmio.
- Fix issues with the Exception level masks (Mike Leach)
- Fall back to using TRCIDR1 when TRCDEVARCH is not "present"
- Use a generic notion of ETM architecture (rather than using
the encoding as in registers)
- Fixed some checkpatch issues.
- Add support for Self Hosted tracing Arm v8.4 extensions. (Mike
Leach)
Originally written by Jonathan, refactored and cleaned up.
- Changed the dts compatible string to "arm,coresight-etm-sysreg"
(Mike Leach)

Changes since V1:
- Flip the switch for iomem from no_iomem to io_mem in csdev_access.
- Split patches for claim/disclaim and CS_LOCK/UNLOCK conversions.
- Move device access initialisation for etm4x to the target CPU
- Cleanup secure exception level mask handling.
- Switch to use TRCDEVARCH for ETM component discovery. This
is for making
- Check the availability of OS/Software Locks before using them.


Suzuki K Poulose (26):
coresight: etm4x: Fix accesses to TRCVMIDCTLR1
coresight: etm4x: Fix accesses to TRCCIDCTLR1
coresight: etm4x: Update TRCIDR3.NUMPROCS handling to match v4.2
coresight: etm4x: Fix accesses to TRCPROCSELR
coresight: etm4x: Handle TRCVIPCSSCTLR accesses
coresight: etm4x: Handle access to TRCSSPCICRn
coresight: Introduce device access abstraction
coresight: tpiu: Prepare for using coresight device access abstraction
coresight: Convert coresight_timeout to use access abstraction
coresight: Convert claim/disclaim operations to use access wrappers
coresight: etm4x: Always read the registers on the host CPU
coresight: etm4x: Convert all register accesses
coresight: etm4x: Add commentary on the registers
coresight: etm4x: Add sysreg access helpers
coresight: etm4x: Define DEVARCH register fields
coresight: etm4x: Check for Software Lock
coresight: etm4x: Cleanup secure exception level masks
coresight: etm4x: Clean up exception level masks
coresight: etm4x: Detect access early on the target CPU
coresight: etm4x: Handle ETM architecture version
coresight: etm4x: Use TRCDEVARCH for component discovery
coresight: etm4x: Add necessary synchronization for sysreg access
coresight: etm4x: Detect system instructions support
coresight: etm4x: Refactor probing routine
coresight: etm4x: Add support for sysreg only devices
dts: bindings: coresight: ETM system register access only units

.../devicetree/bindings/arm/coresight.txt | 5 +-
drivers/hwtracing/coresight/coresight-catu.c | 12 +-
drivers/hwtracing/coresight/coresight-core.c | 130 ++-
.../hwtracing/coresight/coresight-cti-core.c | 18 +-
drivers/hwtracing/coresight/coresight-etb10.c | 10 +-
.../coresight/coresight-etm3x-core.c | 9 +-
.../coresight/coresight-etm4x-core.c | 758 +++++++++++-------
.../coresight/coresight-etm4x-sysfs.c | 44 +-
drivers/hwtracing/coresight/coresight-etm4x.h | 501 +++++++++++-
.../hwtracing/coresight/coresight-funnel.c | 7 +-
.../coresight/coresight-replicator.c | 17 +-
drivers/hwtracing/coresight/coresight-stm.c | 4 +-
.../hwtracing/coresight/coresight-tmc-core.c | 16 +-
.../hwtracing/coresight/coresight-tmc-etf.c | 10 +-
.../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
drivers/hwtracing/coresight/coresight-tpiu.c | 31 +-
include/linux/coresight.h | 230 +++++-
17 files changed, 1376 insertions(+), 430 deletions(-)

--
2.24.1

2020-10-29 08:45:50

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 11/26] coresight: etm4x: Always read the registers on the host CPU

As we are about to add support for sysreg access to ETM4.4+ components,
make sure that we read the registers only on the host CPU.

Cc: Mike Leach <[email protected]>
Reviewed-by: Mathieu Poirier <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-sysfs.c | 23 ++++++++-----------
1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index 989ce7b8ade7..c4781d4e5886 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -2344,23 +2344,20 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset)
return reg.data;
}

-#define coresight_etm4x_reg(name, offset) \
- coresight_simple_reg32(struct etmv4_drvdata, name, offset)
-
#define coresight_etm4x_cross_read(name, offset) \
coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read, \
name, offset)

-coresight_etm4x_reg(trcpdcr, TRCPDCR);
-coresight_etm4x_reg(trcpdsr, TRCPDSR);
-coresight_etm4x_reg(trclsr, TRCLSR);
-coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS);
-coresight_etm4x_reg(trcdevid, TRCDEVID);
-coresight_etm4x_reg(trcdevtype, TRCDEVTYPE);
-coresight_etm4x_reg(trcpidr0, TRCPIDR0);
-coresight_etm4x_reg(trcpidr1, TRCPIDR1);
-coresight_etm4x_reg(trcpidr2, TRCPIDR2);
-coresight_etm4x_reg(trcpidr3, TRCPIDR3);
+coresight_etm4x_cross_read(trcpdcr, TRCPDCR);
+coresight_etm4x_cross_read(trcpdsr, TRCPDSR);
+coresight_etm4x_cross_read(trclsr, TRCLSR);
+coresight_etm4x_cross_read(trcauthstatus, TRCAUTHSTATUS);
+coresight_etm4x_cross_read(trcdevid, TRCDEVID);
+coresight_etm4x_cross_read(trcdevtype, TRCDEVTYPE);
+coresight_etm4x_cross_read(trcpidr0, TRCPIDR0);
+coresight_etm4x_cross_read(trcpidr1, TRCPIDR1);
+coresight_etm4x_cross_read(trcpidr2, TRCPIDR2);
+coresight_etm4x_cross_read(trcpidr3, TRCPIDR3);
coresight_etm4x_cross_read(trcoslsr, TRCOSLSR);
coresight_etm4x_cross_read(trcconfig, TRCCONFIGR);
coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
--
2.24.1

2020-10-29 08:46:00

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 05/26] coresight: etm4x: Handle TRCVIPCSSCTLR accesses

TRCVIPCSSCTLR is not present if the TRCIDR4.NUMPC > 0. Thus we
should only access the register if it is present, preventing
any undesired behavior.

Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 28dd278f6d47..d78a37b6592c 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -141,8 +141,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(config->vissctlr,
drvdata->base + TRCVISSCTLR);
- writel_relaxed(config->vipcssctlr,
- drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ writel_relaxed(config->vipcssctlr,
+ drvdata->base + TRCVIPCSSCTLR);
for (i = 0; i < drvdata->nrseqstate - 1; i++)
writel_relaxed(config->seq_ctrl[i],
drvdata->base + TRCSEQEVRn(i));
@@ -1202,7 +1203,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcvictlr = readl(drvdata->base + TRCVICTLR);
state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR);
state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR);
- state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
state->trcvdctlr = readl(drvdata->base + TRCVDCTLR);
state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR);
state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR);
@@ -1310,7 +1312,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR);
writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR);
- writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
+ if (drvdata->nr_pe_cmp)
+ writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR);
writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR);
writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR);
--
2.24.1

2020-10-29 08:46:09

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 01/26] coresight: etm4x: Fix accesses to TRCVMIDCTLR1

TRCVMIDCTRL1 is only implemented only if the TRCIDR4.NUMVMIDC > 4.
We must not touch the register otherwise.

Cc: [email protected]
Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm4x-core.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 6096d7abf80d..e67365d1ce28 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -193,7 +193,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
writeq_relaxed(config->vmid_val[i],
drvdata->base + TRCVMIDCVRn(i));
writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
- writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);

if (!drvdata->skip_power_up) {
/*
@@ -1243,7 +1244,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);

state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
- state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);

state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);

@@ -1353,7 +1355,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);

writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
- writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);
+ if (drvdata->numvmidc > 4)
+ writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);

writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);

--
2.24.1

2020-10-29 09:05:55

by Mike Leach

[permalink] [raw]
Subject: Re: [PATCH v3 00/26] coresight: Support for ETM system instructions

Hi Suzuki,

On Wed, 28 Oct 2020 at 22:10, Suzuki K Poulose <[email protected]> wrote:
>
> CoreSight ETMv4.4 obsoletes memory mapped access to ETM and
> mandates the system instructions for registers.
> This also implies that they may not be on the amba bus.
> Right now all the CoreSight components are accessed via memory
> map. Also, we have some common routines in coresight generic
> code driver (e.g, CS_LOCK, claim/disclaim), which assume the
> mmio. In order to preserve the generic algorithms at a single
> place and to allow dynamic switch for ETMs, this series introduces
> an abstraction layer for accessing a coresight device. It is
> designed such that the mmio access are fast tracked (i.e, without
> an indirect function call).
>
> This will also help us to get rid of the driver+attribute specific
> sysfs show/store routines and replace them with a single routine
> to access a given register offset (which can be embedded in the
> dev_ext_attribute). This is not currently implemented in the series,
> but can be achieved.
>
> Further we switch the generic routines to work with the abstraction.
> With this in place, we refactor the etm4x code a bit to allow for
> supporting the system instructions with very little new code. The
> changes also switch to using the system instructions by default
> even when we may have an MMIO.
>
> We use TRCDEVARCH for the detection of the ETM component, which
> is a standard register as per CoreSight architecture, rather than
> the etm specific id register TRCIDR1. This is for making sure
> that we are able to detect the ETM via system instructions accurately,
> when the the trace unit could be anything (etm or a custom trace unit).
> To keep the backward compatibility for any existing broken impelementation
> which may not implement TRCDEVARCH, we fall back to TRCIDR1. Also
> this covers us for the changes in the future architecture [0].
>
> The series has been mildly tested on a model for system instructions.
> I would really appreciate any testing on real hardware.
>
> Applies on coresight/next.
>
> [0] https://developer.arm.com/docs/ddi0601/g/aarch64-system-registers/trcidr1
>
> Known issues:
> Checkpatch failure for "coresight: etm4x: Add sysreg access helpers" :
>
> ERROR: Macros with complex values should be enclosed in parentheses
> #121: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:153:
> +#define CASE_READ(res, x) \
> + case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
>
>
> I don't know how to fix that without breaking the build ! Suggestions
> welcome.
>

I hit exactly the same issue with my recent v2 set. The checker really
hates case statements in macros. In my case I shut it up for v3 by
changing:-

#define MAPREG(cval, elem) \
case cval: \
reg->drv_store = &drvcfg->elem; \
break;


if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
switch (offset) {
/* 32 bit single control and filter registers */
MAPREG(TRCEVENTCTL0R, eventctrl0);
MAPREG(TRCEVENTCTL1R, eventctrl1);
MAPREG(TRCSTALLCTLR, stall_ctrl);
MAPREG(TRCTSCTLR, ts_ctrl);
MAPREG(TRCSYNCPR, syncfreq);
MAPREG(TRCCCCTLR, ccctlr);
MAPREG(TRCBBCTLR, bb_ctrl);
MAPREG(TRCVICTLR, vinst_ctrl);
MAPREG(TRCVIIECTLR, viiectlr);
MAPREG(TRCVISSCTLR, vissctlr);
MAPREG(TRCVIPCSSCTLR, vipcssctlr);
MAPREG(TRCSEQRSTEVR, seq_rst);
MAPREG(TRCSEQSTR, seq_state);
MAPREG(TRCEXTINSELR, ext_inp);
MAPREG(TRCCIDCCTLR0, ctxid_mask0);
MAPREG(TRCCIDCCTLR1, ctxid_mask1);
MAPREG(TRCVMIDCCTLR0, vmid_mask0);
MAPREG(TRCVMIDCCTLR1, vmid_mask1);
default:
err = -EINVAL;
break;
}


to

err = -EINVAL;

#define CHECKREG(cval, elem) \
{ \
if (offset == cval) { \
reg->drv_store = &drvcfg->elem; \
err = 0; \
break; \
} \
}

if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
do {
CHECKREG(TRCEVENTCTL0R, eventctrl0);
CHECKREG(TRCEVENTCTL1R, eventctrl1);
CHECKREG(TRCSTALLCTLR, stall_ctrl);
CHECKREG(TRCTSCTLR, ts_ctrl);
CHECKREG(TRCSYNCPR, syncfreq);
CHECKREG(TRCCCCTLR, ccctlr);
CHECKREG(TRCBBCTLR, bb_ctrl);
CHECKREG(TRCVICTLR, vinst_ctrl);
CHECKREG(TRCVIIECTLR, viiectlr);
CHECKREG(TRCVISSCTLR, vissctlr);
CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
CHECKREG(TRCSEQRSTEVR, seq_rst);
CHECKREG(TRCSEQSTR, seq_state);
CHECKREG(TRCEXTINSELR, ext_inp);
CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
} while (0);


A bit contrived but functionally the same - and doesn't annoy the
checker, No idea if the code is more or less efficient after
compilation than a standard switch / case combo, but not on a critical
path for me so wasn't bothered.
As I look again I could have actually put the err = -EINVAL; line just
before the while(0) statement - making it more like a case default -
but my current set is too close to release to change that now.

Cheers

Mike


>
> Changes since V2:
> - Several fixes to the ETM register accesses. Access a register
> when it is present.
> - Add support for TRCIDR3.NUMPROCS for v4.2+
> - Drop OS lock detection. Use software lock only in case of mmio.
> - Fix issues with the Exception level masks (Mike Leach)
> - Fall back to using TRCIDR1 when TRCDEVARCH is not "present"
> - Use a generic notion of ETM architecture (rather than using
> the encoding as in registers)
> - Fixed some checkpatch issues.
> - Add support for Self Hosted tracing Arm v8.4 extensions. (Mike
> Leach)
> Originally written by Jonathan, refactored and cleaned up.
> - Changed the dts compatible string to "arm,coresight-etm-sysreg"
> (Mike Leach)
>
> Changes since V1:
> - Flip the switch for iomem from no_iomem to io_mem in csdev_access.
> - Split patches for claim/disclaim and CS_LOCK/UNLOCK conversions.
> - Move device access initialisation for etm4x to the target CPU
> - Cleanup secure exception level mask handling.
> - Switch to use TRCDEVARCH for ETM component discovery. This
> is for making
> - Check the availability of OS/Software Locks before using them.
>
>
> Suzuki K Poulose (26):
> coresight: etm4x: Fix accesses to TRCVMIDCTLR1
> coresight: etm4x: Fix accesses to TRCCIDCTLR1
> coresight: etm4x: Update TRCIDR3.NUMPROCS handling to match v4.2
> coresight: etm4x: Fix accesses to TRCPROCSELR
> coresight: etm4x: Handle TRCVIPCSSCTLR accesses
> coresight: etm4x: Handle access to TRCSSPCICRn
> coresight: Introduce device access abstraction
> coresight: tpiu: Prepare for using coresight device access abstraction
> coresight: Convert coresight_timeout to use access abstraction
> coresight: Convert claim/disclaim operations to use access wrappers
> coresight: etm4x: Always read the registers on the host CPU
> coresight: etm4x: Convert all register accesses
> coresight: etm4x: Add commentary on the registers
> coresight: etm4x: Add sysreg access helpers
> coresight: etm4x: Define DEVARCH register fields
> coresight: etm4x: Check for Software Lock
> coresight: etm4x: Cleanup secure exception level masks
> coresight: etm4x: Clean up exception level masks
> coresight: etm4x: Detect access early on the target CPU
> coresight: etm4x: Handle ETM architecture version
> coresight: etm4x: Use TRCDEVARCH for component discovery
> coresight: etm4x: Add necessary synchronization for sysreg access
> coresight: etm4x: Detect system instructions support
> coresight: etm4x: Refactor probing routine
> coresight: etm4x: Add support for sysreg only devices
> dts: bindings: coresight: ETM system register access only units
>
> .../devicetree/bindings/arm/coresight.txt | 5 +-
> drivers/hwtracing/coresight/coresight-catu.c | 12 +-
> drivers/hwtracing/coresight/coresight-core.c | 130 ++-
> .../hwtracing/coresight/coresight-cti-core.c | 18 +-
> drivers/hwtracing/coresight/coresight-etb10.c | 10 +-
> .../coresight/coresight-etm3x-core.c | 9 +-
> .../coresight/coresight-etm4x-core.c | 758 +++++++++++-------
> .../coresight/coresight-etm4x-sysfs.c | 44 +-
> drivers/hwtracing/coresight/coresight-etm4x.h | 501 +++++++++++-
> .../hwtracing/coresight/coresight-funnel.c | 7 +-
> .../coresight/coresight-replicator.c | 17 +-
> drivers/hwtracing/coresight/coresight-stm.c | 4 +-
> .../hwtracing/coresight/coresight-tmc-core.c | 16 +-
> .../hwtracing/coresight/coresight-tmc-etf.c | 10 +-
> .../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
> drivers/hwtracing/coresight/coresight-tpiu.c | 31 +-
> include/linux/coresight.h | 230 +++++-
> 17 files changed, 1376 insertions(+), 430 deletions(-)
>
> --
> 2.24.1
>


--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

2020-10-29 09:53:36

by Suzuki K Poulose

[permalink] [raw]
Subject: [PATCH v3 15/26] coresight: etm4x: Define DEVARCH register fields

Define the fields of the DEVARCH register for identifying
a component as an ETMv4.x unit. Going forward, we use the
DEVARCH register for the component identification, rather
than the TRCIDR3.

Cc: Mathieu Poirier <[email protected]>
Cc: Mike Leach <[email protected]>
Signed-off-by: Suzuki K Poulose <[email protected]>
---
.../coresight/coresight-etm4x-core.c | 4 +-
drivers/hwtracing/coresight/coresight-etm4x.h | 42 +++++++++++++++++++
2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 90b80982c615..a5c914b16e59 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -1610,8 +1610,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
static struct amba_cs_uci_id uci_id_etm4[] = {
{
/* ETMv4 UCI data */
- .devarch = 0x47704a13,
- .devarch_mask = 0xfff0ffff,
+ .devarch = ETM_DEVARCH_ETMv4x_ARCH,
+ .devarch_mask = ETM_DEVARCH_ID_MASK,
.devtype = 0x00000013,
}
};
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 5cf71b30a652..e7f6b7b16fb7 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -497,6 +497,48 @@
ETM_MODE_EXCL_KERN | \
ETM_MODE_EXCL_USER)

+/*
+ * TRCDEVARCH Bit field definitions
+ * Bits[31:21] - ARCHITECT = Always Arm Ltd.
+ * * Bits[31:28] = 0x4
+ * * Bits[27:21] = 0b0111011
+ * Bit[20] - PRESENT, Indicates the presence of this register.
+ *
+ * Bit[19:16] - REVISION, Revision of the architecture.
+ *
+ * Bit[15:0] - ARCHID, Identifies this component as an ETM
+ * * Bits[15:12] - architecture version of ETM
+ * * = 4 for ETMv4
+ * * Bits[11:0] = 0xA13, architecture part number for ETM.
+ */
+#define ETM_DEVARCH_ARCHITECT_MASK GENMASK(31, 21)
+#define ETM_DEVARCH_ARCHITECT_ARM ((0x4 << 28) | (0b0111011 << 21))
+#define ETM_DEVARCH_PRESENT BIT(20)
+#define ETM_DEVARCH_REVISION_SHIFT 16
+#define ETM_DEVARCH_REVISION_MASK GENMASK(19, 16)
+#define ETM_DEVARCH_REVISION(x) \
+ (((x) & ETM_DEVARCH_REVISION_MASK) >> ETM_DEVARCH_REVISION_SHIFT)
+#define ETM_DEVARCH_ARCHID_MASK GENMASK(15, 0)
+#define ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT 12
+#define ETM_DEVARCH_ARCHID_ARCH_VER_MASK GENMASK(15, 12)
+#define ETM_DEVARCH_ARCHID_ARCH_VER(x) \
+ (((x) & ETM_DEVARCH_ARCHID_ARCH_VER_MASK) >> ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT)
+
+#define ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(ver) \
+ (((ver) << ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT) & ETM_DEVARCH_ARCHID_ARCH_VER_MASK)
+
+#define ETM_DEVARCH_ARCHID_ARCH_PART(x) ((x) & 0xfffUL)
+
+#define ETM_DEVARCH_MAKE_ARCHID(major) \
+ ((ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(major)) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13))
+
+#define ETM_DEVARCH_ARCHID_ETMv4x ETM_DEVARCH_MAKE_ARCHID(0x4)
+
+#define ETM_DEVARCH_ID_MASK \
+ (ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT)
+#define ETM_DEVARCH_ETMv4x_ARCH \
+ (ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4x | ETM_DEVARCH_PRESENT)
+
#define TRCSTATR_IDLE_BIT 0
#define TRCSTATR_PMSTABLE_BIT 1
#define ETM_DEFAULT_ADDR_COMP 0
--
2.24.1

2020-10-29 15:32:48

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 14/26] coresight: etm4x: Add sysreg access helpers

Joe, Andy

Need your input on the checkpatch failures on this patch. Please
see below.


On 10/28/20 10:09 PM, Suzuki K Poulose wrote:
> ETMv4.4 architecture defines the system instructions for accessing
> ETM via register accesses. Add basic support for accessing a given
> register via system instructions.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 39 ++
> drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++--
> 2 files changed, 365 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 4af7d45dfe63..90b80982c615 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>
> static enum cpuhp_state hp_online;
>
> +u64 etm4x_sysreg_read(struct csdev_access *csa,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit)
> +{
> + u64 res = 0;
> +
> + switch (offset) {
> + ETM4x_READ_CASES(res)
> + default :
> + WARN_ONCE(1, "etm4x: trying to read unsupported register @%x\n",
> + offset);
> + }
> +
> + if (!_relaxed)
> + __iormb(res); /* Imitate the !relaxed I/O helpers */
> +
> + return res;
> +}
> +
> +void etm4x_sysreg_write(struct csdev_access *csa,
> + u64 val,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit)
> +{
> + if (!_relaxed)
> + __iowmb(); /* Imitate the !relaxed I/O helpers */
> + if (!_64bit)
> + val &= GENMASK(31, 0);
> +
> + switch (offset) {
> + ETM4x_WRITE_CASES(val)
> + default :
> + WARN_ONCE(1, "etm4x: trying to write to unsupported register @%x\n",
> + offset);
> + }
> +}
> +
> static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
> {
> /* Writing 0 to TRCOSLAR unlocks the trace registers */
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 510828c73db6..5cf71b30a652 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -125,29 +125,323 @@
> #define TRCCIDR2 0xFF8
> #define TRCCIDR3 0xFFC
>
> -#define etm4x_relaxed_read32(csa, offset) \
> - readl_relaxed((csa)->base + (offset))
> -
> -#define etm4x_read32(csa, offset) \
> - readl((csa)->base + (offset))
> -
> -#define etm4x_relaxed_write32(csa, val, offset) \
> - writel_relaxed((val), (csa)->base + (offset))
> -
> -#define etm4x_write32(csa, val, offset) \
> - writel((val), (csa)->base + (offset))
> -
> -#define etm4x_relaxed_read64(csa, offset) \
> - readq_relaxed((csa)->base + (offset))
> -
> -#define etm4x_read64(csa, offset) \
> - readq((csa)->base + (offset))
> -
> -#define etm4x_relaxed_write64(csa, val, offset) \
> - writeq_relaxed((val), (csa)->base + (offset))
> +/*
> + * System instructions to access ETM registers.
> + * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
> + */
> +#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2)
> +
> +#define ETM4x_CRn(n) (((n) >> 7) & 0x7)
> +#define ETM4x_Op2(n) (((n) >> 4) & 0x7)
> +#define ETM4x_CRm(n) ((n) & 0xf)
> +
> +#include <asm/sysreg.h>
> +#define ETM4x_REG_NUM_TO_SYSREG(n) \
> + sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n))
> +
> +#define READ_ETM4x_REG(reg) \
> + read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg)))
> +#define WRITE_ETM4x_REG(val, reg) \
> + write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg)))
> +
> +#define read_etm4x_sysreg_const_offset(offset) \
> + READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset))
> +
> +#define write_etm4x_sysreg_const_offset(val, offset) \
> + WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset))


Check patch errors as below :

ERROR: Macros with complex values should be enclosed in parentheses
#121: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:153:
+#define CASE_READ(res, x) \
+ case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }

ERROR: trailing statements should be on next line
#122: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:154:
+ case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }

This one may be fixed by splitting the above line to multpile lines.
But the first one above is not easy to fix. And there are more users
of such constructs elsewhere.

> +
> +#define CASE_READ(res, x) \
> + case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
> +

> +#define CASE_WRITE(val, x) \
> + case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; }
> +

Checkpatch error for the CASE_LIST:


ERROR: Macros with complex values should be enclosed in parentheses
#127: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:159:

> +#define CASE_LIST(op, val) \
> + CASE_##op((val), TRCPRGCTLR) \
> + CASE_##op((val), TRCPROCSELR) \
> + CASE_##op((val), TRCSTATR) \
> + CASE_##op((val), TRCCONFIGR) \
> + CASE_##op((val), TRCAUXCTLR) \
> + CASE_##op((val), TRCEVENTCTL0R) \
> + CASE_##op((val), TRCEVENTCTL1R) \
> + CASE_##op((val), TRCSTALLCTLR) \
> + CASE_##op((val), TRCTSCTLR) \
> + CASE_##op((val), TRCSYNCPR) \
> + CASE_##op((val), TRCCCCTLR) \
> + CASE_##op((val), TRCBBCTLR) \
> + CASE_##op((val), TRCTRACEIDR) \
> + CASE_##op((val), TRCQCTLR) \
> + CASE_##op((val), TRCVICTLR) \
> + CASE_##op((val), TRCVIIECTLR) \
> + CASE_##op((val), TRCVISSCTLR) \
> + CASE_##op((val), TRCVIPCSSCTLR) \
> + CASE_##op((val), TRCVDCTLR) \
> + CASE_##op((val), TRCVDSACCTLR) \
> + CASE_##op((val), TRCVDARCCTLR) \
> + CASE_##op((val), TRCSEQEVRn(0)) \
> + CASE_##op((val), TRCSEQEVRn(1)) \
> + CASE_##op((val), TRCSEQEVRn(2)) \
> + CASE_##op((val), TRCSEQRSTEVR) \
> + CASE_##op((val), TRCSEQSTR) \
> + CASE_##op((val), TRCEXTINSELR) \
> + CASE_##op((val), TRCCNTRLDVRn(0)) \
> + CASE_##op((val), TRCCNTRLDVRn(1)) \
> + CASE_##op((val), TRCCNTRLDVRn(2)) \
> + CASE_##op((val), TRCCNTRLDVRn(3)) \
> + CASE_##op((val), TRCCNTCTLRn(0)) \
> + CASE_##op((val), TRCCNTCTLRn(1)) \
> + CASE_##op((val), TRCCNTCTLRn(2)) \
> + CASE_##op((val), TRCCNTCTLRn(3)) \
> + CASE_##op((val), TRCCNTVRn(0)) \
> + CASE_##op((val), TRCCNTVRn(1)) \
> + CASE_##op((val), TRCCNTVRn(2)) \
> + CASE_##op((val), TRCCNTVRn(3)) \
> + CASE_##op((val), TRCIDR8) \
> + CASE_##op((val), TRCIDR9) \
> + CASE_##op((val), TRCIDR10) \
> + CASE_##op((val), TRCIDR11) \
> + CASE_##op((val), TRCIDR12) \
> + CASE_##op((val), TRCIDR13) \
> + CASE_##op((val), TRCIMSPECn(0)) \
> + CASE_##op((val), TRCIMSPECn(1)) \
> + CASE_##op((val), TRCIMSPECn(2)) \
> + CASE_##op((val), TRCIMSPECn(3)) \
> + CASE_##op((val), TRCIMSPECn(4)) \
> + CASE_##op((val), TRCIMSPECn(5)) \
> + CASE_##op((val), TRCIMSPECn(6)) \
> + CASE_##op((val), TRCIMSPECn(7)) \
> + CASE_##op((val), TRCIDR0) \
> + CASE_##op((val), TRCIDR1) \
> + CASE_##op((val), TRCIDR2) \
> + CASE_##op((val), TRCIDR3) \
> + CASE_##op((val), TRCIDR4) \
> + CASE_##op((val), TRCIDR5) \
> + CASE_##op((val), TRCIDR6) \
> + CASE_##op((val), TRCIDR7) \
> + CASE_##op((val), TRCRSCTLRn(2)) \
> + CASE_##op((val), TRCRSCTLRn(3)) \
> + CASE_##op((val), TRCRSCTLRn(4)) \
> + CASE_##op((val), TRCRSCTLRn(5)) \
> + CASE_##op((val), TRCRSCTLRn(6)) \
> + CASE_##op((val), TRCRSCTLRn(7)) \
> + CASE_##op((val), TRCRSCTLRn(8)) \
> + CASE_##op((val), TRCRSCTLRn(9)) \
> + CASE_##op((val), TRCRSCTLRn(10)) \
> + CASE_##op((val), TRCRSCTLRn(11)) \
> + CASE_##op((val), TRCRSCTLRn(12)) \
> + CASE_##op((val), TRCRSCTLRn(13)) \
> + CASE_##op((val), TRCRSCTLRn(14)) \
> + CASE_##op((val), TRCRSCTLRn(15)) \
> + CASE_##op((val), TRCRSCTLRn(16)) \
> + CASE_##op((val), TRCRSCTLRn(17)) \
> + CASE_##op((val), TRCRSCTLRn(18)) \
> + CASE_##op((val), TRCRSCTLRn(19)) \
> + CASE_##op((val), TRCRSCTLRn(20)) \
> + CASE_##op((val), TRCRSCTLRn(21)) \
> + CASE_##op((val), TRCRSCTLRn(22)) \
> + CASE_##op((val), TRCRSCTLRn(23)) \
> + CASE_##op((val), TRCRSCTLRn(24)) \
> + CASE_##op((val), TRCRSCTLRn(25)) \
> + CASE_##op((val), TRCRSCTLRn(26)) \
> + CASE_##op((val), TRCRSCTLRn(27)) \
> + CASE_##op((val), TRCRSCTLRn(28)) \
> + CASE_##op((val), TRCRSCTLRn(29)) \
> + CASE_##op((val), TRCRSCTLRn(30)) \
> + CASE_##op((val), TRCRSCTLRn(31)) \
> + CASE_##op((val), TRCSSCCRn(0)) \
> + CASE_##op((val), TRCSSCCRn(1)) \
> + CASE_##op((val), TRCSSCCRn(2)) \
> + CASE_##op((val), TRCSSCCRn(3)) \
> + CASE_##op((val), TRCSSCCRn(4)) \
> + CASE_##op((val), TRCSSCCRn(5)) \
> + CASE_##op((val), TRCSSCCRn(6)) \
> + CASE_##op((val), TRCSSCCRn(7)) \
> + CASE_##op((val), TRCSSCSRn(0)) \
> + CASE_##op((val), TRCSSCSRn(1)) \
> + CASE_##op((val), TRCSSCSRn(2)) \
> + CASE_##op((val), TRCSSCSRn(3)) \
> + CASE_##op((val), TRCSSCSRn(4)) \
> + CASE_##op((val), TRCSSCSRn(5)) \
> + CASE_##op((val), TRCSSCSRn(6)) \
> + CASE_##op((val), TRCSSCSRn(7)) \
> + CASE_##op((val), TRCSSPCICRn(0)) \
> + CASE_##op((val), TRCSSPCICRn(1)) \
> + CASE_##op((val), TRCSSPCICRn(2)) \
> + CASE_##op((val), TRCSSPCICRn(3)) \
> + CASE_##op((val), TRCSSPCICRn(4)) \
> + CASE_##op((val), TRCSSPCICRn(5)) \
> + CASE_##op((val), TRCSSPCICRn(6)) \
> + CASE_##op((val), TRCSSPCICRn(7)) \
> + CASE_##op((val), TRCOSLAR) \
> + CASE_##op((val), TRCOSLSR) \
> + CASE_##op((val), TRCPDCR) \
> + CASE_##op((val), TRCPDSR) \
> + CASE_##op((val), TRCACVRn(0)) \
> + CASE_##op((val), TRCACVRn(1)) \
> + CASE_##op((val), TRCACVRn(2)) \
> + CASE_##op((val), TRCACVRn(3)) \
> + CASE_##op((val), TRCACVRn(4)) \
> + CASE_##op((val), TRCACVRn(5)) \
> + CASE_##op((val), TRCACVRn(6)) \
> + CASE_##op((val), TRCACVRn(7)) \
> + CASE_##op((val), TRCACVRn(8)) \
> + CASE_##op((val), TRCACVRn(9)) \
> + CASE_##op((val), TRCACVRn(10)) \
> + CASE_##op((val), TRCACVRn(11)) \
> + CASE_##op((val), TRCACVRn(12)) \
> + CASE_##op((val), TRCACVRn(13)) \
> + CASE_##op((val), TRCACVRn(14)) \
> + CASE_##op((val), TRCACVRn(15)) \
> + CASE_##op((val), TRCACATRn(0)) \
> + CASE_##op((val), TRCACATRn(1)) \
> + CASE_##op((val), TRCACATRn(2)) \
> + CASE_##op((val), TRCACATRn(3)) \
> + CASE_##op((val), TRCACATRn(4)) \
> + CASE_##op((val), TRCACATRn(5)) \
> + CASE_##op((val), TRCACATRn(6)) \
> + CASE_##op((val), TRCACATRn(7)) \
> + CASE_##op((val), TRCACATRn(8)) \
> + CASE_##op((val), TRCACATRn(9)) \
> + CASE_##op((val), TRCACATRn(10)) \
> + CASE_##op((val), TRCACATRn(11)) \
> + CASE_##op((val), TRCACATRn(12)) \
> + CASE_##op((val), TRCACATRn(13)) \
> + CASE_##op((val), TRCACATRn(14)) \
> + CASE_##op((val), TRCACATRn(15)) \
> + CASE_##op((val), TRCDVCVRn(0)) \
> + CASE_##op((val), TRCDVCVRn(1)) \
> + CASE_##op((val), TRCDVCVRn(2)) \
> + CASE_##op((val), TRCDVCVRn(3)) \
> + CASE_##op((val), TRCDVCVRn(4)) \
> + CASE_##op((val), TRCDVCVRn(5)) \
> + CASE_##op((val), TRCDVCVRn(6)) \
> + CASE_##op((val), TRCDVCVRn(7)) \
> + CASE_##op((val), TRCDVCMRn(0)) \
> + CASE_##op((val), TRCDVCMRn(1)) \
> + CASE_##op((val), TRCDVCMRn(2)) \
> + CASE_##op((val), TRCDVCMRn(3)) \
> + CASE_##op((val), TRCDVCMRn(4)) \
> + CASE_##op((val), TRCDVCMRn(5)) \
> + CASE_##op((val), TRCDVCMRn(6)) \
> + CASE_##op((val), TRCDVCMRn(7)) \
> + CASE_##op((val), TRCCIDCVRn(0)) \
> + CASE_##op((val), TRCCIDCVRn(1)) \
> + CASE_##op((val), TRCCIDCVRn(2)) \
> + CASE_##op((val), TRCCIDCVRn(3)) \
> + CASE_##op((val), TRCCIDCVRn(4)) \
> + CASE_##op((val), TRCCIDCVRn(5)) \
> + CASE_##op((val), TRCCIDCVRn(6)) \
> + CASE_##op((val), TRCCIDCVRn(7)) \
> + CASE_##op((val), TRCVMIDCVRn(0)) \
> + CASE_##op((val), TRCVMIDCVRn(1)) \
> + CASE_##op((val), TRCVMIDCVRn(2)) \
> + CASE_##op((val), TRCVMIDCVRn(3)) \
> + CASE_##op((val), TRCVMIDCVRn(4)) \
> + CASE_##op((val), TRCVMIDCVRn(5)) \
> + CASE_##op((val), TRCVMIDCVRn(6)) \
> + CASE_##op((val), TRCVMIDCVRn(7)) \
> + CASE_##op((val), TRCCIDCCTLR0) \
> + CASE_##op((val), TRCCIDCCTLR1) \
> + CASE_##op((val), TRCVMIDCCTLR0) \
> + CASE_##op((val), TRCVMIDCCTLR1) \
> + CASE_##op((val), TRCITCTRL) \
> + CASE_##op((val), TRCCLAIMSET) \
> + CASE_##op((val), TRCCLAIMCLR) \
> + CASE_##op((val), TRCDEVAFF0) \
> + CASE_##op((val), TRCDEVAFF1) \
> + CASE_##op((val), TRCLAR) \
> + CASE_##op((val), TRCLSR) \
> + CASE_##op((val), TRCAUTHSTATUS) \
> + CASE_##op((val), TRCDEVARCH) \
> + CASE_##op((val), TRCDEVID) \
> + CASE_##op((val), TRCDEVTYPE) \
> + CASE_##op((val), TRCPIDR4) \
> + CASE_##op((val), TRCPIDR5) \
> + CASE_##op((val), TRCPIDR6) \
> + CASE_##op((val), TRCPIDR7) \
> + CASE_##op((val), TRCPIDR0) \
> + CASE_##op((val), TRCPIDR1) \
> + CASE_##op((val), TRCPIDR2) \
> + CASE_##op((val), TRCPIDR3)
> +
> +#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res))
> +#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val))
> +

2020-10-29 15:47:32

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 00/26] coresight: Support for ETM system instructions

On 10/29/20 7:53 AM, Mike Leach wrote:
> Hi Suzuki,
>
> On Wed, 28 Oct 2020 at 22:10, Suzuki K Poulose <[email protected]> wrote:
>>
>> CoreSight ETMv4.4 obsoletes memory mapped access to ETM and
>> mandates the system instructions for registers.
>> This also implies that they may not be on the amba bus.
>> Right now all the CoreSight components are accessed via memory
>> map. Also, we have some common routines in coresight generic
>> code driver (e.g, CS_LOCK, claim/disclaim), which assume the
>> mmio. In order to preserve the generic algorithms at a single
>> place and to allow dynamic switch for ETMs, this series introduces
>> an abstraction layer for accessing a coresight device. It is
>> designed such that the mmio access are fast tracked (i.e, without
>> an indirect function call).
>>
>> This will also help us to get rid of the driver+attribute specific
>> sysfs show/store routines and replace them with a single routine
>> to access a given register offset (which can be embedded in the
>> dev_ext_attribute). This is not currently implemented in the series,
>> but can be achieved.
>>
>> Further we switch the generic routines to work with the abstraction.
>> With this in place, we refactor the etm4x code a bit to allow for
>> supporting the system instructions with very little new code. The
>> changes also switch to using the system instructions by default
>> even when we may have an MMIO.
>>
>> We use TRCDEVARCH for the detection of the ETM component, which
>> is a standard register as per CoreSight architecture, rather than
>> the etm specific id register TRCIDR1. This is for making sure
>> that we are able to detect the ETM via system instructions accurately,
>> when the the trace unit could be anything (etm or a custom trace unit).
>> To keep the backward compatibility for any existing broken impelementation
>> which may not implement TRCDEVARCH, we fall back to TRCIDR1. Also
>> this covers us for the changes in the future architecture [0].
>>
>> The series has been mildly tested on a model for system instructions.
>> I would really appreciate any testing on real hardware.
>>
>> Applies on coresight/next.
>>
>> [0] https://developer.arm.com/docs/ddi0601/g/aarch64-system-registers/trcidr1
>>
>> Known issues:
>> Checkpatch failure for "coresight: etm4x: Add sysreg access helpers" :
>>
>> ERROR: Macros with complex values should be enclosed in parentheses
>> #121: FILE: drivers/hwtracing/coresight/coresight-etm4x.h:153:
>> +#define CASE_READ(res, x) \
>> + case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
>>
>>
>> I don't know how to fix that without breaking the build ! Suggestions
>> welcome.
>>
>
> I hit exactly the same issue with my recent v2 set. The checker really
> hates case statements in macros. In my case I shut it up for v3 by
> changing:-
>
> #define MAPREG(cval, elem) \
> case cval: \
> reg->drv_store = &drvcfg->elem; \
> break;
>
>
> if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
> ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
> ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
> switch (offset) {
> /* 32 bit single control and filter registers */
> MAPREG(TRCEVENTCTL0R, eventctrl0);
> MAPREG(TRCEVENTCTL1R, eventctrl1);
> MAPREG(TRCSTALLCTLR, stall_ctrl);
> MAPREG(TRCTSCTLR, ts_ctrl);
> MAPREG(TRCSYNCPR, syncfreq);
> MAPREG(TRCCCCTLR, ccctlr);
> MAPREG(TRCBBCTLR, bb_ctrl);
> MAPREG(TRCVICTLR, vinst_ctrl);
> MAPREG(TRCVIIECTLR, viiectlr);
> MAPREG(TRCVISSCTLR, vissctlr);
> MAPREG(TRCVIPCSSCTLR, vipcssctlr);
> MAPREG(TRCSEQRSTEVR, seq_rst);
> MAPREG(TRCSEQSTR, seq_state);
> MAPREG(TRCEXTINSELR, ext_inp);
> MAPREG(TRCCIDCCTLR0, ctxid_mask0);
> MAPREG(TRCCIDCCTLR1, ctxid_mask1);
> MAPREG(TRCVMIDCCTLR0, vmid_mask0);
> MAPREG(TRCVMIDCCTLR1, vmid_mask1);
> default:
> err = -EINVAL;
> break;
> }
>
>
> to
>
> err = -EINVAL;
>
> #define CHECKREG(cval, elem) \
> { \
> if (offset == cval) { \
> reg->drv_store = &drvcfg->elem; \
> err = 0; \
> break; \
> } \
> }
>
> if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
> ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
> ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
> do {
> CHECKREG(TRCEVENTCTL0R, eventctrl0);
> CHECKREG(TRCEVENTCTL1R, eventctrl1);
> CHECKREG(TRCSTALLCTLR, stall_ctrl);
> CHECKREG(TRCTSCTLR, ts_ctrl);
> CHECKREG(TRCSYNCPR, syncfreq);
> CHECKREG(TRCCCCTLR, ccctlr);
> CHECKREG(TRCBBCTLR, bb_ctrl);
> CHECKREG(TRCVICTLR, vinst_ctrl);
> CHECKREG(TRCVIIECTLR, viiectlr);
> CHECKREG(TRCVISSCTLR, vissctlr);
> CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
> CHECKREG(TRCSEQRSTEVR, seq_rst);
> CHECKREG(TRCSEQSTR, seq_state);
> CHECKREG(TRCEXTINSELR, ext_inp);
> CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
> CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
> CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
> CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
> } while (0);
>
>
> A bit contrived but functionally the same - and doesn't annoy the
> checker, No idea if the code is more or less efficient after
> compilation than a standard switch / case combo, but not on a critical
> path for me so wasn't bothered.

Thanks Mike. Functionally it is fine. But I think the Compiler wil be
able to optimize it better with switch() for a large list of cases
with consecutive values.

I guess there are more and more places that this is useful.
I have Cc'ed the checkpatch maintainers in the patch in question.

Cheers
Suzuki

2020-11-02 15:33:15

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v3 26/26] dts: bindings: coresight: ETM system register access only units

On Wed, 28 Oct 2020 22:09:45 +0000, Suzuki K Poulose wrote:
> Document the bindings for ETMs with system register accesses.
>
> Cc: [email protected]
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Cc: Rob Herring <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> Documentation/devicetree/bindings/arm/coresight.txt | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>

Acked-by: Rob Herring <[email protected]>

2020-11-02 21:50:41

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 06/26] coresight: etm4x: Handle access to TRCSSPCICRn

Hi Suzuki,

On Wed, Oct 28, 2020 at 10:09:25PM +0000, Suzuki K Poulose wrote:
> TRCSSPCICR<n> is present only if all of the following are true:
> TRCIDR4.NUMSSCC > n.
> TRCIDR4.NUMPC > 0b0000 .
> TRCSSCSR<n>.PC == 0b1
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index d78a37b6592c..0310eac9dc16 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -175,8 +175,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> drvdata->base + TRCSSCCRn(i));
> writel_relaxed(config->ss_status[i],
> drvdata->base + TRCSSCSRn(i));
> - writel_relaxed(config->ss_pe_cmp[i],
> - drvdata->base + TRCSSPCICRn(i));
> + if (drvdata->nr_pe)

Aren't you missing to check the value of the PC bit in TRCSSCSRn?

/*
* TRCSSCSRn:PC, bit[3]: Indidate support for single-shot PE
* comparator input.
*/
if (drvdata->nr_pe && (config->ss_status[i] & BIT(3)))


I have picked up patches 1 to 5 and added a "Cc:stable" to paches 2, 4 and 5.
More comments to come tomorrow.


Thanks,
Mathieu

> + writel_relaxed(config->ss_pe_cmp[i],
> + drvdata->base + TRCSSPCICRn(i));
> }
> for (i = 0; i < drvdata->nr_addr_cmp; i++) {
> writeq_relaxed(config->addr_val[i],
> @@ -1228,7 +1229,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i));
> state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i));
> - state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
> + if (drvdata->nr_pe)
> + state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
> }
>
> for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> @@ -1344,8 +1346,9 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
> drvdata->base + TRCSSCCRn(i));
> writel_relaxed(state->trcsscsr[i],
> drvdata->base + TRCSSCSRn(i));
> - writel_relaxed(state->trcsspcicr[i],
> - drvdata->base + TRCSSPCICRn(i));
> + if (drvdata->nr_pe)
> + writel_relaxed(state->trcsspcicr[i],
> + drvdata->base + TRCSSPCICRn(i));
> }
>
> for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> --
> 2.24.1
>

2020-11-02 22:08:48

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 06/26] coresight: etm4x: Handle access to TRCSSPCICRn

On 11/2/20 9:46 PM, Mathieu Poirier wrote:
> Hi Suzuki,
>
> On Wed, Oct 28, 2020 at 10:09:25PM +0000, Suzuki K Poulose wrote:
>> TRCSSPCICR<n> is present only if all of the following are true:
>> TRCIDR4.NUMSSCC > n.
>> TRCIDR4.NUMPC > 0b0000 .
>> TRCSSCSR<n>.PC == 0b1
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 ++++++++-----
>> 1 file changed, 8 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index d78a37b6592c..0310eac9dc16 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -175,8 +175,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>> drvdata->base + TRCSSCCRn(i));
>> writel_relaxed(config->ss_status[i],
>> drvdata->base + TRCSSCSRn(i));
>> - writel_relaxed(config->ss_pe_cmp[i],
>> - drvdata->base + TRCSSPCICRn(i));
>> + if (drvdata->nr_pe)
>
> Aren't you missing to check the value of the PC bit in TRCSSCSRn?
>
> /*
> * TRCSSCSRn:PC, bit[3]: Indidate support for single-shot PE
> * comparator input.
> */
> if (drvdata->nr_pe && (config->ss_status[i] & BIT(3)))
>
>

You're right. Thank for catching this. I will update the series and drop
the patches 1-5.


> I have picked up patches 1 to 5 and added a "Cc:stable" to paches 2, 4 and 5.
> More comments to come tomorrow.

Thanks !
Suzuki

2020-11-03 18:05:44

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 08/26] coresight: tpiu: Prepare for using coresight device access abstraction

On Wed, Oct 28, 2020 at 10:09:27PM +0000, Suzuki K Poulose wrote:
> Prepare the TPIU driver to make use of the CoreSight device access
> abstraction layer. The driver touches the device even before the
> coresight device is registered. Thus we could be accessing the
> devices without a csdev. As we are about to use the abstraction
> layer for accessing the device, pass in the access directly
> to avoid having to deal with the un-initialised csdev.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-tpiu.c | 30 +++++++++-----------
> 1 file changed, 13 insertions(+), 17 deletions(-)

Reviewed-by: Mathieu Poirier <[email protected]>

>
> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
> index dfa3b91d0281..98c4a029854c 100644
> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
> @@ -60,49 +60,45 @@ struct tpiu_drvdata {
> struct coresight_device *csdev;
> };
>
> -static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
> +static void tpiu_enable_hw(struct csdev_access *csa)
> {
> - CS_UNLOCK(drvdata->base);
> + CS_UNLOCK(csa->base);
>
> /* TODO: fill this up */
>
> - CS_LOCK(drvdata->base);
> + CS_LOCK(csa->base);
> }
>
> static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
> {
> - struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> -
> - tpiu_enable_hw(drvdata);
> + tpiu_enable_hw(&csdev->access);
> atomic_inc(csdev->refcnt);
> dev_dbg(&csdev->dev, "TPIU enabled\n");
> return 0;
> }
>
> -static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
> +static void tpiu_disable_hw(struct csdev_access *csa)
> {
> - CS_UNLOCK(drvdata->base);
> + CS_UNLOCK(csa->base);
>
> /* Clear formatter and stop on flush */
> - writel_relaxed(FFCR_STOP_FI, drvdata->base + TPIU_FFCR);
> + csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR);
> /* Generate manual flush */
> - writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
> + csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR);
> /* Wait for flush to complete */
> - coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
> + coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
> /* Wait for formatter to stop */
> - coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
> + coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
>
> - CS_LOCK(drvdata->base);
> + CS_LOCK(csa->base);
> }
>
> static int tpiu_disable(struct coresight_device *csdev)
> {
> - struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> -
> if (atomic_dec_return(csdev->refcnt))
> return -EBUSY;
>
> - tpiu_disable_hw(drvdata);
> + tpiu_disable_hw(&csdev->access);
>
> dev_dbg(&csdev->dev, "TPIU disabled\n");
> return 0;
> @@ -152,7 +148,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
> desc.access = CSDEV_ACCESS_IOMEM(base);
>
> /* Disable tpiu to support older devices */
> - tpiu_disable_hw(drvdata);
> + tpiu_disable_hw(&desc.access);
>
> pdata = coresight_get_platform_data(dev);
> if (IS_ERR(pdata))
> --
> 2.24.1
>

2020-11-03 18:07:51

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 09/26] coresight: Convert coresight_timeout to use access abstraction

On Wed, Oct 28, 2020 at 10:09:28PM +0000, Suzuki K Poulose wrote:
> Convert the generic routines to use the new access abstraction layer
> gradually, starting with coresigth_timeout.
>
> Cc: Mike Leach <[email protected]>
> Reviewed-by: Mathieu Poirier <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-catu.c | 5 ++--
> drivers/hwtracing/coresight/coresight-core.c | 15 ++++++----
> drivers/hwtracing/coresight/coresight-etb10.c | 5 ++--
> .../coresight/coresight-etm4x-core.c | 30 ++++++++++++-------
> drivers/hwtracing/coresight/coresight-stm.c | 3 +-
> .../hwtracing/coresight/coresight-tmc-core.c | 15 ++++++----
> drivers/hwtracing/coresight/coresight-tpiu.c | 4 +--
> include/linux/coresight.h | 17 ++++++++---
> 8 files changed, 61 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index 5baf29510f1b..34c74b05c542 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {
>
> static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
> {
> - return coresight_timeout(drvdata->base,
> - CATU_STATUS, CATU_STATUS_READY, 1);
> + struct csdev_access *csa = &drvdata->csdev->access;
> +
> + return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
> }
>
> static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index e96deaca8cab..42ba989a6b5e 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -1412,23 +1412,26 @@ static void coresight_remove_conns(struct coresight_device *csdev)
> }
>
> /**
> - * coresight_timeout - loop until a bit has changed to a specific state.
> - * @addr: base address of the area of interest.
> - * @offset: address of a register, starting from @addr.
> + * coresight_timeout - loop until a bit has changed to a specific register
> + * state.
> + * @csa: coresight device access for the device
> + * @offset: Offset of the register from the base of the device.
> * @position: the position of the bit of interest.
> * @value: the value the bit should have.
> *
> * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
> * TIMEOUT_US has elapsed, which ever happens first.
> */
> -
> -int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
> +int coresight_timeout(struct csdev_access *csa,
> + u32 offset,
> + int position,
> + int value)

There is no need for stacking, please maximise the 80 characters. The function
stubs in coresight.h should also be revised.

> {
> int i;
> u32 val;
>
> for (i = TIMEOUT_US; i > 0; i--) {
> - val = __raw_readl(addr + offset);
> + val = csdev_access_read32(csa, offset);

I vaguely remember commenting on this, or perhaps it was on some othe patch you
wrote... Anyways, I think it is a good thing to go from an unordered access to
an ordered access for the timeout function.

With the above:

Reviewed-by: Mathieu Poirier <[email protected]>

> /* waiting on the bit to go from 0 to 1 */
> if (value) {
> if (val & BIT(position))
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index b91633c6c9b4..f994a22876d9 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -251,6 +251,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
> {
> u32 ffcr;
> struct device *dev = &drvdata->csdev->dev;
> + struct csdev_access *csa = &drvdata->csdev->access;
>
> CS_UNLOCK(drvdata->base);
>
> @@ -262,7 +263,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
> ffcr |= ETB_FFCR_FON_MAN;
> writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
>
> - if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
> + if (coresight_timeout(csa, ETB_FFCR, ETB_FFCR_BIT, 0)) {
> dev_err(dev,
> "timeout while waiting for completion of Manual Flush\n");
> }
> @@ -270,7 +271,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
> /* disable trace capture */
> writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
>
> - if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
> + if (coresight_timeout(csa, ETB_FFSR, ETB_FFSR_BIT, 1)) {
> dev_err(dev,
> "timeout while waiting for Formatter to Stop\n");
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index c5cb93f1b80c..2744aadaa5ec 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -107,7 +107,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> {
> int i, rc;
> struct etmv4_config *config = &drvdata->config;
> - struct device *etm_dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
> + struct device *etm_dev = &csdev->dev;
> + struct csdev_access *csa = &csdev->access;
>
> CS_UNLOCK(drvdata->base);
>
> @@ -121,7 +123,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> writel_relaxed(0, drvdata->base + TRCPRGCTLR);
>
> /* wait for TRCSTATR.IDLE to go up */
> - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
> + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
> dev_err(etm_dev,
> "timeout while waiting for Idle Trace Status\n");
> if (drvdata->nr_pe)
> @@ -212,7 +214,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> writel_relaxed(1, drvdata->base + TRCPRGCTLR);
>
> /* wait for TRCSTATR.IDLE to go back down to '0' */
> - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
> + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
> dev_err(etm_dev,
> "timeout while waiting for Idle Trace Status\n");
>
> @@ -476,7 +478,9 @@ static void etm4_disable_hw(void *info)
> u32 control;
> struct etmv4_drvdata *drvdata = info;
> struct etmv4_config *config = &drvdata->config;
> - struct device *etm_dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
> + struct device *etm_dev = &csdev->dev;
> + struct csdev_access *csa = &csdev->access;
> int i;
>
> CS_UNLOCK(drvdata->base);
> @@ -503,8 +507,7 @@ static void etm4_disable_hw(void *info)
> writel_relaxed(control, drvdata->base + TRCPRGCTLR);
>
> /* wait for TRCSTATR.PMSTABLE to go to '1' */
> - if (coresight_timeout(drvdata->base, TRCSTATR,
> - TRCSTATR_PMSTABLE_BIT, 1))
> + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
> dev_err(etm_dev,
> "timeout while waiting for PM stable Trace Status\n");
>
> @@ -1160,7 +1163,15 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> {
> int i, ret = 0;
> struct etmv4_save_state *state;
> - struct device *etm_dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
> + struct csdev_access *csa;
> + struct device *etm_dev;
> +
> + if (WARN_ON(!csdev))
> + return -ENODEV;
> +
> + etm_dev = &csdev->dev;
> + csa = &csdev->access;
>
> /*
> * As recommended by 3.4.1 ("The procedure when powering down the PE")
> @@ -1175,8 +1186,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> etm4_os_lock(drvdata);
>
> /* wait for TRCSTATR.PMSTABLE to go up */
> - if (coresight_timeout(drvdata->base, TRCSTATR,
> - TRCSTATR_PMSTABLE_BIT, 1)) {
> + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) {
> dev_err(etm_dev,
> "timeout while waiting for PM Stable Status\n");
> etm4_os_unlock(drvdata);
> @@ -1264,7 +1274,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> state->trcpdcr = readl(drvdata->base + TRCPDCR);
>
> /* wait for TRCSTATR.IDLE to go up */
> - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
> + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
> dev_err(etm_dev,
> "timeout while waiting for Idle Trace Status\n");
> etm4_os_unlock(drvdata);
> diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
> index 315500b7763f..9cba67b27586 100644
> --- a/drivers/hwtracing/coresight/coresight-stm.c
> +++ b/drivers/hwtracing/coresight/coresight-stm.c
> @@ -258,6 +258,7 @@ static void stm_disable(struct coresight_device *csdev,
> struct perf_event *event)
> {
> struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> + struct csdev_access *csa = &csdev->access;
>
> /*
> * For as long as the tracer isn't disabled another entity can't
> @@ -270,7 +271,7 @@ static void stm_disable(struct coresight_device *csdev,
> spin_unlock(&drvdata->spinlock);
>
> /* Wait until the engine has completely stopped */
> - coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0);
> + coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0);
>
> pm_runtime_put(csdev->dev.parent);
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
> index 8fd640d41e1b..572f4b316798 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-core.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
> @@ -33,16 +33,20 @@ DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
>
> void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
> {
> + struct coresight_device *csdev = drvdata->csdev;
> + struct csdev_access *csa = &csdev->access;
> +
> /* Ensure formatter, unformatter and hardware fifo are empty */
> - if (coresight_timeout(drvdata->base,
> - TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
> - dev_err(&drvdata->csdev->dev,
> + if (coresight_timeout(csa, TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
> + dev_err(&csdev->dev,
> "timeout while waiting for TMC to be Ready\n");
> }
> }
>
> void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
> {
> + struct coresight_device *csdev = drvdata->csdev;
> + struct csdev_access *csa = &csdev->access;
> u32 ffcr;
>
> ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
> @@ -51,9 +55,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
> ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
> writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
> /* Ensure flush completes */
> - if (coresight_timeout(drvdata->base,
> - TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
> - dev_err(&drvdata->csdev->dev,
> + if (coresight_timeout(csa, TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
> + dev_err(&csdev->dev,
> "timeout while waiting for completion of Manual Flush\n");
> }
>
> diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
> index 98c4a029854c..1e92c76d9656 100644
> --- a/drivers/hwtracing/coresight/coresight-tpiu.c
> +++ b/drivers/hwtracing/coresight/coresight-tpiu.c
> @@ -86,9 +86,9 @@ static void tpiu_disable_hw(struct csdev_access *csa)
> /* Generate manual flush */
> csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR);
> /* Wait for flush to complete */
> - coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
> + coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
> /* Wait for formatter to stop */
> - coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
> + coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
>
> CS_LOCK(csa->base);
> }
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 5a34c2f2debc..cefc8fe239e6 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -469,8 +469,10 @@ coresight_register(struct coresight_desc *desc);
> extern void coresight_unregister(struct coresight_device *csdev);
> extern int coresight_enable(struct coresight_device *csdev);
> extern void coresight_disable(struct coresight_device *csdev);
> -extern int coresight_timeout(void __iomem *addr, u32 offset,
> - int position, int value);
> +extern int coresight_timeout(struct csdev_access *csa,
> + u32 offset,
> + int position,
> + int value);
>
> extern int coresight_claim_device(void __iomem *base);
> extern int coresight_claim_device_unlocked(void __iomem *base);
> @@ -502,8 +504,15 @@ static inline void coresight_unregister(struct coresight_device *csdev) {}
> static inline int
> coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
> static inline void coresight_disable(struct coresight_device *csdev) {}
> -static inline int coresight_timeout(void __iomem *addr, u32 offset,
> - int position, int value) { return 1; }
> +
> +static inline int coresight_timeout(struct csdev_access *csa,
> + u32 offset,
> + int position,
> + int value)
> +{
> + return 1;
> +}
> +
> static inline int coresight_claim_device_unlocked(void __iomem *base)
> {
> return -EINVAL;
> --
> 2.24.1
>

2020-11-03 18:40:51

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 10/26] coresight: Convert claim/disclaim operations to use access wrappers

On Wed, Oct 28, 2020 at 10:09:29PM +0000, Suzuki K Poulose wrote:
> Convert the generic CLAIM tag management APIs to use the
> device access layer abstraction.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-catu.c | 6 +-
> drivers/hwtracing/coresight/coresight-core.c | 66 +++++++++++--------
> .../hwtracing/coresight/coresight-cti-core.c | 17 +++--
> drivers/hwtracing/coresight/coresight-etb10.c | 4 +-
> .../coresight/coresight-etm3x-core.c | 8 ++-
> .../coresight/coresight-etm4x-core.c | 4 +-
> .../hwtracing/coresight/coresight-funnel.c | 6 +-
> .../coresight/coresight-replicator.c | 16 +++--
> .../hwtracing/coresight/coresight-tmc-etf.c | 10 +--
> .../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
> include/linux/coresight.h | 16 ++---
> 11 files changed, 95 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
> index 34c74b05c542..438063523463 100644
> --- a/drivers/hwtracing/coresight/coresight-catu.c
> +++ b/drivers/hwtracing/coresight/coresight-catu.c
> @@ -412,6 +412,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
> u32 control, mode;
> struct etr_buf *etr_buf = data;
> struct device *dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
>
> if (catu_wait_for_ready(drvdata))
> dev_warn(dev, "Timeout while waiting for READY\n");
> @@ -422,7 +423,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
> return -EBUSY;
> }
>
> - rc = coresight_claim_device_unlocked(drvdata->base);
> + rc = coresight_claim_device_unlocked(csdev);
> if (rc)
> return rc;
>
> @@ -466,9 +467,10 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
> {
> int rc = 0;
> struct device *dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
>
> catu_write_control(drvdata, 0);
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
> if (catu_wait_for_ready(drvdata)) {
> dev_info(dev, "Timeout while waiting for READY\n");
> rc = -EAGAIN;
> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
> index 42ba989a6b5e..4e7dd5941046 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -145,30 +145,32 @@ static int coresight_find_link_outport(struct coresight_device *csdev,
> return -ENODEV;
> }
>
> -static inline u32 coresight_read_claim_tags(void __iomem *base)
> +static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
> {
> - return readl_relaxed(base + CORESIGHT_CLAIMCLR);
> + return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
> }
>
> -static inline bool coresight_is_claimed_self_hosted(void __iomem *base)
> +static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
> {
> - return coresight_read_claim_tags(base) == CORESIGHT_CLAIM_SELF_HOSTED;
> + return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
> }
>
> -static inline bool coresight_is_claimed_any(void __iomem *base)
> +static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
> {
> - return coresight_read_claim_tags(base) != 0;
> + return coresight_read_claim_tags(csdev) != 0;
> }
>
> -static inline void coresight_set_claim_tags(void __iomem *base)
> +static inline void coresight_set_claim_tags(struct coresight_device *csdev)
> {
> - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET);
> + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> + CORESIGHT_CLAIMSET);

Indentation

> isb();
> }
>
> -static inline void coresight_clear_claim_tags(void __iomem *base)
> +static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
> {
> - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR);
> + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
> + CORESIGHT_CLAIMCLR);

Indentation

> isb();
> }
>
> @@ -182,27 +184,33 @@ static inline void coresight_clear_claim_tags(void __iomem *base)
> * Called with CS_UNLOCKed for the component.
> * Returns : 0 on success
> */
> -int coresight_claim_device_unlocked(void __iomem *base)
> +int coresight_claim_device_unlocked(struct coresight_device *csdev)
> {
> - if (coresight_is_claimed_any(base))
> + if (WARN_ON(!csdev))
> + return -EINVAL;
> +
> + if (coresight_is_claimed_any(csdev))
> return -EBUSY;
>
> - coresight_set_claim_tags(base);
> - if (coresight_is_claimed_self_hosted(base))
> + coresight_set_claim_tags(csdev);
> + if (coresight_is_claimed_self_hosted(csdev))
> return 0;
> /* There was a race setting the tags, clean up and fail */
> - coresight_clear_claim_tags(base);
> + coresight_clear_claim_tags(csdev);
> return -EBUSY;
> }
> EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
>
> -int coresight_claim_device(void __iomem *base)
> +int coresight_claim_device(struct coresight_device *csdev)
> {
> int rc;
>
> - CS_UNLOCK(base);
> - rc = coresight_claim_device_unlocked(base);
> - CS_LOCK(base);
> + if (WARN_ON(!csdev))
> + return -EINVAL;
> +
> + CS_UNLOCK(csdev->access.base);
> + rc = coresight_claim_device_unlocked(csdev);
> + CS_LOCK(csdev->access.base);
>
> return rc;
> }
> @@ -212,11 +220,14 @@ EXPORT_SYMBOL_GPL(coresight_claim_device);
> * coresight_disclaim_device_unlocked : Clear the claim tags for the device.
> * Called with CS_UNLOCKed for the component.
> */
> -void coresight_disclaim_device_unlocked(void __iomem *base)
> +void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
> {
>
> - if (coresight_is_claimed_self_hosted(base))
> - coresight_clear_claim_tags(base);
> + if (WARN_ON(!csdev))
> + return;
> +
> + if (coresight_is_claimed_self_hosted(csdev))
> + coresight_clear_claim_tags(csdev);
> else
> /*
> * The external agent may have not honoured our claim
> @@ -227,11 +238,14 @@ void coresight_disclaim_device_unlocked(void __iomem *base)
> }
> EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
>
> -void coresight_disclaim_device(void __iomem *base)
> +void coresight_disclaim_device(struct coresight_device *csdev)
> {
> - CS_UNLOCK(base);
> - coresight_disclaim_device_unlocked(base);
> - CS_LOCK(base);
> + if (WARN_ON(!csdev))
> + return;
> +
> + CS_UNLOCK(csdev->access.base);
> + coresight_disclaim_device_unlocked(csdev);
> + CS_LOCK(csdev->access.base);
> }
> EXPORT_SYMBOL_GPL(coresight_disclaim_device);
>
> diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
> index 3bb0de97d66e..5651d7f61a70 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-core.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-core.c
> @@ -102,7 +102,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
> goto cti_state_unchanged;
>
> /* claim the device */
> - rc = coresight_claim_device(drvdata->base);
> + rc = coresight_claim_device(drvdata->csdev);
> if (rc)
> goto cti_err_not_enabled;
>
> @@ -136,7 +136,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
> goto cti_hp_not_enabled;
>
> /* try to claim the device */
> - if (coresight_claim_device(drvdata->base))
> + if (coresight_claim_device(drvdata->csdev))
> goto cti_hp_not_enabled;
>
> cti_write_all_hw_regs(drvdata);
> @@ -154,6 +154,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
> {
> struct cti_config *config = &drvdata->config;
> struct device *dev = &drvdata->csdev->dev;
> + struct coresight_device *csdev = drvdata->csdev;
>
> spin_lock(&drvdata->spinlock);
>
> @@ -171,7 +172,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
> writel_relaxed(0, drvdata->base + CTICONTROL);
> config->hw_enabled = false;
>
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
> CS_LOCK(drvdata->base);
> spin_unlock(&drvdata->spinlock);
> pm_runtime_put(dev);
> @@ -655,6 +656,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> void *v)
> {
> struct cti_drvdata *drvdata;
> + struct coresight_device *csdev;
> unsigned int cpu = smp_processor_id();
> int notify_res = NOTIFY_OK;
>
> @@ -662,6 +664,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> return NOTIFY_OK;
>
> drvdata = cti_cpu_drvdata[cpu];
> + csdev = drvdata->csdev;
>
> if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
> return NOTIFY_BAD;
> @@ -673,13 +676,13 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> /* CTI regs all static - we have a copy & nothing to save */
> drvdata->config.hw_powered = false;
> if (drvdata->config.hw_enabled)
> - coresight_disclaim_device(drvdata->base);
> + coresight_disclaim_device(csdev);
> break;
>
> case CPU_PM_ENTER_FAILED:
> drvdata->config.hw_powered = true;
> if (drvdata->config.hw_enabled) {
> - if (coresight_claim_device(drvdata->base))
> + if (coresight_claim_device(csdev))
> drvdata->config.hw_enabled = false;
> }
> break;
> @@ -692,7 +695,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> /* check enable reference count to enable HW */
> if (atomic_read(&drvdata->config.enable_req_count)) {
> /* check we can claim the device as we re-power */
> - if (coresight_claim_device(drvdata->base))
> + if (coresight_claim_device(csdev))
> goto cti_notify_exit;
>
> drvdata->config.hw_enabled = true;
> @@ -736,7 +739,7 @@ static int cti_dying_cpu(unsigned int cpu)
> spin_lock(&drvdata->spinlock);
> drvdata->config.hw_powered = false;
> if (drvdata->config.hw_enabled)
> - coresight_disclaim_device(drvdata->base);
> + coresight_disclaim_device(drvdata->csdev);
> spin_unlock(&drvdata->spinlock);
> return 0;
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> index f994a22876d9..0a416883e012 100644
> --- a/drivers/hwtracing/coresight/coresight-etb10.c
> +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> @@ -132,7 +132,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata)
>
> static int etb_enable_hw(struct etb_drvdata *drvdata)
> {
> - int rc = coresight_claim_device(drvdata->base);
> + int rc = coresight_claim_device(drvdata->csdev);
>
> if (rc)
> return rc;
> @@ -344,7 +344,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
> {
> __etb_disable_hw(drvdata);
> etb_dump_hw(drvdata);
> - coresight_disclaim_device(drvdata->base);
> + coresight_disclaim_device(drvdata->csdev);
> }
>
> static int etb_disable(struct coresight_device *csdev)
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> index 36c5b0ae1b43..70d6d809cb47 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> @@ -358,10 +358,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
> int i, rc;
> u32 etmcr;
> struct etm_config *config = &drvdata->config;
> + struct coresight_device *csdev = drvdata->csdev;
>
> CS_UNLOCK(drvdata->base);
>
> - rc = coresight_claim_device_unlocked(drvdata->base);
> + rc = coresight_claim_device_unlocked(csdev);
> if (rc)
> goto done;
>
> @@ -566,6 +567,7 @@ static void etm_disable_hw(void *info)
> int i;
> struct etm_drvdata *drvdata = info;
> struct etm_config *config = &drvdata->config;
> + struct coresight_device *csdev = drvdata->csdev;
>
> CS_UNLOCK(drvdata->base);
> etm_set_prog(drvdata);
> @@ -577,7 +579,7 @@ static void etm_disable_hw(void *info)
> config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
>
> etm_set_pwrdwn(drvdata);
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
>
> CS_LOCK(drvdata->base);
>
> @@ -602,7 +604,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
> * power down the tracer.
> */
> etm_set_pwrdwn(drvdata);
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
>
> CS_LOCK(drvdata->base);
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 2744aadaa5ec..4f1bcf98fefe 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -115,7 +115,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>
> etm4_os_unlock(drvdata);
>
> - rc = coresight_claim_device_unlocked(drvdata->base);
> + rc = coresight_claim_device_unlocked(csdev);
> if (rc)
> goto done;
>
> @@ -523,7 +523,7 @@ static void etm4_disable_hw(void *info)
> readl_relaxed(drvdata->base + TRCCNTVRn(i));
> }
>
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
>
> CS_LOCK(drvdata->base);
>
> diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
> index f77466aea26f..2f8675c527bf 100644
> --- a/drivers/hwtracing/coresight/coresight-funnel.c
> +++ b/drivers/hwtracing/coresight/coresight-funnel.c
> @@ -52,13 +52,14 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
> {
> u32 functl;
> int rc = 0;
> + struct coresight_device *csdev = drvdata->csdev;
>
> CS_UNLOCK(drvdata->base);
>
> functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
> /* Claim the device only when we enable the first slave */
> if (!(functl & FUNNEL_ENSx_MASK)) {
> - rc = coresight_claim_device_unlocked(drvdata->base);
> + rc = coresight_claim_device_unlocked(csdev);
> if (rc)
> goto done;
> }
> @@ -101,6 +102,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
> int inport)
> {
> u32 functl;
> + struct coresight_device *csdev = drvdata->csdev;
>
> CS_UNLOCK(drvdata->base);
>
> @@ -110,7 +112,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
>
> /* Disclaim the device if none of the slaves are now active */
> if (!(functl & FUNNEL_ENSx_MASK))
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
>
> CS_LOCK(drvdata->base);
> }
> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
> index fcf25740116c..e35d79e74e30 100644
> --- a/drivers/hwtracing/coresight/coresight-replicator.c
> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
> @@ -45,12 +45,18 @@ struct replicator_drvdata {
>
> static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
> {
> + struct coresight_device *csdev = drvdata->csdev;
> CS_UNLOCK(drvdata->base);
>
> - if (!coresight_claim_device_unlocked(drvdata->base)) {
> + if (WARN_ON(!csdev))
> + return;

I don't see a need for this check. Function replicator_reset() is called from
probe() where the validity of drvdata->csdev is checked just before.

> +
> + CS_UNLOCK(drvdata->base);
> +
> + if (!coresight_claim_device_unlocked(csdev)) {
> writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
> writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
> }
>
> CS_LOCK(drvdata->base);
> @@ -70,6 +76,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
> {
> int rc = 0;
> u32 id0val, id1val;
> + struct coresight_device *csdev = drvdata->csdev;
>
> CS_UNLOCK(drvdata->base);
>
> @@ -84,7 +91,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
> id0val = id1val = 0xff;
>
> if (id0val == 0xff && id1val == 0xff)
> - rc = coresight_claim_device_unlocked(drvdata->base);
> + rc = coresight_claim_device_unlocked(csdev);
>
> if (!rc) {
> switch (outport) {
> @@ -140,6 +147,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
> int inport, int outport)
> {
> u32 reg;
> + struct coresight_device *csdev = drvdata->csdev;
>
> switch (outport) {
> case 0:
> @@ -160,7 +168,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
>
> if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
> (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
> CS_LOCK(drvdata->base);
> }
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 44402d413ebb..3a5605eda68f 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -37,7 +37,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
>
> static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
> {
> - int rc = coresight_claim_device(drvdata->base);
> + int rc = coresight_claim_device(drvdata->csdev);
>
> if (rc)
> return rc;
> @@ -88,7 +88,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
> static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
> {
> __tmc_etb_disable_hw(drvdata);
> - coresight_disclaim_device(drvdata->base);
> + coresight_disclaim_device(drvdata->csdev);
> }
>
> static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
> @@ -109,7 +109,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
>
> static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
> {
> - int rc = coresight_claim_device(drvdata->base);
> + int rc = coresight_claim_device(drvdata->csdev);
>
> if (rc)
> return rc;
> @@ -120,11 +120,13 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
>
> static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
> {
> + struct coresight_device *csdev = drvdata->csdev;
> +
> CS_UNLOCK(drvdata->base);
>
> tmc_flush_and_stop(drvdata);
> tmc_disable_hw(drvdata);
> - coresight_disclaim_device_unlocked(drvdata->base);
> + coresight_disclaim_device_unlocked(csdev);
> CS_LOCK(drvdata->base);
> }
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 714f9e867e5f..a8b1c49761c7 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -1038,7 +1038,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
> rc = tmc_etr_enable_catu(drvdata, etr_buf);
> if (rc)
> return rc;
> - rc = coresight_claim_device(drvdata->base);
> + rc = coresight_claim_device(drvdata->csdev);
> if (!rc) {
> drvdata->etr_buf = etr_buf;
> __tmc_etr_enable_hw(drvdata);
> @@ -1132,7 +1132,7 @@ void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
> __tmc_etr_disable_hw(drvdata);
> /* Disable CATU device if this ETR is connected to one */
> tmc_etr_disable_catu(drvdata);
> - coresight_disclaim_device(drvdata->base);
> + coresight_disclaim_device(drvdata->csdev);
> /* Reset the ETR buf used by hardware */
> drvdata->etr_buf = NULL;
> }
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index cefc8fe239e6..c2d0a2aea45f 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -474,11 +474,11 @@ extern int coresight_timeout(struct csdev_access *csa,
> int position,
> int value);
>
> -extern int coresight_claim_device(void __iomem *base);
> -extern int coresight_claim_device_unlocked(void __iomem *base);
> +extern int coresight_claim_device(struct coresight_device *csdev);
> +extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
>
> -extern void coresight_disclaim_device(void __iomem *base);
> -extern void coresight_disclaim_device_unlocked(void __iomem *base);
> +extern void coresight_disclaim_device(struct coresight_device *csdev);
> +extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
> extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
> struct device *dev);
>
> @@ -513,18 +513,18 @@ static inline int coresight_timeout(struct csdev_access *csa,
> return 1;
> }
>
> -static inline int coresight_claim_device_unlocked(void __iomem *base)
> +static inline int coresight_claim_device_unlocked(struct coresight_device *csdev)
> {
> return -EINVAL;
> }
>
> -static inline int coresight_claim_device(void __iomem *base)
> +static inline int coresight_claim_device(struct coresight_device *csdev)
> {
> return -EINVAL;
> }
>
> -static inline void coresight_disclaim_device(void __iomem *base) {}
> -static inline void coresight_disclaim_device_unlocked(void __iomem *base) {}
> +static inline void coresight_disclaim_device(struct coresight_device *csdev) {}
> +static inline void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {}
>
> static inline bool coresight_loses_context_with_cpu(struct device *dev)
> {
> --
> 2.24.1
>

2020-11-03 18:56:52

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 12/26] coresight: etm4x: Convert all register accesses

On Wed, Oct 28, 2020 at 10:09:31PM +0000, Suzuki K Poulose wrote:
> Convert all register accesses from etm4x driver to use a wrapper
> to allow switching the access at runtime with little overhead.
>
> co-developed by sed tool ;-), mostly equivalent to :
>
> s/readl\(_relaxed\)\?(drvdata->base + \(.*\))/etm4x_\1_read32(csdev, \2)
> s/writel\(_relaxed\)\?(\(.*\), drvdata->base + \(.*\))/etm4x_\1_write32(csdev, \2, \3)
>
> We don't want to replace them with the csdev_access_* to
> avoid a function call for every register access for system
> register access. This is a prepartory step to add system
> register access later where the support is available.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 326 +++++++++---------
> .../coresight/coresight-etm4x-sysfs.c | 9 +-
> drivers/hwtracing/coresight/coresight-etm4x.h | 24 ++
> 3 files changed, 187 insertions(+), 172 deletions(-)

Reviewed-by: Mathieu Poirier <[email protected]>

>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 4f1bcf98fefe..4af7d45dfe63 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -56,18 +56,28 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>
> static enum cpuhp_state hp_online;
>
> -static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
> +static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
> {
> /* Writing 0 to TRCOSLAR unlocks the trace registers */
> - writel_relaxed(0x0, drvdata->base + TRCOSLAR);
> + etm4x_relaxed_write32(csa, 0x0, TRCOSLAR);
> drvdata->os_unlock = true;
> isb();
> }
>
> +static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
> +{
> + if (!WARN_ON(!drvdata->csdev))
> + etm4_os_unlock_csa(drvdata, &drvdata->csdev->access);
> +
> +}
> +
> static void etm4_os_lock(struct etmv4_drvdata *drvdata)
> {
> + if (WARN_ON(!drvdata->csdev))
> + return;
> +
> /* Writing 0x1 to TRCOSLAR locks the trace registers */
> - writel_relaxed(0x1, drvdata->base + TRCOSLAR);
> + etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR);
> drvdata->os_unlock = false;
> isb();
> }
> @@ -120,45 +130,39 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> goto done;
>
> /* Disable the trace unit before programming trace registers */
> - writel_relaxed(0, drvdata->base + TRCPRGCTLR);
> + etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
>
> /* wait for TRCSTATR.IDLE to go up */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
> dev_err(etm_dev,
> "timeout while waiting for Idle Trace Status\n");
> if (drvdata->nr_pe)
> - writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
> - writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
> + etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR);
> + etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR);
> /* nothing specific implemented */
> - writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
> - writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R);
> - writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R);
> - writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR);
> - writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR);
> - writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR);
> - writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR);
> - writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR);
> - writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR);
> - writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR);
> - writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
> - writel_relaxed(config->vissctlr,
> - drvdata->base + TRCVISSCTLR);
> + etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR);
> + etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R);
> + etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R);
> + etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR);
> + etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR);
> + etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR);
> + etm4x_relaxed_write32(csa, config->ccctlr, TRCCCCTLR);
> + etm4x_relaxed_write32(csa, config->bb_ctrl, TRCBBCTLR);
> + etm4x_relaxed_write32(csa, drvdata->trcid, TRCTRACEIDR);
> + etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR);
> + etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR);
> + etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR);
> if (drvdata->nr_pe_cmp)
> - writel_relaxed(config->vipcssctlr,
> - drvdata->base + TRCVIPCSSCTLR);
> + etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR);
> for (i = 0; i < drvdata->nrseqstate - 1; i++)
> - writel_relaxed(config->seq_ctrl[i],
> - drvdata->base + TRCSEQEVRn(i));
> - writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR);
> - writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR);
> - writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR);
> + etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i));
> + etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR);
> + etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR);
> + etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR);
> for (i = 0; i < drvdata->nr_cntr; i++) {
> - writel_relaxed(config->cntrldvr[i],
> - drvdata->base + TRCCNTRLDVRn(i));
> - writel_relaxed(config->cntr_ctrl[i],
> - drvdata->base + TRCCNTCTLRn(i));
> - writel_relaxed(config->cntr_val[i],
> - drvdata->base + TRCCNTVRn(i));
> + etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i));
> + etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i));
> + etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i));
> }
>
> /*
> @@ -166,52 +170,45 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> * such start at 2.
> */
> for (i = 2; i < drvdata->nr_resource * 2; i++)
> - writel_relaxed(config->res_ctrl[i],
> - drvdata->base + TRCRSCTLRn(i));
> + etm4x_relaxed_write32(csa, config->res_ctrl[i], TRCRSCTLRn(i));
>
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> /* always clear status bit on restart if using single-shot */
> if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
> config->ss_status[i] &= ~BIT(31);
> - writel_relaxed(config->ss_ctrl[i],
> - drvdata->base + TRCSSCCRn(i));
> - writel_relaxed(config->ss_status[i],
> - drvdata->base + TRCSSCSRn(i));
> + etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
> + etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
> if (drvdata->nr_pe)
> - writel_relaxed(config->ss_pe_cmp[i],
> - drvdata->base + TRCSSPCICRn(i));
> + etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
> }
> for (i = 0; i < drvdata->nr_addr_cmp; i++) {
> - writeq_relaxed(config->addr_val[i],
> - drvdata->base + TRCACVRn(i));
> - writeq_relaxed(config->addr_acc[i],
> - drvdata->base + TRCACATRn(i));
> + etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
> + etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
> }
> for (i = 0; i < drvdata->numcidc; i++)
> - writeq_relaxed(config->ctxid_pid[i],
> - drvdata->base + TRCCIDCVRn(i));
> - writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
> + etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i));
> + etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0);
> if (drvdata->numcidc > 4)
> - writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
> + etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1);
>
> for (i = 0; i < drvdata->numvmidc; i++)
> - writeq_relaxed(config->vmid_val[i],
> - drvdata->base + TRCVMIDCVRn(i));
> - writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
> + etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i));
> + etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0);
> if (drvdata->numvmidc > 4)
> - writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
> + etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1);
>
> if (!drvdata->skip_power_up) {
> + u32 trcpdcr = etm4x_relaxed_read32(csa, TRCPDCR);
> +
> /*
> * Request to keep the trace unit powered and also
> * emulation of powerdown
> */
> - writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) |
> - TRCPDCR_PU, drvdata->base + TRCPDCR);
> + etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
> }
>
> /* Enable the trace unit */
> - writel_relaxed(1, drvdata->base + TRCPRGCTLR);
> + etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
>
> /* wait for TRCSTATR.IDLE to go back down to '0' */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
> @@ -487,12 +484,12 @@ static void etm4_disable_hw(void *info)
>
> if (!drvdata->skip_power_up) {
> /* power can be removed from the trace unit now */
> - control = readl_relaxed(drvdata->base + TRCPDCR);
> + control = etm4x_relaxed_read32(csa, TRCPDCR);
> control &= ~TRCPDCR_PU;
> - writel_relaxed(control, drvdata->base + TRCPDCR);
> + etm4x_relaxed_write32(csa, control, TRCPDCR);
> }
>
> - control = readl_relaxed(drvdata->base + TRCPRGCTLR);
> + control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
>
> /* EN, bit[0] Trace unit enable bit */
> control &= ~0x1;
> @@ -504,7 +501,7 @@ static void etm4_disable_hw(void *info)
> */
> dsb(sy);
> isb();
> - writel_relaxed(control, drvdata->base + TRCPRGCTLR);
> + etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
>
> /* wait for TRCSTATR.PMSTABLE to go to '1' */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
> @@ -514,13 +511,13 @@ static void etm4_disable_hw(void *info)
> /* read the status of the single shot comparators */
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> config->ss_status[i] =
> - readl_relaxed(drvdata->base + TRCSSCSRn(i));
> + etm4x_relaxed_read32(csa, TRCSSCSRn(i));
> }
>
> /* read back the current counter values */
> for (i = 0; i < drvdata->nr_cntr; i++) {
> config->cntr_val[i] =
> - readl_relaxed(drvdata->base + TRCCNTVRn(i));
> + etm4x_relaxed_read32(csa, TRCCNTVRn(i));
> }
>
> coresight_disclaim_device_unlocked(csdev);
> @@ -549,7 +546,7 @@ static int etm4_disable_perf(struct coresight_device *csdev,
> * scheduled again. Configuration of the start/stop logic happens in
> * function etm4_set_event_filters().
> */
> - control = readl_relaxed(drvdata->base + TRCVICTLR);
> + control = etm4x_relaxed_read32(&csdev->access, TRCVICTLR);
> /* TRCVICTLR::SSSTATUS, bit[9] */
> filters->ssstatus = (control & BIT(9));
>
> @@ -629,15 +626,17 @@ static void etm4_init_arch_data(void *info)
> u32 etmidr4;
> u32 etmidr5;
> struct etmv4_drvdata *drvdata = info;
> + struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> + struct csdev_access *csa = &tmp_csa;
> int i;
>
> /* Make sure all registers are accessible */
> - etm4_os_unlock(drvdata);
> + etm4_os_unlock_csa(drvdata, csa);
>
> CS_UNLOCK(drvdata->base);
>
> /* find all capabilities of the tracing unit */
> - etmidr0 = readl_relaxed(drvdata->base + TRCIDR0);
> + etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
>
> /* INSTP0, bits[2:1] P0 tracing support field */
> if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2))
> @@ -677,7 +676,7 @@ static void etm4_init_arch_data(void *info)
> drvdata->ts_size = BMVAL(etmidr0, 24, 28);
>
> /* base architecture of trace unit */
> - etmidr1 = readl_relaxed(drvdata->base + TRCIDR1);
> + etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1);
> /*
> * TRCARCHMIN, bits[7:4] architecture the minor version number
> * TRCARCHMAJ, bits[11:8] architecture major versin number
> @@ -686,7 +685,7 @@ static void etm4_init_arch_data(void *info)
> drvdata->config.arch = drvdata->arch;
>
> /* maximum size of resources */
> - etmidr2 = readl_relaxed(drvdata->base + TRCIDR2);
> + etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
> /* CIDSIZE, bits[9:5] Indicates the Context ID size */
> drvdata->ctxid_size = BMVAL(etmidr2, 5, 9);
> /* VMIDSIZE, bits[14:10] Indicates the VMID size */
> @@ -694,7 +693,7 @@ static void etm4_init_arch_data(void *info)
> /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */
> drvdata->ccsize = BMVAL(etmidr2, 25, 28);
>
> - etmidr3 = readl_relaxed(drvdata->base + TRCIDR3);
> + etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3);
> /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */
> drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
> /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
> @@ -744,7 +743,7 @@ static void etm4_init_arch_data(void *info)
> drvdata->nooverflow = false;
>
> /* number of resources trace unit supports */
> - etmidr4 = readl_relaxed(drvdata->base + TRCIDR4);
> + etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4);
> /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */
> drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3);
> /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
> @@ -770,14 +769,14 @@ static void etm4_init_arch_data(void *info)
> drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23);
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> drvdata->config.ss_status[i] =
> - readl_relaxed(drvdata->base + TRCSSCSRn(i));
> + etm4x_relaxed_read32(csa, TRCSSCSRn(i));
> }
> /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */
> drvdata->numcidc = BMVAL(etmidr4, 24, 27);
> /* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */
> drvdata->numvmidc = BMVAL(etmidr4, 28, 31);
>
> - etmidr5 = readl_relaxed(drvdata->base + TRCIDR5);
> + etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5);
> /* NUMEXTIN, bits[8:0] number of external inputs implemented */
> drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8);
> /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */
> @@ -1196,56 +1195,56 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
>
> state = drvdata->save_state;
>
> - state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR);
> + state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR);
> if (drvdata->nr_pe)
> - state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
> - state->trcconfigr = readl(drvdata->base + TRCCONFIGR);
> - state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR);
> - state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R);
> - state->trceventctl1r = readl(drvdata->base + TRCEVENTCTL1R);
> - state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR);
> - state->trctsctlr = readl(drvdata->base + TRCTSCTLR);
> - state->trcsyncpr = readl(drvdata->base + TRCSYNCPR);
> - state->trcccctlr = readl(drvdata->base + TRCCCCTLR);
> - state->trcbbctlr = readl(drvdata->base + TRCBBCTLR);
> - state->trctraceidr = readl(drvdata->base + TRCTRACEIDR);
> - state->trcqctlr = readl(drvdata->base + TRCQCTLR);
> -
> - state->trcvictlr = readl(drvdata->base + TRCVICTLR);
> - state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR);
> - state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR);
> + state->trcprocselr = etm4x_read32(csa, TRCPROCSELR);
> + state->trcconfigr = etm4x_read32(csa, TRCCONFIGR);
> + state->trcauxctlr = etm4x_read32(csa, TRCAUXCTLR);
> + state->trceventctl0r = etm4x_read32(csa, TRCEVENTCTL0R);
> + state->trceventctl1r = etm4x_read32(csa, TRCEVENTCTL1R);
> + state->trcstallctlr = etm4x_read32(csa, TRCSTALLCTLR);
> + state->trctsctlr = etm4x_read32(csa, TRCTSCTLR);
> + state->trcsyncpr = etm4x_read32(csa, TRCSYNCPR);
> + state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
> + state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
> + state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
> + state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
> +
> + state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
> + state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
> + state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
> if (drvdata->nr_pe_cmp)
> - state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
> - state->trcvdctlr = readl(drvdata->base + TRCVDCTLR);
> - state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR);
> - state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR);
> + state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
> + state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR);
> + state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR);
> + state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR);
>
> for (i = 0; i < drvdata->nrseqstate - 1; i++)
> - state->trcseqevr[i] = readl(drvdata->base + TRCSEQEVRn(i));
> + state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
>
> - state->trcseqrstevr = readl(drvdata->base + TRCSEQRSTEVR);
> - state->trcseqstr = readl(drvdata->base + TRCSEQSTR);
> - state->trcextinselr = readl(drvdata->base + TRCEXTINSELR);
> + state->trcseqrstevr = etm4x_read32(csa, TRCSEQRSTEVR);
> + state->trcseqstr = etm4x_read32(csa, TRCSEQSTR);
> + state->trcextinselr = etm4x_read32(csa, TRCEXTINSELR);
>
> for (i = 0; i < drvdata->nr_cntr; i++) {
> - state->trccntrldvr[i] = readl(drvdata->base + TRCCNTRLDVRn(i));
> - state->trccntctlr[i] = readl(drvdata->base + TRCCNTCTLRn(i));
> - state->trccntvr[i] = readl(drvdata->base + TRCCNTVRn(i));
> + state->trccntrldvr[i] = etm4x_read32(csa, TRCCNTRLDVRn(i));
> + state->trccntctlr[i] = etm4x_read32(csa, TRCCNTCTLRn(i));
> + state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i));
> }
>
> for (i = 0; i < drvdata->nr_resource * 2; i++)
> - state->trcrsctlr[i] = readl(drvdata->base + TRCRSCTLRn(i));
> + state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));
>
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> - state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i));
> - state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i));
> + state->trcssccr[i] = etm4x_read32(csa, TRCSSCCRn(i));
> + state->trcsscsr[i] = etm4x_read32(csa, TRCSSCSRn(i));
> if (drvdata->nr_pe)
> - state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
> + state->trcsspcicr[i] = etm4x_read32(csa, TRCSSPCICRn(i));
> }
>
> for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> - state->trcacvr[i] = readq(drvdata->base + TRCACVRn(i));
> - state->trcacatr[i] = readq(drvdata->base + TRCACATRn(i));
> + state->trcacvr[i] = etm4x_read64(csa, TRCACVRn(i));
> + state->trcacatr[i] = etm4x_read64(csa, TRCACATRn(i));
> }
>
> /*
> @@ -1256,22 +1255,22 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> */
>
> for (i = 0; i < drvdata->numcidc; i++)
> - state->trccidcvr[i] = readq(drvdata->base + TRCCIDCVRn(i));
> + state->trccidcvr[i] = etm4x_read64(csa, TRCCIDCVRn(i));
>
> for (i = 0; i < drvdata->numvmidc; i++)
> - state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i));
> + state->trcvmidcvr[i] = etm4x_read64(csa, TRCVMIDCVRn(i));
>
> - state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0);
> + state->trccidcctlr0 = etm4x_read32(csa, TRCCIDCCTLR0);
> if (drvdata->numcidc > 4)
> - state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
> + state->trccidcctlr1 = etm4x_read32(csa, TRCCIDCCTLR1);
>
> - state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
> + state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0);
> if (drvdata->numvmidc > 4)
> - state->trcvmidcctlr1 = readl(drvdata->base + TRCVMIDCCTLR1);
> + state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1);
>
> - state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);
> + state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR);
>
> - state->trcpdcr = readl(drvdata->base + TRCPDCR);
> + state->trcpdcr = etm4x_read32(csa, TRCPDCR);
>
> /* wait for TRCSTATR.IDLE to go up */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
> @@ -1289,8 +1288,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> * potentially save power on systems that respect the TRCPDCR_PU
> * despite requesting software to save/restore state.
> */
> - writel_relaxed((state->trcpdcr & ~TRCPDCR_PU),
> - drvdata->base + TRCPDCR);
> + etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
>
> out:
> CS_LOCK(drvdata->base);
> @@ -1301,92 +1299,82 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
> {
> int i;
> struct etmv4_save_state *state = drvdata->save_state;
> + struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> + struct csdev_access *csa = &tmp_csa;
>
> CS_UNLOCK(drvdata->base);
>
> - writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
> + etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
>
> - writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR);
> + etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
> if (drvdata->nr_pe)
> - writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
> - writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR);
> - writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR);
> - writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R);
> - writel_relaxed(state->trceventctl1r, drvdata->base + TRCEVENTCTL1R);
> - writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR);
> - writel_relaxed(state->trctsctlr, drvdata->base + TRCTSCTLR);
> - writel_relaxed(state->trcsyncpr, drvdata->base + TRCSYNCPR);
> - writel_relaxed(state->trcccctlr, drvdata->base + TRCCCCTLR);
> - writel_relaxed(state->trcbbctlr, drvdata->base + TRCBBCTLR);
> - writel_relaxed(state->trctraceidr, drvdata->base + TRCTRACEIDR);
> - writel_relaxed(state->trcqctlr, drvdata->base + TRCQCTLR);
> -
> - writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR);
> - writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR);
> - writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR);
> + etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR);
> + etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR);
> + etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR);
> + etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R);
> + etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R);
> + etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR);
> + etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR);
> + etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR);
> + etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
> + etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
> + etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
> + etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
> +
> + etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
> + etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
> + etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
> if (drvdata->nr_pe_cmp)
> - writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
> - writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR);
> - writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR);
> - writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR);
> + etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
> + etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR);
> + etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR);
> + etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR);
>
> for (i = 0; i < drvdata->nrseqstate - 1; i++)
> - writel_relaxed(state->trcseqevr[i],
> - drvdata->base + TRCSEQEVRn(i));
> + etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
>
> - writel_relaxed(state->trcseqrstevr, drvdata->base + TRCSEQRSTEVR);
> - writel_relaxed(state->trcseqstr, drvdata->base + TRCSEQSTR);
> - writel_relaxed(state->trcextinselr, drvdata->base + TRCEXTINSELR);
> + etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR);
> + etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR);
> + etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR);
>
> for (i = 0; i < drvdata->nr_cntr; i++) {
> - writel_relaxed(state->trccntrldvr[i],
> - drvdata->base + TRCCNTRLDVRn(i));
> - writel_relaxed(state->trccntctlr[i],
> - drvdata->base + TRCCNTCTLRn(i));
> - writel_relaxed(state->trccntvr[i],
> - drvdata->base + TRCCNTVRn(i));
> + etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i));
> + etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i));
> + etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i));
> }
>
> for (i = 0; i < drvdata->nr_resource * 2; i++)
> - writel_relaxed(state->trcrsctlr[i],
> - drvdata->base + TRCRSCTLRn(i));
> + etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));
>
> for (i = 0; i < drvdata->nr_ss_cmp; i++) {
> - writel_relaxed(state->trcssccr[i],
> - drvdata->base + TRCSSCCRn(i));
> - writel_relaxed(state->trcsscsr[i],
> - drvdata->base + TRCSSCSRn(i));
> + etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i));
> + etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i));
> if (drvdata->nr_pe)
> - writel_relaxed(state->trcsspcicr[i],
> - drvdata->base + TRCSSPCICRn(i));
> + etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i));
> }
>
> for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
> - writeq_relaxed(state->trcacvr[i],
> - drvdata->base + TRCACVRn(i));
> - writeq_relaxed(state->trcacatr[i],
> - drvdata->base + TRCACATRn(i));
> + etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i));
> + etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i));
> }
>
> for (i = 0; i < drvdata->numcidc; i++)
> - writeq_relaxed(state->trccidcvr[i],
> - drvdata->base + TRCCIDCVRn(i));
> + etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i));
>
> for (i = 0; i < drvdata->numvmidc; i++)
> - writeq_relaxed(state->trcvmidcvr[i],
> - drvdata->base + TRCVMIDCVRn(i));
> + etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i));
>
> - writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0);
> + etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0);
> if (drvdata->numcidc > 4)
> - writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
> + etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1);
>
> - writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
> + etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0);
> if (drvdata->numvmidc > 4)
> - writel_relaxed(state->trcvmidcctlr1, drvdata->base + TRCVMIDCCTLR1);
> + etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1);
>
> - writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
> + etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
>
> - writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR);
> + etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR);
>
> drvdata->state_needs_restore = false;
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index c4781d4e5886..fce9df16bfb5 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -2319,7 +2319,8 @@ static struct attribute *coresight_etmv4_attrs[] = {
> };
>
> struct etmv4_reg {
> - void __iomem *addr;
> + struct coresight_device *csdev;
> + u32 offset;
> u32 data;
> };
>
> @@ -2327,7 +2328,7 @@ static void do_smp_cross_read(void *data)
> {
> struct etmv4_reg *reg = data;
>
> - reg->data = readl_relaxed(reg->addr);
> + reg->data = etm4x_relaxed_read32(&reg->csdev->access, reg->offset);
> }
>
> static u32 etmv4_cross_read(const struct device *dev, u32 offset)
> @@ -2335,7 +2336,9 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset)
> struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
> struct etmv4_reg reg;
>
> - reg.addr = drvdata->base + offset;
> + reg.offset = offset;
> + reg.csdev = drvdata->csdev;
> +
> /*
> * smp cross call ensures the CPU will be powered up before
> * accessing the ETMv4 trace core registers
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index eefc7371c6c4..14e0f29db6b3 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -120,6 +120,30 @@
> #define TRCCIDR2 0xFF8
> #define TRCCIDR3 0xFFC
>
> +#define etm4x_relaxed_read32(csa, offset) \
> + readl_relaxed((csa)->base + (offset))
> +
> +#define etm4x_read32(csa, offset) \
> + readl((csa)->base + (offset))
> +
> +#define etm4x_relaxed_write32(csa, val, offset) \
> + writel_relaxed((val), (csa)->base + (offset))
> +
> +#define etm4x_write32(csa, val, offset) \
> + writel((val), (csa)->base + (offset))
> +
> +#define etm4x_relaxed_read64(csa, offset) \
> + readq_relaxed((csa)->base + (offset))
> +
> +#define etm4x_read64(csa, offset) \
> + readq((csa)->base + (offset))
> +
> +#define etm4x_relaxed_write64(csa, val, offset) \
> + writeq_relaxed((val), (csa)->base + (offset))
> +
> +#define etm4x_write64(csa, val, offset) \
> + writeq((val), (csa)->base + (offset))
> +
> /* ETMv4 resources */
> #define ETM_MAX_NR_PE 8
> #define ETMv4_MAX_CNTR 4
> --
> 2.24.1
>

2020-11-03 19:05:47

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 13/26] coresight: etm4x: Add commentary on the registers

On Wed, Oct 28, 2020 at 10:09:32PM +0000, Suzuki K Poulose wrote:
> As we are about define a switch..case table for individual register
> access by offset for implementing the system instruction support,
> document the possible set of registers for each group to make
> it easier to co-relate.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-etm4x.h | 21 ++++++++++++-------
> 1 file changed, 13 insertions(+), 8 deletions(-)

Reviewed-by: Mathieu Poirier <[email protected]>

I'm done for today and will continue tomorrow.

Thanks,
Mathieu

>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 14e0f29db6b3..510828c73db6 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -44,13 +44,13 @@
> #define TRCVDSACCTLR 0x0A4
> #define TRCVDARCCTLR 0x0A8
> /* Derived resources registers */
> -#define TRCSEQEVRn(n) (0x100 + (n * 4))
> +#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */
> #define TRCSEQRSTEVR 0x118
> #define TRCSEQSTR 0x11C
> #define TRCEXTINSELR 0x120
> -#define TRCCNTRLDVRn(n) (0x140 + (n * 4))
> -#define TRCCNTCTLRn(n) (0x150 + (n * 4))
> -#define TRCCNTVRn(n) (0x160 + (n * 4))
> +#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) /* n = 0-3 */
> +#define TRCCNTCTLRn(n) (0x150 + (n * 4)) /* n = 0-3 */
> +#define TRCCNTVRn(n) (0x160 + (n * 4)) /* n = 0-3 */
> /* ID registers */
> #define TRCIDR8 0x180
> #define TRCIDR9 0x184
> @@ -59,7 +59,7 @@
> #define TRCIDR12 0x190
> #define TRCIDR13 0x194
> #define TRCIMSPEC0 0x1C0
> -#define TRCIMSPECn(n) (0x1C0 + (n * 4))
> +#define TRCIMSPECn(n) (0x1C0 + (n * 4)) /* n = 1-7 */
> #define TRCIDR0 0x1E0
> #define TRCIDR1 0x1E4
> #define TRCIDR2 0x1E8
> @@ -68,9 +68,12 @@
> #define TRCIDR5 0x1F4
> #define TRCIDR6 0x1F8
> #define TRCIDR7 0x1FC
> -/* Resource selection registers */
> +/*
> + * Resource selection registers, n = 2-31.
> + * First pair (regs 0, 1) is always present and is reserved.
> + */
> #define TRCRSCTLRn(n) (0x200 + (n * 4))
> -/* Single-shot comparator registers */
> +/* Single-shot comparator registers, n = 0-7 */
> #define TRCSSCCRn(n) (0x280 + (n * 4))
> #define TRCSSCSRn(n) (0x2A0 + (n * 4))
> #define TRCSSPCICRn(n) (0x2C0 + (n * 4))
> @@ -80,11 +83,13 @@
> #define TRCPDCR 0x310
> #define TRCPDSR 0x314
> /* Trace registers (0x318-0xEFC) */
> -/* Comparator registers */
> +/* Address Comparator registers n = 0-15 */
> #define TRCACVRn(n) (0x400 + (n * 8))
> #define TRCACATRn(n) (0x480 + (n * 8))
> +/* Data Value Comparator Value registers, n = 0-7 */
> #define TRCDVCVRn(n) (0x500 + (n * 16))
> #define TRCDVCMRn(n) (0x580 + (n * 16))
> +/* ContextID/Virtual ContextID comparators, n = 0-7 */
> #define TRCCIDCVRn(n) (0x600 + (n * 8))
> #define TRCVMIDCVRn(n) (0x640 + (n * 8))
> #define TRCCIDCCTLR0 0x680
> --
> 2.24.1
>

2020-11-03 19:07:08

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 13/26] coresight: etm4x: Add commentary on the registers

On Wed, 28 Oct 2020 at 16:10, Suzuki K Poulose <[email protected]> wrote:
>
> As we are about define a switch..case table for individual register
> access by offset for implementing the system instruction support,
> document the possible set of registers for each group to make
> it easier to co-relate.

s/co-relate/correlate

>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-etm4x.h | 21 ++++++++++++-------
> 1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 14e0f29db6b3..510828c73db6 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -44,13 +44,13 @@
> #define TRCVDSACCTLR 0x0A4
> #define TRCVDARCCTLR 0x0A8
> /* Derived resources registers */
> -#define TRCSEQEVRn(n) (0x100 + (n * 4))
> +#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */
> #define TRCSEQRSTEVR 0x118
> #define TRCSEQSTR 0x11C
> #define TRCEXTINSELR 0x120
> -#define TRCCNTRLDVRn(n) (0x140 + (n * 4))
> -#define TRCCNTCTLRn(n) (0x150 + (n * 4))
> -#define TRCCNTVRn(n) (0x160 + (n * 4))
> +#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) /* n = 0-3 */
> +#define TRCCNTCTLRn(n) (0x150 + (n * 4)) /* n = 0-3 */
> +#define TRCCNTVRn(n) (0x160 + (n * 4)) /* n = 0-3 */
> /* ID registers */
> #define TRCIDR8 0x180
> #define TRCIDR9 0x184
> @@ -59,7 +59,7 @@
> #define TRCIDR12 0x190
> #define TRCIDR13 0x194
> #define TRCIMSPEC0 0x1C0
> -#define TRCIMSPECn(n) (0x1C0 + (n * 4))
> +#define TRCIMSPECn(n) (0x1C0 + (n * 4)) /* n = 1-7 */
> #define TRCIDR0 0x1E0
> #define TRCIDR1 0x1E4
> #define TRCIDR2 0x1E8
> @@ -68,9 +68,12 @@
> #define TRCIDR5 0x1F4
> #define TRCIDR6 0x1F8
> #define TRCIDR7 0x1FC
> -/* Resource selection registers */
> +/*
> + * Resource selection registers, n = 2-31.
> + * First pair (regs 0, 1) is always present and is reserved.
> + */
> #define TRCRSCTLRn(n) (0x200 + (n * 4))
> -/* Single-shot comparator registers */
> +/* Single-shot comparator registers, n = 0-7 */
> #define TRCSSCCRn(n) (0x280 + (n * 4))
> #define TRCSSCSRn(n) (0x2A0 + (n * 4))
> #define TRCSSPCICRn(n) (0x2C0 + (n * 4))
> @@ -80,11 +83,13 @@
> #define TRCPDCR 0x310
> #define TRCPDSR 0x314
> /* Trace registers (0x318-0xEFC) */
> -/* Comparator registers */
> +/* Address Comparator registers n = 0-15 */
> #define TRCACVRn(n) (0x400 + (n * 8))
> #define TRCACATRn(n) (0x480 + (n * 8))
> +/* Data Value Comparator Value registers, n = 0-7 */
> #define TRCDVCVRn(n) (0x500 + (n * 16))
> #define TRCDVCMRn(n) (0x580 + (n * 16))
> +/* ContextID/Virtual ContextID comparators, n = 0-7 */
> #define TRCCIDCVRn(n) (0x600 + (n * 8))
> #define TRCVMIDCVRn(n) (0x640 + (n * 8))
> #define TRCCIDCCTLR0 0x680
> --
> 2.24.1
>

2020-11-04 10:46:40

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 09/26] coresight: Convert coresight_timeout to use access abstraction

On 11/3/20 6:03 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:28PM +0000, Suzuki K Poulose wrote:
>> Convert the generic routines to use the new access abstraction layer
>> gradually, starting with coresigth_timeout.
>>
>> Cc: Mike Leach <[email protected]>
>> Reviewed-by: Mathieu Poirier <[email protected]>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---



>> diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
>> index 5baf29510f1b..34c74b05c542 100644
>> --- a/drivers/hwtracing/coresight/coresight-catu.c
>> +++ b/drivers/hwtracing/coresight/coresight-catu.c
>> @@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {
>>
>> static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
>> {
>> - return coresight_timeout(drvdata->base,
>> - CATU_STATUS, CATU_STATUS_READY, 1);
>> + struct csdev_access *csa = &drvdata->csdev->access;
>> +
>> + return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
>> }
>>
>> static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
>> diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
>> index e96deaca8cab..42ba989a6b5e 100644
>> --- a/drivers/hwtracing/coresight/coresight-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-core.c
>> @@ -1412,23 +1412,26 @@ static void coresight_remove_conns(struct coresight_device *csdev)
>> }
>>
>> /**
>> - * coresight_timeout - loop until a bit has changed to a specific state.
>> - * @addr: base address of the area of interest.
>> - * @offset: address of a register, starting from @addr.
>> + * coresight_timeout - loop until a bit has changed to a specific register
>> + * state.
>> + * @csa: coresight device access for the device
>> + * @offset: Offset of the register from the base of the device.
>> * @position: the position of the bit of interest.
>> * @value: the value the bit should have.
>> *
>> * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
>> * TIMEOUT_US has elapsed, which ever happens first.
>> */
>> -
>> -int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
>> +int coresight_timeout(struct csdev_access *csa,
>> + u32 offset,
>> + int position,
>> + int value)
>
> There is no need for stacking, please maximise the 80 characters. The function
> stubs in coresight.h should also be revised.
>
>> {
>> int i;
>> u32 val;
>>
>> for (i = TIMEOUT_US; i > 0; i--) {
>> - val = __raw_readl(addr + offset);
>> + val = csdev_access_read32(csa, offset);
>
> I vaguely remember commenting on this, or perhaps it was on some othe patch you
> wrote... Anyways, I think it is a good thing to go from an unordered access to
> an ordered access for the timeout function.

Yes, you did mention it in the v1.

>
> With the above:
>
> Reviewed-by: Mathieu Poirier <[email protected]>

Thanks, will address the comments.

Suzuki

2020-11-04 10:56:55

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 10/26] coresight: Convert claim/disclaim operations to use access wrappers

On 11/3/20 6:36 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:29PM +0000, Suzuki K Poulose wrote:
>> Convert the generic CLAIM tag management APIs to use the
>> device access layer abstraction.
>>
>> Cc: Mathieu Poirier <[email protected]>
>> Cc: Mike Leach <[email protected]>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> drivers/hwtracing/coresight/coresight-catu.c | 6 +-
>> drivers/hwtracing/coresight/coresight-core.c | 66 +++++++++++--------
>> .../hwtracing/coresight/coresight-cti-core.c | 17 +++--
>> drivers/hwtracing/coresight/coresight-etb10.c | 4 +-
>> .../coresight/coresight-etm3x-core.c | 8 ++-
>> .../coresight/coresight-etm4x-core.c | 4 +-
>> .../hwtracing/coresight/coresight-funnel.c | 6 +-
>> .../coresight/coresight-replicator.c | 16 +++--
>> .../hwtracing/coresight/coresight-tmc-etf.c | 10 +--
>> .../hwtracing/coresight/coresight-tmc-etr.c | 4 +-
>> include/linux/coresight.h | 16 ++---
>> 11 files changed, 95 insertions(+), 62 deletions(-)
>>

>> }
>>
>> -static inline void coresight_set_claim_tags(void __iomem *base)
>> +static inline void coresight_set_claim_tags(struct coresight_device *csdev)
>> {
>> - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET);
>> + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>> + CORESIGHT_CLAIMSET);
>
> Indentation
>
>> isb();
>> }
>>
>> -static inline void coresight_clear_claim_tags(void __iomem *base)
>> +static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
>> {
>> - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR);
>> + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
>> + CORESIGHT_CLAIMCLR);
>
> Indentation
>
>> isb();
>> }
>>


>> diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
>> index fcf25740116c..e35d79e74e30 100644
>> --- a/drivers/hwtracing/coresight/coresight-replicator.c
>> +++ b/drivers/hwtracing/coresight/coresight-replicator.c
>> @@ -45,12 +45,18 @@ struct replicator_drvdata {
>>
>> static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
>> {
>> + struct coresight_device *csdev = drvdata->csdev;
>> CS_UNLOCK(drvdata->base);
>>
>> - if (!coresight_claim_device_unlocked(drvdata->base)) {
>> + if (WARN_ON(!csdev))
>> + return;
>
> I don't see a need for this check. Function replicator_reset() is called from
> probe() where the validity of drvdata->csdev is checked just before.
>

Correct. We only needed drvdata->base earlier, which was fine. But we
now need csdev for the reset. That check was added to make sure that
we don't break the guarantee. I could take that down.

Cheers
Suzuki

2020-11-05 20:57:21

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 14/26] coresight: etm4x: Add sysreg access helpers

On Wed, Oct 28, 2020 at 10:09:33PM +0000, Suzuki K Poulose wrote:
> ETMv4.4 architecture defines the system instructions for accessing
> ETM via register accesses. Add basic support for accessing a given
> register via system instructions.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 39 ++
> drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++--
> 2 files changed, 365 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 4af7d45dfe63..90b80982c615 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>
> static enum cpuhp_state hp_online;
>
> +u64 etm4x_sysreg_read(struct csdev_access *csa,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit)

Please fix the stacking.

> +{
> + u64 res = 0;
> +
> + switch (offset) {
> + ETM4x_READ_CASES(res)
> + default :
> + WARN_ONCE(1, "etm4x: trying to read unsupported register @%x\n",
> + offset);
> + }
> +
> + if (!_relaxed)
> + __iormb(res); /* Imitate the !relaxed I/O helpers */
> +
> + return res;
> +}
> +
> +void etm4x_sysreg_write(struct csdev_access *csa,
> + u64 val,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit)

Here too.

> +{
> + if (!_relaxed)
> + __iowmb(); /* Imitate the !relaxed I/O helpers */
> + if (!_64bit)
> + val &= GENMASK(31, 0);
> +
> + switch (offset) {
> + ETM4x_WRITE_CASES(val)
> + default :
> + WARN_ONCE(1, "etm4x: trying to write to unsupported register @%x\n",
> + offset);
> + }
> +}
> +
> static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
> {
> /* Writing 0 to TRCOSLAR unlocks the trace registers */
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 510828c73db6..5cf71b30a652 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -125,29 +125,323 @@
> #define TRCCIDR2 0xFF8
> #define TRCCIDR3 0xFFC
>
> -#define etm4x_relaxed_read32(csa, offset) \
> - readl_relaxed((csa)->base + (offset))
> -
> -#define etm4x_read32(csa, offset) \
> - readl((csa)->base + (offset))
> -
> -#define etm4x_relaxed_write32(csa, val, offset) \
> - writel_relaxed((val), (csa)->base + (offset))
> -
> -#define etm4x_write32(csa, val, offset) \
> - writel((val), (csa)->base + (offset))
> -
> -#define etm4x_relaxed_read64(csa, offset) \
> - readq_relaxed((csa)->base + (offset))
> -
> -#define etm4x_read64(csa, offset) \
> - readq((csa)->base + (offset))
> -
> -#define etm4x_relaxed_write64(csa, val, offset) \
> - writeq_relaxed((val), (csa)->base + (offset))
> +/*
> + * System instructions to access ETM registers.
> + * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
> + */
> +#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2)
> +
> +#define ETM4x_CRn(n) (((n) >> 7) & 0x7)
> +#define ETM4x_Op2(n) (((n) >> 4) & 0x7)
> +#define ETM4x_CRm(n) ((n) & 0xf)
> +
> +#include <asm/sysreg.h>
> +#define ETM4x_REG_NUM_TO_SYSREG(n) \
> + sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n))
> +
> +#define READ_ETM4x_REG(reg) \
> + read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg)))
> +#define WRITE_ETM4x_REG(val, reg) \
> + write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg)))
> +
> +#define read_etm4x_sysreg_const_offset(offset) \
> + READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset))
> +
> +#define write_etm4x_sysreg_const_offset(val, offset) \
> + WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset))
> +
> +#define CASE_READ(res, x) \
> + case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
> +
> +#define CASE_WRITE(val, x) \
> + case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; }
> +
> +#define CASE_LIST(op, val) \
> + CASE_##op((val), TRCPRGCTLR) \
> + CASE_##op((val), TRCPROCSELR) \
> + CASE_##op((val), TRCSTATR) \
> + CASE_##op((val), TRCCONFIGR) \
> + CASE_##op((val), TRCAUXCTLR) \
> + CASE_##op((val), TRCEVENTCTL0R) \
> + CASE_##op((val), TRCEVENTCTL1R) \
> + CASE_##op((val), TRCSTALLCTLR) \
> + CASE_##op((val), TRCTSCTLR) \
> + CASE_##op((val), TRCSYNCPR) \
> + CASE_##op((val), TRCCCCTLR) \
> + CASE_##op((val), TRCBBCTLR) \
> + CASE_##op((val), TRCTRACEIDR) \
> + CASE_##op((val), TRCQCTLR) \
> + CASE_##op((val), TRCVICTLR) \
> + CASE_##op((val), TRCVIIECTLR) \
> + CASE_##op((val), TRCVISSCTLR) \
> + CASE_##op((val), TRCVIPCSSCTLR) \
> + CASE_##op((val), TRCVDCTLR) \
> + CASE_##op((val), TRCVDSACCTLR) \
> + CASE_##op((val), TRCVDARCCTLR) \
> + CASE_##op((val), TRCSEQEVRn(0)) \
> + CASE_##op((val), TRCSEQEVRn(1)) \
> + CASE_##op((val), TRCSEQEVRn(2)) \
> + CASE_##op((val), TRCSEQRSTEVR) \
> + CASE_##op((val), TRCSEQSTR) \
> + CASE_##op((val), TRCEXTINSELR) \
> + CASE_##op((val), TRCCNTRLDVRn(0)) \
> + CASE_##op((val), TRCCNTRLDVRn(1)) \
> + CASE_##op((val), TRCCNTRLDVRn(2)) \
> + CASE_##op((val), TRCCNTRLDVRn(3)) \
> + CASE_##op((val), TRCCNTCTLRn(0)) \
> + CASE_##op((val), TRCCNTCTLRn(1)) \
> + CASE_##op((val), TRCCNTCTLRn(2)) \
> + CASE_##op((val), TRCCNTCTLRn(3)) \
> + CASE_##op((val), TRCCNTVRn(0)) \
> + CASE_##op((val), TRCCNTVRn(1)) \
> + CASE_##op((val), TRCCNTVRn(2)) \
> + CASE_##op((val), TRCCNTVRn(3)) \
> + CASE_##op((val), TRCIDR8) \
> + CASE_##op((val), TRCIDR9) \
> + CASE_##op((val), TRCIDR10) \
> + CASE_##op((val), TRCIDR11) \
> + CASE_##op((val), TRCIDR12) \
> + CASE_##op((val), TRCIDR13) \
> + CASE_##op((val), TRCIMSPECn(0)) \
> + CASE_##op((val), TRCIMSPECn(1)) \
> + CASE_##op((val), TRCIMSPECn(2)) \
> + CASE_##op((val), TRCIMSPECn(3)) \
> + CASE_##op((val), TRCIMSPECn(4)) \
> + CASE_##op((val), TRCIMSPECn(5)) \
> + CASE_##op((val), TRCIMSPECn(6)) \
> + CASE_##op((val), TRCIMSPECn(7)) \
> + CASE_##op((val), TRCIDR0) \
> + CASE_##op((val), TRCIDR1) \
> + CASE_##op((val), TRCIDR2) \
> + CASE_##op((val), TRCIDR3) \
> + CASE_##op((val), TRCIDR4) \
> + CASE_##op((val), TRCIDR5) \
> + CASE_##op((val), TRCIDR6) \
> + CASE_##op((val), TRCIDR7) \
> + CASE_##op((val), TRCRSCTLRn(2)) \
> + CASE_##op((val), TRCRSCTLRn(3)) \
> + CASE_##op((val), TRCRSCTLRn(4)) \
> + CASE_##op((val), TRCRSCTLRn(5)) \
> + CASE_##op((val), TRCRSCTLRn(6)) \
> + CASE_##op((val), TRCRSCTLRn(7)) \
> + CASE_##op((val), TRCRSCTLRn(8)) \
> + CASE_##op((val), TRCRSCTLRn(9)) \
> + CASE_##op((val), TRCRSCTLRn(10)) \
> + CASE_##op((val), TRCRSCTLRn(11)) \
> + CASE_##op((val), TRCRSCTLRn(12)) \
> + CASE_##op((val), TRCRSCTLRn(13)) \
> + CASE_##op((val), TRCRSCTLRn(14)) \
> + CASE_##op((val), TRCRSCTLRn(15)) \
> + CASE_##op((val), TRCRSCTLRn(16)) \
> + CASE_##op((val), TRCRSCTLRn(17)) \
> + CASE_##op((val), TRCRSCTLRn(18)) \
> + CASE_##op((val), TRCRSCTLRn(19)) \
> + CASE_##op((val), TRCRSCTLRn(20)) \
> + CASE_##op((val), TRCRSCTLRn(21)) \
> + CASE_##op((val), TRCRSCTLRn(22)) \
> + CASE_##op((val), TRCRSCTLRn(23)) \
> + CASE_##op((val), TRCRSCTLRn(24)) \
> + CASE_##op((val), TRCRSCTLRn(25)) \
> + CASE_##op((val), TRCRSCTLRn(26)) \
> + CASE_##op((val), TRCRSCTLRn(27)) \
> + CASE_##op((val), TRCRSCTLRn(28)) \
> + CASE_##op((val), TRCRSCTLRn(29)) \
> + CASE_##op((val), TRCRSCTLRn(30)) \
> + CASE_##op((val), TRCRSCTLRn(31)) \
> + CASE_##op((val), TRCSSCCRn(0)) \
> + CASE_##op((val), TRCSSCCRn(1)) \
> + CASE_##op((val), TRCSSCCRn(2)) \
> + CASE_##op((val), TRCSSCCRn(3)) \
> + CASE_##op((val), TRCSSCCRn(4)) \
> + CASE_##op((val), TRCSSCCRn(5)) \
> + CASE_##op((val), TRCSSCCRn(6)) \
> + CASE_##op((val), TRCSSCCRn(7)) \
> + CASE_##op((val), TRCSSCSRn(0)) \
> + CASE_##op((val), TRCSSCSRn(1)) \
> + CASE_##op((val), TRCSSCSRn(2)) \
> + CASE_##op((val), TRCSSCSRn(3)) \
> + CASE_##op((val), TRCSSCSRn(4)) \
> + CASE_##op((val), TRCSSCSRn(5)) \
> + CASE_##op((val), TRCSSCSRn(6)) \
> + CASE_##op((val), TRCSSCSRn(7)) \
> + CASE_##op((val), TRCSSPCICRn(0)) \
> + CASE_##op((val), TRCSSPCICRn(1)) \
> + CASE_##op((val), TRCSSPCICRn(2)) \
> + CASE_##op((val), TRCSSPCICRn(3)) \
> + CASE_##op((val), TRCSSPCICRn(4)) \
> + CASE_##op((val), TRCSSPCICRn(5)) \
> + CASE_##op((val), TRCSSPCICRn(6)) \
> + CASE_##op((val), TRCSSPCICRn(7)) \
> + CASE_##op((val), TRCOSLAR) \
> + CASE_##op((val), TRCOSLSR) \
> + CASE_##op((val), TRCPDCR) \
> + CASE_##op((val), TRCPDSR) \
> + CASE_##op((val), TRCACVRn(0)) \
> + CASE_##op((val), TRCACVRn(1)) \
> + CASE_##op((val), TRCACVRn(2)) \
> + CASE_##op((val), TRCACVRn(3)) \
> + CASE_##op((val), TRCACVRn(4)) \
> + CASE_##op((val), TRCACVRn(5)) \
> + CASE_##op((val), TRCACVRn(6)) \
> + CASE_##op((val), TRCACVRn(7)) \
> + CASE_##op((val), TRCACVRn(8)) \
> + CASE_##op((val), TRCACVRn(9)) \
> + CASE_##op((val), TRCACVRn(10)) \
> + CASE_##op((val), TRCACVRn(11)) \
> + CASE_##op((val), TRCACVRn(12)) \
> + CASE_##op((val), TRCACVRn(13)) \
> + CASE_##op((val), TRCACVRn(14)) \
> + CASE_##op((val), TRCACVRn(15)) \
> + CASE_##op((val), TRCACATRn(0)) \
> + CASE_##op((val), TRCACATRn(1)) \
> + CASE_##op((val), TRCACATRn(2)) \
> + CASE_##op((val), TRCACATRn(3)) \
> + CASE_##op((val), TRCACATRn(4)) \
> + CASE_##op((val), TRCACATRn(5)) \
> + CASE_##op((val), TRCACATRn(6)) \
> + CASE_##op((val), TRCACATRn(7)) \
> + CASE_##op((val), TRCACATRn(8)) \
> + CASE_##op((val), TRCACATRn(9)) \
> + CASE_##op((val), TRCACATRn(10)) \
> + CASE_##op((val), TRCACATRn(11)) \
> + CASE_##op((val), TRCACATRn(12)) \
> + CASE_##op((val), TRCACATRn(13)) \
> + CASE_##op((val), TRCACATRn(14)) \
> + CASE_##op((val), TRCACATRn(15)) \
> + CASE_##op((val), TRCDVCVRn(0)) \
> + CASE_##op((val), TRCDVCVRn(1)) \
> + CASE_##op((val), TRCDVCVRn(2)) \
> + CASE_##op((val), TRCDVCVRn(3)) \
> + CASE_##op((val), TRCDVCVRn(4)) \
> + CASE_##op((val), TRCDVCVRn(5)) \
> + CASE_##op((val), TRCDVCVRn(6)) \
> + CASE_##op((val), TRCDVCVRn(7)) \
> + CASE_##op((val), TRCDVCMRn(0)) \
> + CASE_##op((val), TRCDVCMRn(1)) \
> + CASE_##op((val), TRCDVCMRn(2)) \
> + CASE_##op((val), TRCDVCMRn(3)) \
> + CASE_##op((val), TRCDVCMRn(4)) \
> + CASE_##op((val), TRCDVCMRn(5)) \
> + CASE_##op((val), TRCDVCMRn(6)) \
> + CASE_##op((val), TRCDVCMRn(7)) \
> + CASE_##op((val), TRCCIDCVRn(0)) \
> + CASE_##op((val), TRCCIDCVRn(1)) \
> + CASE_##op((val), TRCCIDCVRn(2)) \
> + CASE_##op((val), TRCCIDCVRn(3)) \
> + CASE_##op((val), TRCCIDCVRn(4)) \
> + CASE_##op((val), TRCCIDCVRn(5)) \
> + CASE_##op((val), TRCCIDCVRn(6)) \
> + CASE_##op((val), TRCCIDCVRn(7)) \
> + CASE_##op((val), TRCVMIDCVRn(0)) \
> + CASE_##op((val), TRCVMIDCVRn(1)) \
> + CASE_##op((val), TRCVMIDCVRn(2)) \
> + CASE_##op((val), TRCVMIDCVRn(3)) \
> + CASE_##op((val), TRCVMIDCVRn(4)) \
> + CASE_##op((val), TRCVMIDCVRn(5)) \
> + CASE_##op((val), TRCVMIDCVRn(6)) \
> + CASE_##op((val), TRCVMIDCVRn(7)) \
> + CASE_##op((val), TRCCIDCCTLR0) \
> + CASE_##op((val), TRCCIDCCTLR1) \
> + CASE_##op((val), TRCVMIDCCTLR0) \
> + CASE_##op((val), TRCVMIDCCTLR1) \
> + CASE_##op((val), TRCITCTRL) \
> + CASE_##op((val), TRCCLAIMSET) \
> + CASE_##op((val), TRCCLAIMCLR) \
> + CASE_##op((val), TRCDEVAFF0) \
> + CASE_##op((val), TRCDEVAFF1) \
> + CASE_##op((val), TRCLAR) \
> + CASE_##op((val), TRCLSR) \
> + CASE_##op((val), TRCAUTHSTATUS) \
> + CASE_##op((val), TRCDEVARCH) \
> + CASE_##op((val), TRCDEVID) \
> + CASE_##op((val), TRCDEVTYPE) \
> + CASE_##op((val), TRCPIDR4) \
> + CASE_##op((val), TRCPIDR5) \
> + CASE_##op((val), TRCPIDR6) \
> + CASE_##op((val), TRCPIDR7) \
> + CASE_##op((val), TRCPIDR0) \
> + CASE_##op((val), TRCPIDR1) \
> + CASE_##op((val), TRCPIDR2) \
> + CASE_##op((val), TRCPIDR3)
> +
> +#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res))
> +#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val))
> +
> +#define read_etm4x_sysreg_offset(csa, offset, _64bit) \
> + ({ \
> + u64 __val; \
> + \
> + if (__builtin_constant_p((offset))) \

Neat trick - I wonder how you stumbled on that one.


> + __val = read_etm4x_sysreg_const_offset((offset)); \
> + else \
> + __val = etm4x_sysreg_read((csa), (offset), \
> + true, _64bit); \
> + __val; \
> + })
> +
> +#define write_etm4x_sysreg_offset(csa, val, offset, _64bit) \
> + do { \
> + if (__builtin_constant_p((offset))) \
> + write_etm4x_sysreg_const_offset((val), \
> + (offset)); \
> + else \
> + etm4x_sysreg_write((csa), (val), (offset), \
> + true, _64bit); \
> + } while (0)
> +
> +
> +#define etm4x_relaxed_read32(csa, offset) \
> + ((u32)((csa)->io_mem ? \
> + readl_relaxed((csa)->base + (offset)) : \
> + read_etm4x_sysreg_offset((csa), (offset), false)))

Please add an extra new line - otherwise it is very hard to read.

> +#define etm4x_relaxed_read64(csa, offset) \
> + ((u64)((csa)->io_mem ? \
> + readq_relaxed((csa)->base + (offset)) : \
> + read_etm4x_sysreg_offset((csa), (offset), true)))

Here too.

> +#define etm4x_read32(csa, offset) \
> + ({ \
> + u32 __val = etm4x_relaxed_read32((csa), (offset)); \
> + __iormb(__val); \
> + __val; \
> + })
> +
> +#define etm4x_read64(csa, offset) \
> + ({ \
> + u64 __val = etm4x_relaxed_read64((csa), (offset)); \
> + __iormb(__val); \
> + __val; \
> + })
> +
> +#define etm4x_relaxed_write32(csa, val, offset) \
> + do { \
> + if ((csa)->io_mem) \
> + writel_relaxed((val), (csa)->base + (offset)); \
> + else \
> + write_etm4x_sysreg_offset((csa), (val), \
> + (offset), false); \

Why using an if/else statement and above the '?' condition marker? I would
really like a uniform approach. Otherwise the reader keeps looking for
something subtle when there isn't.

> + } while (0)
> +
> +#define etm4x_relaxed_write64(csa, val, offset) \
> + do { \
> + if ((csa)->io_mem) \
> + writeq_relaxed((val), (csa)->base + (offset)); \
> + else \
> + write_etm4x_sysreg_offset((csa), (val), \
> + (offset), true); \
> + } while (0)
> +
> +#define etm4x_write32(csa, val, offset) \
> + do { \
> + __iowmb(); \
> + etm4x_relaxed_write32((csa), (val), (offset)); \
> + } while (0)
> +
> +#define etm4x_write64(csa, val, offset) \
> + do { \
> + __iowmb(); \
> + etm4x_relaxed_write64((csa), (val), (offset)); \
> + } while (0)
>
> -#define etm4x_write64(csa, val, offset) \
> - writeq((val), (csa)->base + (offset))
>
> /* ETMv4 resources */
> #define ETM_MAX_NR_PE 8
> @@ -512,4 +806,14 @@ enum etm_addr_ctxtype {
>
> extern const struct attribute_group *coresight_etmv4_groups[];
> void etm4_config_trace_mode(struct etmv4_config *config);
> +
> +u64 etm4x_sysreg_read(struct csdev_access *csa,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit);
> +void etm4x_sysreg_write(struct csdev_access *csa,
> + u64 val,
> + u32 offset,
> + bool _relaxed,
> + bool _64bit);

With the above:

Reviewed-by: Mathieu Poirier <[email protected]>

This patch holds together well. I commend you on rendering something that is
quite complex into a manageable implementation. That being said it will impact
Mike's complex configuration patchset (or Mike's complex configuration patchset
will have an impact on this).

> #endif
> --
> 2.24.1
>

2020-11-05 21:53:07

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 16/26] coresight: etm4x: Check for Software Lock

On Wed, Oct 28, 2020 at 10:09:35PM +0000, Suzuki K Poulose wrote:
> The Software lock is not implemented for system instructions
> based accesses. So, skip the lock register access in such
> cases.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 40 ++++++++++++-------
> 1 file changed, 25 insertions(+), 15 deletions(-)
>

Reviewed-by: Mathieu Poirier <[email protected]>

> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index a5c914b16e59..a12d58a04c5d 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -121,6 +121,21 @@ static void etm4_os_lock(struct etmv4_drvdata *drvdata)
> isb();
> }
>
> +static void etm4_cs_lock(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + /* Software Lock is only accessible via memory mapped interface */
> + if (csa->io_mem)
> + CS_LOCK(csa->base);
> +}
> +
> +static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + if (csa->io_mem)
> + CS_UNLOCK(csa->base);
> +}
> +
> static bool etm4_arch_supported(u8 arch)
> {
> /* Mask out the minor version number */
> @@ -160,8 +175,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> struct device *etm_dev = &csdev->dev;
> struct csdev_access *csa = &csdev->access;
>
> - CS_UNLOCK(drvdata->base);
> -
> + etm4_cs_unlock(drvdata, csa);
> etm4_os_unlock(drvdata);
>
> rc = coresight_claim_device_unlocked(csdev);
> @@ -262,7 +276,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> isb();
>
> done:
> - CS_LOCK(drvdata->base);
> + etm4_cs_lock(drvdata, csa);
>
> dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n",
> drvdata->cpu, rc);
> @@ -519,7 +533,7 @@ static void etm4_disable_hw(void *info)
> struct csdev_access *csa = &csdev->access;
> int i;
>
> - CS_UNLOCK(drvdata->base);
> + etm4_cs_unlock(drvdata, csa);
>
> if (!drvdata->skip_power_up) {
> /* power can be removed from the trace unit now */
> @@ -560,8 +574,7 @@ static void etm4_disable_hw(void *info)
> }
>
> coresight_disclaim_device_unlocked(csdev);
> -
> - CS_LOCK(drvdata->base);
> + etm4_cs_lock(drvdata, csa);
>
> dev_dbg(&drvdata->csdev->dev,
> "cpu: %d disable smp call done\n", drvdata->cpu);
> @@ -671,8 +684,7 @@ static void etm4_init_arch_data(void *info)
>
> /* Make sure all registers are accessible */
> etm4_os_unlock_csa(drvdata, csa);
> -
> - CS_UNLOCK(drvdata->base);
> + etm4_cs_unlock(drvdata, csa);
>
> /* find all capabilities of the tracing unit */
> etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
> @@ -837,7 +849,7 @@ static void etm4_init_arch_data(void *info)
> drvdata->nrseqstate = BMVAL(etmidr5, 25, 27);
> /* NUMCNTR, bits[30:28] number of counters available for tracing */
> drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
> - CS_LOCK(drvdata->base);
> + etm4_cs_lock(drvdata, csa);
> }
>
> /* Set ELx trace filter access in the TRCVICTLR register */
> @@ -1218,8 +1230,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> dsb(sy);
> isb();
>
> - CS_UNLOCK(drvdata->base);
> -
> + etm4_cs_unlock(drvdata, csa);
> /* Lock the OS lock to disable trace and external debugger access */
> etm4_os_lock(drvdata);
>
> @@ -1330,7 +1341,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
> etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
>
> out:
> - CS_LOCK(drvdata->base);
> + etm4_cs_lock(drvdata, csa);
> return ret;
> }
>
> @@ -1341,8 +1352,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
> struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> struct csdev_access *csa = &tmp_csa;
>
> - CS_UNLOCK(drvdata->base);
> -
> + etm4_cs_unlock(drvdata, csa);
> etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
>
> etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
> @@ -1426,7 +1436,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
>
> /* Unlock the OS lock to re-enable trace and external debug access */
> etm4_os_unlock(drvdata);
> - CS_LOCK(drvdata->base);
> + etm4_cs_lock(drvdata, csa);
> }
>
> static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
> --
> 2.24.1
>

2020-11-05 21:57:59

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 17/26] coresight: etm4x: Cleanup secure exception level masks

On Wed, Oct 28, 2020 at 10:09:36PM +0000, Suzuki K Poulose wrote:
> We rely on the ETM architecture version to decide whether
> Secure EL2 is available on the CPU for excluding the level
> for address comparators and viewinst main control register.
> We must instead use the TRCDIDR3.EXLEVEL_S field to detect
> the supported levels.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++----------
> drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++--
> 2 files changed, 7 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index a12d58a04c5d..6e3f9cb7de3f 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -733,7 +733,6 @@ static void etm4_init_arch_data(void *info)
> * TRCARCHMAJ, bits[11:8] architecture major versin number
> */
> drvdata->arch = BMVAL(etmidr1, 4, 11);
> - drvdata->config.arch = drvdata->arch;
>
> /* maximum size of resources */
> etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
> @@ -749,6 +748,7 @@ static void etm4_init_arch_data(void *info)
> drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
> /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
> drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
> + drvdata->config.s_ex_level = drvdata->s_ex_level;
> /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
> drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
>
> @@ -920,16 +920,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
> static u64 etm4_get_access_type(struct etmv4_config *config)
> {
> u64 access_type = etm4_get_ns_access_type(config);
> - u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
>
> - /*
> - * EXLEVEL_S, bits[11:8], don't trace anything happening
> - * in secure state.
> - */
> - access_type |= (ETM_EXLEVEL_S_APP |
> - ETM_EXLEVEL_S_OS |
> - s_hyp |
> - ETM_EXLEVEL_S_MON);
> + /* All supported secure ELs are excluded */
> + access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
>
> return access_type;
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index e7f6b7b16fb7..2ac4ecb0af61 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -546,6 +546,8 @@
> /* PowerDown Control Register bits */
> #define TRCPDCR_PU BIT(3)
>
> +#define TRCACATR_EXLEVEL_SHIFT 8
> +
> /* secure state access levels - TRCACATRn */
> #define ETM_EXLEVEL_S_APP BIT(8)
> #define ETM_EXLEVEL_S_OS BIT(9)
> @@ -615,7 +617,7 @@
> * @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.
> - * @arch: ETM architecture version (for arch dependent config).
> + * @s_ex_level: Secure ELs where tracing is supported.
> */
> struct etmv4_config {
> u32 mode;
> @@ -659,7 +661,7 @@ struct etmv4_config {
> u32 vmid_mask0;
> u32 vmid_mask1;
> u32 ext_inp;
> - u8 arch;
> + u8 s_ex_level;

Instead of making s_ex_level redundant I suggest to pass a struct etmv4_drvdata
to etm4_get_access_type().

More comments to come tomorrow.

Thanks,
Mathieu

> };
>
> /**
> --
> 2.24.1
>

2020-11-05 22:52:21

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 14/26] coresight: etm4x: Add sysreg access helpers

Hi Mathieu,

On 11/5/20 8:52 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:33PM +0000, Suzuki K Poulose wrote:
>> ETMv4.4 architecture defines the system instructions for accessing
>> ETM via register accesses. Add basic support for accessing a given
>> register via system instructions.
>>
>> Cc: Mathieu Poirier <[email protected]>
>> Cc: Mike Leach <[email protected]>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> .../coresight/coresight-etm4x-core.c | 39 ++
>> drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++--
>> 2 files changed, 365 insertions(+), 22 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index 4af7d45dfe63..90b80982c615 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>>
>> static enum cpuhp_state hp_online;
>>
>> +u64 etm4x_sysreg_read(struct csdev_access *csa,
>> + u32 offset,
>> + bool _relaxed,
>> + bool _64bit)
>
> Please fix the stacking.
>

Sure.


>> +
>> +void etm4x_sysreg_write(struct csdev_access *csa,
>> + u64 val,
>> + u32 offset,
>> + bool _relaxed,
>> + bool _64bit)
>
> Here too.

Sure.


>> /* Writing 0 to TRCOSLAR unlocks the trace registers */
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
>> index 510828c73db6..5cf71b30a652 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x.

>> +
>> +#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res))
>> +#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val))
>> +
>> +#define read_etm4x_sysreg_offset(csa, offset, _64bit) \
>> + ({ \
>> + u64 __val; \
>> + \
>> + if (__builtin_constant_p((offset))) \
>
> Neat trick - I wonder how you stumbled on that one.
>

:-). There are plenty of uses in the kernel and glibc.

>
>> + __val = read_etm4x_sysreg_const_offset((offset)); \
>> + else \
>> + __val = etm4x_sysreg_read((csa), (offset), \
>> + true, _64bit); \
>> + __val; \
>> + })
>> +
>> +#define write_etm4x_sysreg_offset(csa, val, offset, _64bit) \
>> + do { \
>> + if (__builtin_constant_p((offset))) \
>> + write_etm4x_sysreg_const_offset((val), \
>> + (offset)); \
>> + else \
>> + etm4x_sysreg_write((csa), (val), (offset), \
>> + true, _64bit); \
>> + } while (0)
>> +
>> +
>> +#define etm4x_relaxed_read32(csa, offset) \
>> + ((u32)((csa)->io_mem ? \
>> + readl_relaxed((csa)->base + (offset)) : \
>> + read_etm4x_sysreg_offset((csa), (offset), false)))
>
> Please add an extra new line - otherwise it is very hard to read.
>

Sure

>> +#define etm4x_relaxed_read64(csa, offset) \
>> + ((u64)((csa)->io_mem ? \
>> + readq_relaxed((csa)->base + (offset)) : \
>> + read_etm4x_sysreg_offset((csa), (offset), true)))
>
> Here too.
>

sure

>> +#define etm4x_read32(csa, offset) \
>> + ({ \
>> + u32 __val = etm4x_relaxed_read32((csa), (offset)); \
>> + __iormb(__val); \
>> + __val; \
>> + })
>> +
>> +#define etm4x_read64(csa, offset) \
>> + ({ \
>> + u64 __val = etm4x_relaxed_read64((csa), (offset)); \
>> + __iormb(__val); \
>> + __val; \
>> + })
>> +
>> +#define etm4x_relaxed_write32(csa, val, offset) \
>> + do { \
>> + if ((csa)->io_mem) \
>> + writel_relaxed((val), (csa)->base + (offset)); \
>> + else \
>> + write_etm4x_sysreg_offset((csa), (val), \
>> + (offset), false); \
>
> Why using an if/else statement and above the '?' condition marker? I would
> really like a uniform approach. Otherwise the reader keeps looking for
> something subtle when there isn't.

The write variants do not return a result, unlike the read.
So, we cant use the '?'

>
>> + } while (0)
>> +
>> +#define etm4x_relaxed_write64(csa, val, offset) \
>> + do { \
>> + if ((csa)->io_mem) \
>> + writeq_relaxed((val), (csa)->base + (offset)); \
>> + else \
>> + write_etm4x_sysreg_offset((csa), (val), \
>> + (offset), true); \
>> + } while (0)
>> +
>> +#define etm4x_write32(csa, val, offset) \
>> + do { \
>> + __iowmb(); \
>> + etm4x_relaxed_write32((csa), (val), (offset)); \
>> + } while (0)
>> +
>> +#define etm4x_write64(csa, val, offset) \
>> + do { \
>> + __iowmb(); \
>> + etm4x_relaxed_write64((csa), (val), (offset)); \
>> + } while (0)
>>
>> -#define etm4x_write64(csa, val, offset) \
>> - writeq((val), (csa)->base + (offset))
>>
>> /* ETMv4 resources */
>> #define ETM_MAX_NR_PE 8
>> @@ -512,4 +806,14 @@ enum etm_addr_ctxtype {
>>
>> extern const struct attribute_group *coresight_etmv4_groups[];
>> void etm4_config_trace_mode(struct etmv4_config *config);
>> +
>> +u64 etm4x_sysreg_read(struct csdev_access *csa,
>> + u32 offset,
>> + bool _relaxed,
>> + bool _64bit);
>> +void etm4x_sysreg_write(struct csdev_access *csa,
>> + u64 val,
>> + u32 offset,
>> + bool _relaxed,
>> + bool _64bit);
>
> With the above:
>
> Reviewed-by: Mathieu Poirier <[email protected]>

Thanks !

>
> This patch holds together well. I commend you on rendering something that is
> quite complex into a manageable implementation. That being said it will impact
> Mike's complex configuration patchset (or Mike's complex configuration patchset
> will have an impact on this).

I understand. Will see when we get to it.

Cheers
Suzuki

2020-11-06 18:55:00

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 18/26] coresight: etm4x: Clean up exception level masks

Good morning,

On Wed, Oct 28, 2020 at 10:09:37PM +0000, Suzuki K Poulose wrote:
> etm4_get_access_type() calculates the exception level bits
> for use in address comparator registers. This is also used
> by the TRCVICTLR register by shifting to the required position.
>
> This patch cleans up the logic to make etm4_get_access_type()
> calcualte a generic mask which can be used by all users by
> shifting to their field.
>
> No functional changes, only code cleanups.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> Changes since previous version:
> - Fix the duplicate shift. More commentary
> ---
> .../coresight/coresight-etm4x-core.c | 47 +++++++++----------
> .../coresight/coresight-etm4x-sysfs.c | 12 ++---
> drivers/hwtracing/coresight/coresight-etm4x.h | 46 +++++++++++-------
> 3 files changed, 59 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 6e3f9cb7de3f..f038bb10bc78 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -852,20 +852,16 @@ static void etm4_init_arch_data(void *info)
> etm4_cs_lock(drvdata, csa);
> }
>
> +static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
> +{
> + return etm4_get_access_type(config) << TRCVICTLR_EXLEVEL_SHIFT;
> +}
> +
> /* Set ELx trace filter access in the TRCVICTLR register */
> static void etm4_set_victlr_access(struct etmv4_config *config)
> {
> - u64 access_type;
> -
> - config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK | ETM_EXLEVEL_NS_VICTLR_MASK);
> -
> - /*
> - * TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering
> - * bits in vinst_ctrl, same bit pattern as TRCACATRn values returned by
> - * etm4_get_access_type() but with a relative shift in this register.
> - */
> - access_type = etm4_get_access_type(config) << ETM_EXLEVEL_LSHIFT_TRCVICTLR;
> - config->vinst_ctrl |= (u32)access_type;
> + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK | TRCVICTLR_EXLEVEL_NS_MASK);
> + config->vinst_ctrl |= etm4_get_victlr_access_type(config);
> }
>
> static void etm4_set_default_config(struct etmv4_config *config)
> @@ -895,12 +891,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
> u64 access_type = 0;
>
> /*
> - * EXLEVEL_NS, bits[15:12]
> - * The Exception levels are:
> - * Bit[12] Exception level 0 - Application
> - * Bit[13] Exception level 1 - OS
> - * Bit[14] Exception level 2 - Hypervisor
> - * Bit[15] Never implemented
> + * EXLEVEL_NS, for NonSecure Exception levels.
> + * The mask here is a generic value and must be
> + * shifted to the corresponding field for the registers
> */
> if (!is_kernel_in_hyp_mode()) {
> /* Stay away from hypervisor mode for non-VHE */
> @@ -917,20 +910,26 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
> return access_type;
> }
>
> +/*
> + * Construct the exception level masks for a given config.
> + * This must be shifted to the corresponding register field
> + * for usage.
> + */
> static u64 etm4_get_access_type(struct etmv4_config *config)
> {
> - u64 access_type = etm4_get_ns_access_type(config);
> -
> - /* All supported secure ELs are excluded */
> - access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
> + /* All Secure exception levels are excluded from the trace */
> + return etm4_get_ns_access_type(config) | (u64)config->s_ex_level;
> +}
>
> - return access_type;
> +static u64 etm4_get_comparator_access_type(struct etmv4_config *config)
> +{
> + return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT;
> }
>
> static void etm4_set_comparator_filter(struct etmv4_config *config,
> u64 start, u64 stop, int comparator)
> {
> - u64 access_type = etm4_get_access_type(config);
> + u64 access_type = etm4_get_comparator_access_type(config);
>
> /* First half of default address comparator */
> config->addr_val[comparator] = start;
> @@ -965,7 +964,7 @@ static void etm4_set_start_stop_filter(struct etmv4_config *config,
> enum etm_addr_type type)
> {
> int shift;
> - u64 access_type = etm4_get_access_type(config);
> + u64 access_type = etm4_get_comparator_access_type(config);
>
> /* Configure the comparator */
> config->addr_val[comparator] = address;
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> index fce9df16bfb5..009818675928 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
> @@ -743,7 +743,7 @@ static ssize_t s_exlevel_vinst_show(struct device *dev,
> struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> struct etmv4_config *config = &drvdata->config;
>
> - val = (config->vinst_ctrl & ETM_EXLEVEL_S_VICTLR_MASK) >> 16;
> + val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_S_MASK) >> TRCVICTLR_EXLEVEL_S_SHIFT;
> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
> }
>
> @@ -760,10 +760,10 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
>
> spin_lock(&drvdata->spinlock);
> /* clear all EXLEVEL_S bits */
> - config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK);
> + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK);
> /* enable instruction tracing for corresponding exception level */
> val &= drvdata->s_ex_level;
> - config->vinst_ctrl |= (val << 16);
> + config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_S_SHIFT);
> spin_unlock(&drvdata->spinlock);
> return size;
> }
> @@ -778,7 +778,7 @@ static ssize_t ns_exlevel_vinst_show(struct device *dev,
> struct etmv4_config *config = &drvdata->config;
>
> /* EXLEVEL_NS, bits[23:20] */
> - val = (config->vinst_ctrl & ETM_EXLEVEL_NS_VICTLR_MASK) >> 20;
> + val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_NS_MASK) >> TRCVICTLR_EXLEVEL_NS_SHIFT;
> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
> }
>
> @@ -795,10 +795,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
>
> spin_lock(&drvdata->spinlock);
> /* clear EXLEVEL_NS bits */
> - config->vinst_ctrl &= ~(ETM_EXLEVEL_NS_VICTLR_MASK);
> + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK);
> /* enable instruction tracing for corresponding exception level */
> val &= drvdata->ns_ex_level;
> - config->vinst_ctrl |= (val << 20);
> + config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT);
> spin_unlock(&drvdata->spinlock);
> return size;
> }
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index 2ac4ecb0af61..f1251ddf1984 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -548,24 +548,38 @@
>
> #define TRCACATR_EXLEVEL_SHIFT 8
>
> -/* secure state access levels - TRCACATRn */
> -#define ETM_EXLEVEL_S_APP BIT(8)
> -#define ETM_EXLEVEL_S_OS BIT(9)
> -#define ETM_EXLEVEL_S_HYP BIT(10)
> -#define ETM_EXLEVEL_S_MON BIT(11)
> -/* non-secure state access levels - TRCACATRn */
> -#define ETM_EXLEVEL_NS_APP BIT(12)
> -#define ETM_EXLEVEL_NS_OS BIT(13)
> -#define ETM_EXLEVEL_NS_HYP BIT(14)
> -#define ETM_EXLEVEL_NS_NA BIT(15)
> -
> -/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */
> -#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8
> +/*
> + * Exception level mask for Secure and Non-Secure ELs.
> + * ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn).
> + * The Secure and Non-Secure ELs are always to gether.
> + * Non-secure EL3 is never implemented.
> + * We use the following generic mask as they appear in different
> + * registers and this can be shifted for the appropriate
> + * fields.
> + */
> +#define ETM_EXLEVEL_S_APP BIT(0) /* Secure EL0 */
> +#define ETM_EXLEVEL_S_OS BIT(1) /* Secure EL1 */
> +#define ETM_EXLEVEL_S_HYP BIT(2) /* Secure EL2 */
> +#define ETM_EXLEVEL_S_MON BIT(3) /* Secure EL3/Montor */

s/Montor/Monitor

> +#define ETM_EXLEVEL_NS_APP BIT(4) /* NonSecure EL0 */
> +#define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */
> +#define ETM_EXLEVEL_NS_HYP BIT(6) /* NonSecure EL2 */
> +
> +#define ETM_EXLEVEL_MASK (GENMASK(6, 0))

Not used.

> +#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0))
> +#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4))

This needs to be GENMASK(2, 0) in order TRCVICTLR_EXLEVEL_NS_SHIFT to be 20.
Otherwise the resulting mask is 4 bit off to the left.

> +
> +/* access level controls in TRCACATRn */
> +#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 ETM_EXLEVEL_S_VICTLR_MASK GENMASK(19, 16)
> -/* NS MON (EL3) mode never implemented */
> -#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
> +#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
> +#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)
>
> /* Interpretation of resource numbers change at ETM v4.3 architecture */
> #define ETM4X_ARCH_4V3 0x43
> --
> 2.24.1
>

2020-11-06 20:36:31

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

On Wed, Oct 28, 2020 at 10:09:38PM +0000, Suzuki K Poulose wrote:
> In preparation to detect the support for system instruction
> support, move the detection of the device access to the target
> CPU.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
> 1 file changed, 40 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index f038bb10bc78..308674ab746c 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>
> static enum cpuhp_state hp_online;
>
> +struct etm_init_arg {

s/etm_init_arg/etm4_init_arg

> + struct etmv4_drvdata *drvdata;
> + struct csdev_access *csa;
> +};
> +
> u64 etm4x_sysreg_read(struct csdev_access *csa,
> u32 offset,
> bool _relaxed,
> @@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
> .source_ops = &etm4_source_ops,
> };
>
> +static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> + return true;
> +}
> +
> +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + if (drvdata->base)
> + return etm_init_iomem_access(drvdata, csa);
> +
> + return false;
> +}

Returning a boolean rather than an int for the above two functions seems odd to
me.

> +
> static void etm4_init_arch_data(void *info)
> {
> u32 etmidr0;
> @@ -677,11 +698,22 @@ static void etm4_init_arch_data(void *info)
> u32 etmidr3;
> u32 etmidr4;
> u32 etmidr5;
> - struct etmv4_drvdata *drvdata = info;
> - struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> - struct csdev_access *csa = &tmp_csa;
> + struct etm_init_arg *init_arg = info;
> + struct etmv4_drvdata *drvdata;
> + struct csdev_access *csa;
> int i;
>
> + drvdata = init_arg->drvdata;
> + csa = init_arg->csa;
> +
> + /*
> + * If we are unable to detect the access mechanism,
> + * or unable to detect the trace unit type, fail
> + * early.
> + */
> + if (!etm_init_csdev_access(drvdata, csa))
> + return;
> +
> /* Make sure all registers are accessible */
> etm4_os_unlock_csa(drvdata, csa);
> etm4_cs_unlock(drvdata, csa);
> @@ -1524,6 +1556,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> struct etmv4_drvdata *drvdata;
> struct resource *res = &adev->res;
> struct coresight_desc desc = { 0 };
> + struct etm_init_arg init_arg = { 0 };
>
> drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> if (!drvdata)
> @@ -1551,7 +1584,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> return PTR_ERR(base);
>
> drvdata->base = base;
> - desc.access = CSDEV_ACCESS_IOMEM(base);
>
> spin_lock_init(&drvdata->spinlock);
>
> @@ -1563,8 +1595,11 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> if (!desc.name)
> return -ENOMEM;
>
> + init_arg.drvdata = drvdata;
> + init_arg.csa = &desc.access;
> +
> if (smp_call_function_single(drvdata->cpu,
> - etm4_init_arch_data, drvdata, 1))
> + etm4_init_arch_data, &init_arg, 1))
> dev_err(dev, "ETM arch init failed\n");
>
> if (etm4_arch_supported(drvdata->arch) == false)
> --
> 2.24.1
>

2020-11-06 20:48:43

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

On Wed, Oct 28, 2020 at 10:09:38PM +0000, Suzuki K Poulose wrote:
> In preparation to detect the support for system instruction
> support, move the detection of the device access to the target
> CPU.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
> 1 file changed, 40 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index f038bb10bc78..308674ab746c 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>
> static enum cpuhp_state hp_online;
>
> +struct etm_init_arg {
> + struct etmv4_drvdata *drvdata;
> + struct csdev_access *csa;
> +};
> +
> u64 etm4x_sysreg_read(struct csdev_access *csa,
> u32 offset,
> bool _relaxed,
> @@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
> .source_ops = &etm4_source_ops,
> };
>
> +static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> + return true;
> +}
> +
> +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
> + struct csdev_access *csa)
> +{
> + if (drvdata->base)
> + return etm_init_iomem_access(drvdata, csa);
> +
> + return false;
> +}

I would also prefix the above two functions with "etm4_" rather than "etm_" to
follow what is already done in this file.

> +
> static void etm4_init_arch_data(void *info)
> {
> u32 etmidr0;
> @@ -677,11 +698,22 @@ static void etm4_init_arch_data(void *info)
> u32 etmidr3;
> u32 etmidr4;
> u32 etmidr5;
> - struct etmv4_drvdata *drvdata = info;
> - struct csdev_access tmp_csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> - struct csdev_access *csa = &tmp_csa;
> + struct etm_init_arg *init_arg = info;
> + struct etmv4_drvdata *drvdata;
> + struct csdev_access *csa;
> int i;
>
> + drvdata = init_arg->drvdata;
> + csa = init_arg->csa;
> +
> + /*
> + * If we are unable to detect the access mechanism,
> + * or unable to detect the trace unit type, fail
> + * early.
> + */
> + if (!etm_init_csdev_access(drvdata, csa))
> + return;
> +
> /* Make sure all registers are accessible */
> etm4_os_unlock_csa(drvdata, csa);
> etm4_cs_unlock(drvdata, csa);
> @@ -1524,6 +1556,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> struct etmv4_drvdata *drvdata;
> struct resource *res = &adev->res;
> struct coresight_desc desc = { 0 };
> + struct etm_init_arg init_arg = { 0 };
>
> drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> if (!drvdata)
> @@ -1551,7 +1584,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> return PTR_ERR(base);
>
> drvdata->base = base;
> - desc.access = CSDEV_ACCESS_IOMEM(base);
>
> spin_lock_init(&drvdata->spinlock);
>
> @@ -1563,8 +1595,11 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> if (!desc.name)
> return -ENOMEM;
>
> + init_arg.drvdata = drvdata;
> + init_arg.csa = &desc.access;
> +
> if (smp_call_function_single(drvdata->cpu,
> - etm4_init_arch_data, drvdata, 1))
> + etm4_init_arch_data, &init_arg, 1))
> dev_err(dev, "ETM arch init failed\n");
>
> if (etm4_arch_supported(drvdata->arch) == false)
> --
> 2.24.1
>

2020-11-06 21:13:34

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 20/26] coresight: etm4x: Handle ETM architecture version

On Wed, Oct 28, 2020 at 10:09:39PM +0000, Suzuki K Poulose wrote:
> We are about to rely on TRCDEVARCH for detecting the ETM
> and its architecture version, falling back to TRCIDR1 if
> the former is not implemented (in older broken implementations).
>
> Also, we use the architecture version information to do
> make some decisions. Streamline the architecture version
> handling by adding helpers.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 2 +-
> drivers/hwtracing/coresight/coresight-etm4x.h | 60 ++++++++++++++++++-
> 2 files changed, 58 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 308674ab746c..4ef47a2946a4 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -842,7 +842,7 @@ static void etm4_init_arch_data(void *info)
> * Otherwise for values 0x1 and above the number is N + 1 as per v4.2.
> */
> drvdata->nr_resource = BMVAL(etmidr4, 16, 19);
> - if ((drvdata->arch < ETM4X_ARCH_4V3) || (drvdata->nr_resource > 0))
> + if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0))
> drvdata->nr_resource += 1;
> /*
> * NUMSSCC, bits[23:20] the number of single-shot
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> index f1251ddf1984..fe7107282e54 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> @@ -459,7 +459,6 @@
> #define ETM_MAX_RES_SEL 32
> #define ETM_MAX_SS_CMP 8
>
> -#define ETM_ARCH_V4 0x40
> #define ETMv4_SYNC_MASK 0x1F
> #define ETM_CYC_THRESHOLD_MASK 0xFFF
> #define ETM_CYC_THRESHOLD_DEFAULT 0x100
> @@ -581,8 +580,63 @@
> #define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
> #define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)
>
> +#define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8
> +#define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
> +#define ETM_TRCIDR1_ARCH_MAJOR(x) \
> + (((x) & ETM_TRCIDR1_ARCH_MAJOR_MASK) >> ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
> +#define ETM_TRCIDR1_ARCH_MINOR_SHIFT 4
> +#define ETM_TRCIDR1_ARCH_MINOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MINOR_SHIFT)
> +#define ETM_TRCIDR1_ARCH_MINOR(x) \
> + (((x) & ETM_TRCIDR1_ARCH_MINOR_MASK) >> ETM_TRCIDR1_ARCH_MINOR_SHIFT)
> +#define ETM_TRCIDR1_ARCH_SHIFT ETM_TRCIDR1_ARCH_MINOR_SHIFT
> +#define ETM_TRCIDR1_ARCH_MASK \
> + (ETM_TRCIDR1_ARCH_MAJOR_MASK | ETM_TRCIDR1_ARCH_MINOR_MASK)
> +
> +#define ETM_TRCIDR1_ARCH_ETMv4 0x4
> +
> +/*
> + * Driver representation of the ETM architecture.
> + * The version of an ETM component can be detected from
> + *
> + * TRCDEVARCH - CoreSight architected register
> + * - Bits[15:12] - Major version
> + * - Bits[19:16] - Minor version
> + * TRCIDR1 - ETM architected register
> + * - Bits[12:8] - Major version

This should be [11:8], bit 12 is part of RES1.

> + * - Bits[7:4] - Minor version
> + * We must rely on TRCDEVARCH for the version information,
> + * however we don't want to break the support for potential
> + * old implementations which might not implement it. Thus
> + * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
> + * for memory mapped components.
> + * Now to make certain decisions easier based on the version
> + * we use an internal representation of the version in the
> + * driver, as follows :
> + *
> + * ETM_ARCH_VERSION[7:0], where :
> + * Bits[7:4] - Major version
> + * Bits[3:0] - Minro version
> + */
> +#define ETM_ARCH_VERSION(major, minor) \
> + ((((major) & 0xfU) << 4) | (((minor) & 0xfU)))
> +#define ETM_ARCH_MAJOR_VERSION(arch) (((arch) >> 4) & 0xfU)
> +#define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU)

There are a few unused defines brought in by this patch. I trust they will be
used in subsequent patches.

> +
> +#define ETM_ARCH_V4 ETM_ARCH_VERSION(4, 0)
> /* Interpretation of resource numbers change at ETM v4.3 architecture */
> -#define ETM4X_ARCH_4V3 0x43
> +#define ETM_ARCH_V4_3 ETM_ARCH_VERSION(4, 3)
> +
> +static inline u8 etm_devarch_to_arch(u32 devarch)
> +{
> + return ETM_ARCH_VERSION(ETM_DEVARCH_ARCHID_ARCH_VER(devarch),
> + ETM_DEVARCH_REVISION(devarch));
> +}
> +
> +static inline u8 etm_trcidr_to_arch(u32 trcidr1)
> +{
> + return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
> + ETM_TRCIDR1_ARCH_MINOR(trcidr1));
> +}
>
> /**
> * struct etmv4_config - configuration information related to an ETMv4
> @@ -744,7 +798,7 @@ struct etmv4_save_state {
> * @spinlock: Only one at a time pls.
> * @mode: This tracer's mode, i.e sysFS, Perf or disabled.
> * @cpu: The cpu this component is affined to.
> - * @arch: ETM version number.
> + * @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.
> --
> 2.24.1
>

2020-11-06 21:46:17

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 21/26] coresight: etm4x: Use TRCDEVARCH for component discovery

On Wed, Oct 28, 2020 at 10:09:40PM +0000, Suzuki K Poulose wrote:
> We have been using TRCIDR1 for detecting the ETM version. This
> is in preparation for the future IP support.
>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 46 +++++++++----------
> 1 file changed, 23 insertions(+), 23 deletions(-)

Reviewed-by: Mathieu Poirier <[email protected]>

I'm out of time for today, I will resume on Monday.

Thanks,
Mathieu

>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 4ef47a2946a4..e36bc1c722c7 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -141,18 +141,6 @@ static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
> CS_UNLOCK(csa->base);
> }
>
> -static bool etm4_arch_supported(u8 arch)
> -{
> - /* Mask out the minor version number */
> - switch (arch & 0xf0) {
> - case ETM_ARCH_V4:
> - break;
> - default:
> - return false;
> - }
> - return true;
> -}
> -
> static int etm4_cpu_id(struct coresight_device *csdev)
> {
> struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> @@ -677,6 +665,26 @@ static const struct coresight_ops etm4_cs_ops = {
> static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
> struct csdev_access *csa)
> {
> + u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
> + u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);
> +
> + /*
> + * All ETMs must implement TRCDEVARCH to indicate that
> + * the component is an ETMv4. To support any broken
> + * implementations we fall back to TRCIDR1 check, which
> + * is not really reliable.
> + */
> + if ((devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH) {
> + drvdata->arch = etm_devarch_to_arch(devarch);
> + } else {
> + pr_warn("CPU%d: ETM4x incompatible TRCDEVARCH: %x, falling back to TRCIDR1\n",
> + smp_processor_id(), devarch);
> +
> + if (ETM_TRCIDR1_ARCH_MAJOR(idr1) != ETM_TRCIDR1_ARCH_ETMv4)
> + return false;
> + drvdata->arch = etm_trcidr_to_arch(idr1);
> + }
> +
> *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> return true;
> }
> @@ -693,7 +701,6 @@ static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
> static void etm4_init_arch_data(void *info)
> {
> u32 etmidr0;
> - u32 etmidr1;
> u32 etmidr2;
> u32 etmidr3;
> u32 etmidr4;
> @@ -758,14 +765,6 @@ static void etm4_init_arch_data(void *info)
> /* TSSIZE, bits[28:24] Global timestamp size field */
> drvdata->ts_size = BMVAL(etmidr0, 24, 28);
>
> - /* base architecture of trace unit */
> - etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1);
> - /*
> - * TRCARCHMIN, bits[7:4] architecture the minor version number
> - * TRCARCHMAJ, bits[11:8] architecture major versin number
> - */
> - drvdata->arch = BMVAL(etmidr1, 4, 11);
> -
> /* maximum size of resources */
> etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
> /* CIDSIZE, bits[9:5] Indicates the Context ID size */
> @@ -1602,7 +1601,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> etm4_init_arch_data, &init_arg, 1))
> dev_err(dev, "ETM arch init failed\n");
>
> - if (etm4_arch_supported(drvdata->arch) == false)
> + if (!drvdata->arch)
> return -EINVAL;
>
> etm4_init_trace_id(drvdata);
> @@ -1634,7 +1633,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
>
> pm_runtime_put(&adev->dev);
> dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
> - drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf);
> + drvdata->cpu, ETM_ARCH_MAJOR_VERSION(drvdata->arch),
> + ETM_ARCH_MINOR_VERSION(drvdata->arch));
>
> if (boot_enable) {
> coresight_enable(drvdata->csdev);
> --
> 2.24.1
>

2020-11-09 09:43:45

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 17/26] coresight: etm4x: Cleanup secure exception level masks

On 11/5/20 9:55 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:36PM +0000, Suzuki K Poulose wrote:
>> We rely on the ETM architecture version to decide whether
>> Secure EL2 is available on the CPU for excluding the level
>> for address comparators and viewinst main control register.
>> We must instead use the TRCDIDR3.EXLEVEL_S field to detect
>> the supported levels.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++----------
>> drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++--
>> 2 files changed, 7 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index a12d58a04c5d..6e3f9cb7de3f 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -733,7 +733,6 @@ static void etm4_init_arch_data(void *info)
>> * TRCARCHMAJ, bits[11:8] architecture major versin number
>> */
>> drvdata->arch = BMVAL(etmidr1, 4, 11);
>> - drvdata->config.arch = drvdata->arch;
>>
>> /* maximum size of resources */
>> etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
>> @@ -749,6 +748,7 @@ static void etm4_init_arch_data(void *info)
>> drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
>> /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
>> drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
>> + drvdata->config.s_ex_level = drvdata->s_ex_level;
>> /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
>> drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
>>
>> @@ -920,16 +920,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
>> static u64 etm4_get_access_type(struct etmv4_config *config)
>> {
>> u64 access_type = etm4_get_ns_access_type(config);
>> - u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
>>
>> - /*
>> - * EXLEVEL_S, bits[11:8], don't trace anything happening
>> - * in secure state.
>> - */
>> - access_type |= (ETM_EXLEVEL_S_APP |
>> - ETM_EXLEVEL_S_OS |
>> - s_hyp |
>> - ETM_EXLEVEL_S_MON);
>> + /* All supported secure ELs are excluded */
>> + access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
>>
>> return access_type;
>> }
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
>> index e7f6b7b16fb7..2ac4ecb0af61 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
>> @@ -546,6 +546,8 @@
>> /* PowerDown Control Register bits */
>> #define TRCPDCR_PU BIT(3)
>>
>> +#define TRCACATR_EXLEVEL_SHIFT 8
>> +
>> /* secure state access levels - TRCACATRn */
>> #define ETM_EXLEVEL_S_APP BIT(8)
>> #define ETM_EXLEVEL_S_OS BIT(9)
>> @@ -615,7 +617,7 @@
>> * @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.
>> - * @arch: ETM architecture version (for arch dependent config).
>> + * @s_ex_level: Secure ELs where tracing is supported.
>> */
>> struct etmv4_config {
>> u32 mode;
>> @@ -659,7 +661,7 @@ struct etmv4_config {
>> u32 vmid_mask0;
>> u32 vmid_mask1;
>> u32 ext_inp;
>> - u8 arch;
>> + u8 s_ex_level;
>
> Instead of making s_ex_level redundant I suggest to pass a struct etmv4_drvdata
> to etm4_get_access_type().

I had given thought about that. But this is called from different
places, e.g, etm4_set_comparator_filter() where the drvdata is not
available. Thus, making that change is quite invasive, going down to
the call stack. Morever, the config->arch was already redundant (also
cached in drvdata), mainly due to this reason. We simply replace the
arch field with the actual supported mask of the ELs for precise
programming.

Please let me know if you would like to make the proposed changes.

Cheers
Suzuki




>
> More comments to come tomorrow.
>
> Thanks,
> Mathieu
>
>> };
>>
>> /**
>> --
>> 2.24.1
>>

2020-11-09 09:46:28

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 18/26] coresight: etm4x: Clean up exception level masks

On 11/6/20 6:52 PM, Mathieu Poirier wrote:
> Good morning,

Good morning.

>
> On Wed, Oct 28, 2020 at 10:09:37PM +0000, Suzuki K Poulose wrote:
>> etm4_get_access_type() calculates the exception level bits
>> for use in address comparator registers. This is also used
>> by the TRCVICTLR register by shifting to the required position.
>>
>> This patch cleans up the logic to make etm4_get_access_type()
>> calcualte a generic mask which can be used by all users by
>> shifting to their field.
>>
>> No functional changes, only code cleanups.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> Changes since previous version:
>> - Fix the duplicate shift. More commentary
>> ---

>> -/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */
>> -#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8
>> +/*
>> + * Exception level mask for Secure and Non-Secure ELs.
>> + * ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn).
>> + * The Secure and Non-Secure ELs are always to gether.
>> + * Non-secure EL3 is never implemented.
>> + * We use the following generic mask as they appear in different
>> + * registers and this can be shifted for the appropriate
>> + * fields.
>> + */
>> +#define ETM_EXLEVEL_S_APP BIT(0) /* Secure EL0 */
>> +#define ETM_EXLEVEL_S_OS BIT(1) /* Secure EL1 */
>> +#define ETM_EXLEVEL_S_HYP BIT(2) /* Secure EL2 */
>> +#define ETM_EXLEVEL_S_MON BIT(3) /* Secure EL3/Montor */
>
> s/Montor/Monitor
>

>> +#define ETM_EXLEVEL_NS_APP BIT(4) /* NonSecure EL0 */
>> +#define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */
>> +#define ETM_EXLEVEL_NS_HYP BIT(6) /* NonSecure EL2 */
>> +
>> +#define ETM_EXLEVEL_MASK (GENMASK(6, 0))
>
> Not used.
>
>> +#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0))
>> +#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4))
>
> This needs to be GENMASK(2, 0) in order TRCVICTLR_EXLEVEL_NS_SHIFT to be 20.
> Otherwise the resulting mask is 4 bit off to the left.
>



Will address the comments. Thanks for spotting the mistakes.

Suzuki

2020-11-09 09:52:07

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

On 11/6/20 8:34 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:38PM +0000, Suzuki K Poulose wrote:
>> In preparation to detect the support for system instruction
>> support, move the detection of the device access to the target
>> CPU.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> .../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
>> 1 file changed, 40 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index f038bb10bc78..308674ab746c 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>>
>> static enum cpuhp_state hp_online;
>>
>> +struct etm_init_arg {
>
> s/etm_init_arg/etm4_init_arg

Part of the reason was to add a future IP support where it is not all
ETM4. Again it doesn't really matter. I could change it.

>
>> + struct etmv4_drvdata *drvdata;
>> + struct csdev_access *csa;
>> +};
>> +
>> u64 etm4x_sysreg_read(struct csdev_access *csa,
>> u32 offset,
>> bool _relaxed,
>> @@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
>> .source_ops = &etm4_source_ops,
>> };
>>
>> +static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
>> + struct csdev_access *csa)
>> +{
>> + *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
>> + return true;
>> +}
>> +
>> +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
>> + struct csdev_access *csa)
>> +{
>> + if (drvdata->base)
>> + return etm_init_iomem_access(drvdata, csa);
>> +
>> + return false;
>> +}
>
> Returning a boolean rather than an int for the above two functions seems odd to
> me.
>

We don't return an error from the caller of these functions. So, all we
need to know is, if the operation was success or failure. Having bool
makes it explicit for the checkings, rather than documenting the
expected return values. Hence the choice. But I am open to changing them
if you prefer it that way.



Cheers
Suzuki

2020-11-09 09:53:10

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 20/26] coresight: etm4x: Handle ETM architecture version

On 11/6/20 9:11 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:39PM +0000, Suzuki K Poulose wrote:
>> We are about to rely on TRCDEVARCH for detecting the ETM
>> and its architecture version, falling back to TRCIDR1 if
>> the former is not implemented (in older broken implementations).
>>
>> Also, we use the architecture version information to do
>> make some decisions. Streamline the architecture version
>> handling by adding helpers.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> .../coresight/coresight-etm4x-core.c | 2 +-
>> drivers/hwtracing/coresight/coresight-etm4x.h | 60 ++++++++++++++++++-
>> 2 files changed, 58 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index 308674ab746c..4ef47a2946a4 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -842,7 +842,7 @@ static void etm4_init_arch_data(void *info)
>> * Otherwise for values 0x1 and above the number is N + 1 as per v4.2.
>> */
>> drvdata->nr_resource = BMVAL(etmidr4, 16, 19);
>> - if ((drvdata->arch < ETM4X_ARCH_4V3) || (drvdata->nr_resource > 0))
>> + if ((drvdata->arch < ETM_ARCH_V4_3) || (drvdata->nr_resource > 0))
>> drvdata->nr_resource += 1;
>> /*
>> * NUMSSCC, bits[23:20] the number of single-shot
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
>> index f1251ddf1984..fe7107282e54 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
>> @@ -459,7 +459,6 @@
>> #define ETM_MAX_RES_SEL 32
>> #define ETM_MAX_SS_CMP 8
>>
>> -#define ETM_ARCH_V4 0x40
>> #define ETMv4_SYNC_MASK 0x1F
>> #define ETM_CYC_THRESHOLD_MASK 0xFFF
>> #define ETM_CYC_THRESHOLD_DEFAULT 0x100
>> @@ -581,8 +580,63 @@
>> #define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
>> #define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)
>>
>> +#define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8
>> +#define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
>> +#define ETM_TRCIDR1_ARCH_MAJOR(x) \
>> + (((x) & ETM_TRCIDR1_ARCH_MAJOR_MASK) >> ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
>> +#define ETM_TRCIDR1_ARCH_MINOR_SHIFT 4
>> +#define ETM_TRCIDR1_ARCH_MINOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MINOR_SHIFT)
>> +#define ETM_TRCIDR1_ARCH_MINOR(x) \
>> + (((x) & ETM_TRCIDR1_ARCH_MINOR_MASK) >> ETM_TRCIDR1_ARCH_MINOR_SHIFT)
>> +#define ETM_TRCIDR1_ARCH_SHIFT ETM_TRCIDR1_ARCH_MINOR_SHIFT
>> +#define ETM_TRCIDR1_ARCH_MASK \
>> + (ETM_TRCIDR1_ARCH_MAJOR_MASK | ETM_TRCIDR1_ARCH_MINOR_MASK)
>> +
>> +#define ETM_TRCIDR1_ARCH_ETMv4 0x4
>> +
>> +/*
>> + * Driver representation of the ETM architecture.
>> + * The version of an ETM component can be detected from
>> + *
>> + * TRCDEVARCH - CoreSight architected register
>> + * - Bits[15:12] - Major version
>> + * - Bits[19:16] - Minor version
>> + * TRCIDR1 - ETM architected register
>> + * - Bits[12:8] - Major version
>
> This should be [11:8], bit 12 is part of RES1.

Well spotted. will fix it.

>
>> + * - Bits[7:4] - Minor version
>> + * We must rely on TRCDEVARCH for the version information,
>> + * however we don't want to break the support for potential
>> + * old implementations which might not implement it. Thus
>> + * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
>> + * for memory mapped components.
>> + * Now to make certain decisions easier based on the version
>> + * we use an internal representation of the version in the
>> + * driver, as follows :
>> + *
>> + * ETM_ARCH_VERSION[7:0], where :
>> + * Bits[7:4] - Major version
>> + * Bits[3:0] - Minro version
>> + */
>> +#define ETM_ARCH_VERSION(major, minor) \
>> + ((((major) & 0xfU) << 4) | (((minor) & 0xfU)))
>> +#define ETM_ARCH_MAJOR_VERSION(arch) (((arch) >> 4) & 0xfU)
>> +#define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU)
>
> There are a few unused defines brought in by this patch. I trust they will be
> used in subsequent patches.

Yes, they will be used. The reason for adding them here was to introduce
the helpers along with the defintions. This will be also used for
handling future architecture versions.

Suzuki

2020-11-09 17:44:15

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 17/26] coresight: etm4x: Cleanup secure exception level masks

On Mon, Nov 09, 2020 at 09:40:54AM +0000, Suzuki K Poulose wrote:
> On 11/5/20 9:55 PM, Mathieu Poirier wrote:
> > On Wed, Oct 28, 2020 at 10:09:36PM +0000, Suzuki K Poulose wrote:
> > > We rely on the ETM architecture version to decide whether
> > > Secure EL2 is available on the CPU for excluding the level
> > > for address comparators and viewinst main control register.
> > > We must instead use the TRCDIDR3.EXLEVEL_S field to detect
> > > the supported levels.
> > >
> > > Signed-off-by: Suzuki K Poulose <[email protected]>
> > > ---
> > > drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++----------
> > > drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++--
> > > 2 files changed, 7 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > index a12d58a04c5d..6e3f9cb7de3f 100644
> > > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > @@ -733,7 +733,6 @@ static void etm4_init_arch_data(void *info)
> > > * TRCARCHMAJ, bits[11:8] architecture major versin number
> > > */
> > > drvdata->arch = BMVAL(etmidr1, 4, 11);
> > > - drvdata->config.arch = drvdata->arch;
> > > /* maximum size of resources */
> > > etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2);
> > > @@ -749,6 +748,7 @@ static void etm4_init_arch_data(void *info)
> > > drvdata->ccitmin = BMVAL(etmidr3, 0, 11);
> > > /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
> > > drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
> > > + drvdata->config.s_ex_level = drvdata->s_ex_level;
> > > /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */
> > > drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
> > > @@ -920,16 +920,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config)
> > > static u64 etm4_get_access_type(struct etmv4_config *config)
> > > {
> > > u64 access_type = etm4_get_ns_access_type(config);
> > > - u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
> > > - /*
> > > - * EXLEVEL_S, bits[11:8], don't trace anything happening
> > > - * in secure state.
> > > - */
> > > - access_type |= (ETM_EXLEVEL_S_APP |
> > > - ETM_EXLEVEL_S_OS |
> > > - s_hyp |
> > > - ETM_EXLEVEL_S_MON);
> > > + /* All supported secure ELs are excluded */
> > > + access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
> > > return access_type;
> > > }
> > > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> > > index e7f6b7b16fb7..2ac4ecb0af61 100644
> > > --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> > > +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> > > @@ -546,6 +546,8 @@
> > > /* PowerDown Control Register bits */
> > > #define TRCPDCR_PU BIT(3)
> > > +#define TRCACATR_EXLEVEL_SHIFT 8
> > > +
> > > /* secure state access levels - TRCACATRn */
> > > #define ETM_EXLEVEL_S_APP BIT(8)
> > > #define ETM_EXLEVEL_S_OS BIT(9)
> > > @@ -615,7 +617,7 @@
> > > * @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.
> > > - * @arch: ETM architecture version (for arch dependent config).
> > > + * @s_ex_level: Secure ELs where tracing is supported.
> > > */
> > > struct etmv4_config {
> > > u32 mode;
> > > @@ -659,7 +661,7 @@ struct etmv4_config {
> > > u32 vmid_mask0;
> > > u32 vmid_mask1;
> > > u32 ext_inp;
> > > - u8 arch;
> > > + u8 s_ex_level;
> >
> > Instead of making s_ex_level redundant I suggest to pass a struct etmv4_drvdata
> > to etm4_get_access_type().
>
> I had given thought about that. But this is called from different
> places, e.g, etm4_set_comparator_filter() where the drvdata is not
> available. Thus, making that change is quite invasive, going down to
> the call stack. Morever, the config->arch was already redundant (also
> cached in drvdata), mainly due to this reason. We simply replace the
> arch field with the actual supported mask of the ELs for precise
> programming.
>

I also noticed config->arch while looking at this patch.

> Please let me know if you would like to make the proposed changes.

The problem with adding s_ex_level to etmv4_config is that we are adding to the
technological debt, i.e the more we add the more have to fix. The upside with
the status quo is that we don't add to an already extensive patchset. We can
move forward with the latter but would really like to see both ->arch and
->s_ex_level fixed in a subsequent patchset.

>
> Cheers
> Suzuki
>
>
>
>
> >
> > More comments to come tomorrow.
> >
> > Thanks,
> > Mathieu
> >
> > > };
> > > /**
> > > --
> > > 2.24.1
> > >
>

2020-11-09 17:50:35

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

On Mon, Nov 09, 2020 at 09:48:07AM +0000, Suzuki K Poulose wrote:
> On 11/6/20 8:34 PM, Mathieu Poirier wrote:
> > On Wed, Oct 28, 2020 at 10:09:38PM +0000, Suzuki K Poulose wrote:
> > > In preparation to detect the support for system instruction
> > > support, move the detection of the device access to the target
> > > CPU.
> > >
> > > Signed-off-by: Suzuki K Poulose <[email protected]>
> > > ---
> > > .../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
> > > 1 file changed, 40 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > index f038bb10bc78..308674ab746c 100644
> > > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
> > > static enum cpuhp_state hp_online;
> > > +struct etm_init_arg {
> >
> > s/etm_init_arg/etm4_init_arg
>
> Part of the reason was to add a future IP support where it is not all
> ETM4. Again it doesn't really matter. I could change it.
>

I thought about that too but the inclusion of etmv4_drvdata cancels any attempts
at making things generic.

> >
> > > + struct etmv4_drvdata *drvdata;
> > > + struct csdev_access *csa;
> > > +};
> > > +
> > > u64 etm4x_sysreg_read(struct csdev_access *csa,
> > > u32 offset,
> > > bool _relaxed,
> > > @@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
> > > .source_ops = &etm4_source_ops,
> > > };
> > > +static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
> > > + struct csdev_access *csa)
> > > +{
> > > + *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
> > > + return true;
> > > +}
> > > +
> > > +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
> > > + struct csdev_access *csa)
> > > +{
> > > + if (drvdata->base)
> > > + return etm_init_iomem_access(drvdata, csa);
> > > +
> > > + return false;
> > > +}
> >
> > Returning a boolean rather than an int for the above two functions seems odd to
> > me.
> >
>
> We don't return an error from the caller of these functions. So, all we

And this is done from smp_call_function_single() where returning a meaningful
error value would mandate changes to struct etm_init_arg, which is needlessly
messy for this set. Void my comment.

> need to know is, if the operation was success or failure. Having bool
> makes it explicit for the checkings, rather than documenting the
> expected return values. Hence the choice. But I am open to changing them
> if you prefer it that way.
>
>
>
> Cheers
> Suzuki

2020-11-09 18:37:09

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 22/26] coresight: etm4x: Add necessary synchronization for sysreg access

On Wed, Oct 28, 2020 at 10:09:41PM +0000, Suzuki K Poulose wrote:
> As per the specification any update to the TRCPRGCTLR must be synchronized
> by a context synchronization event (in our case an explicist ISB) before
> the TRCSTATR is checked.
>
> Cc: Mike Leach <[email protected]>
> Cc: Mathieu Poirier <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index e36bc1c722c7..4bc2f15b6332 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -178,6 +178,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> /* Disable the trace unit before programming trace registers */
> etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
>
> + /*
> + * If we use system instructions, we need to synchronize the
> + * write to the TRCPRGCTLR, before accessing the TRCSTATR.
> + * See ARM IHI0064F, section
> + * "4.3.7 Synchronization of register updates"
> + */
> + if (!csa->io_mem)
> + isb();
> +

When I first read the documentation on system instruction section 4.3.7 really
got me thinking...

At the very top, right after the title "Synchronization of register updates" one
can read "Software running on the PE...". Later in the text, when specifying
the synchronisation rules, the term "trace analyzer" is used. _Typically_ a trace
analyzer is an external box.

Arm documentation is precise and usually doesn't overlook that kind of detail.
The question is to understand if a context synchronisation event is also needed
when programming is done on the PE. If so I think the documentation should be
amended.

In that case:

Reviewed-by: Mathieu Poirier <[email protected]>


> /* wait for TRCSTATR.IDLE to go up */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
> dev_err(etm_dev,
> @@ -256,6 +265,10 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> /* Enable the trace unit */
> etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
>
> + /* Synchronize the register updates for sysreg access */
> + if (!csa->io_mem)
> + isb();
> +
> /* wait for TRCSTATR.IDLE to go back down to '0' */
> if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
> dev_err(etm_dev,
> --
> 2.24.1
>

2020-11-09 20:45:42

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 24/26] coresight: etm4x: Refactor probing routine

On Wed, Oct 28, 2020 at 10:09:43PM +0000, Suzuki K Poulose wrote:
> CoreSight ETM with system register access may not have a
> memory mapped i/o access. Refactor the ETM specific probing
> into a common routine to allow reusing the code for such ETMs.
>
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> .../coresight/coresight-etm4x-core.c | 48 +++++++++++--------
> 1 file changed, 29 insertions(+), 19 deletions(-)

Reviewed-by: Mathieu Poirier <[email protected]>

>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index dc537b5612eb..25fab5513604 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -1598,14 +1598,11 @@ static void etm4_pm_clear(void)
> }
> }
>
> -static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> +static int etm4_probe(struct device *dev, void __iomem *base)
> {
> int ret;
> - void __iomem *base;
> - struct device *dev = &adev->dev;
> struct coresight_platform_data *pdata = NULL;
> struct etmv4_drvdata *drvdata;
> - struct resource *res = &adev->res;
> struct coresight_desc desc = { 0 };
> struct etm_init_arg init_arg = { 0 };
>
> @@ -1629,11 +1626,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> if (fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
> drvdata->skip_power_up = true;
>
> - /* Validity for the resource is already checked by the AMBA core */
> - base = devm_ioremap_resource(dev, res);
> - if (IS_ERR(base))
> - return PTR_ERR(base);
> -
> drvdata->base = base;
>
> spin_lock_init(&drvdata->spinlock);
> @@ -1663,7 +1655,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> if (IS_ERR(pdata))
> return PTR_ERR(pdata);
>
> - adev->dev.platform_data = pdata;
> + dev->platform_data = pdata;
>
> desc.type = CORESIGHT_DEV_TYPE_SOURCE;
> desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
> @@ -1683,7 +1675,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
>
> etmdrvdata[drvdata->cpu] = drvdata;
>
> - pm_runtime_put(&adev->dev);
> dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
> drvdata->cpu, ETM_ARCH_MAJOR_VERSION(drvdata->arch),
> ETM_ARCH_MINOR_VERSION(drvdata->arch));
> @@ -1696,6 +1687,25 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
> return 0;
> }
>
> +static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
> +{
> + void __iomem *base;
> + struct device *dev = &adev->dev;
> + struct resource *res = &adev->res;
> + int ret;
> +
> + /* Validity for the resource is already checked by the AMBA core */
> + base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + ret = etm4_probe(dev, base);
> + if (!ret)
> + pm_runtime_put(&adev->dev);
> +
> + return ret;
> +}
> +
> static struct amba_cs_uci_id uci_id_etm4[] = {
> {
> /* ETMv4 UCI data */
> @@ -1712,15 +1722,15 @@ static void __exit clear_etmdrvdata(void *info)
> etmdrvdata[cpu] = NULL;
> }
>
> -static int __exit etm4_remove(struct amba_device *adev)
> +static int __exit etm4_remove_amba(struct amba_device *adev)
> {
> struct etmv4_drvdata *drvdata = dev_get_drvdata(&adev->dev);
>
> etm_perf_symlink(drvdata->csdev, false);
>
> /*
> - * Taking hotplug lock here to avoid racing between etm4_remove and
> - * CPU hotplug call backs.
> + * Taking hotplug lock here to avoid racing between etm4_remove_amba()
> + * and CPU hotplug call backs.
> */
> cpus_read_lock();
> /*
> @@ -1760,14 +1770,14 @@ static const struct amba_id etm4_ids[] = {
>
> MODULE_DEVICE_TABLE(amba, etm4_ids);
>
> -static struct amba_driver etm4x_driver = {
> +static struct amba_driver etm4x_amba_driver = {
> .drv = {
> .name = "coresight-etm4x",
> .owner = THIS_MODULE,
> .suppress_bind_attrs = true,
> },
> - .probe = etm4_probe,
> - .remove = etm4_remove,
> + .probe = etm4_probe_amba,
> + .remove = etm4_remove_amba,
> .id_table = etm4_ids,
> };
>
> @@ -1781,7 +1791,7 @@ static int __init etm4x_init(void)
> if (ret)
> return ret;
>
> - ret = amba_driver_register(&etm4x_driver);
> + ret = amba_driver_register(&etm4x_amba_driver);
> if (ret) {
> pr_err("Error registering etm4x driver\n");
> etm4_pm_clear();
> @@ -1792,7 +1802,7 @@ static int __init etm4x_init(void)
>
> static void __exit etm4x_exit(void)
> {
> - amba_driver_unregister(&etm4x_driver);
> + amba_driver_unregister(&etm4x_amba_driver);
> etm4_pm_clear();
> }
>
> --
> 2.24.1
>

2020-11-09 20:51:46

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 26/26] dts: bindings: coresight: ETM system register access only units

On Wed, Oct 28, 2020 at 10:09:45PM +0000, Suzuki K Poulose wrote:
> Document the bindings for ETMs with system register accesses.
>
> Cc: [email protected]
> Cc: Mathieu Poirier <[email protected]>
> Cc: Mike Leach <[email protected]>
> Cc: Rob Herring <[email protected]>
> Signed-off-by: Suzuki K Poulose <[email protected]>
> ---
> Documentation/devicetree/bindings/arm/coresight.txt | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> index d711676b4a51..bff96a550102 100644
> --- a/Documentation/devicetree/bindings/arm/coresight.txt
> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> @@ -34,9 +34,12 @@ its hardware characteristcs.
> Program Flow Trace Macrocell:
> "arm,coresight-etm3x", "arm,primecell";
>
> - - Embedded Trace Macrocell (version 4.x):
> + - Embedded Trace Macrocell (version 4.x), with memory mapped access.
> "arm,coresight-etm4x", "arm,primecell";
>
> + - Embedded Trace Macrocell with system register access only.
> + "arm,coresight-etm-sysreg";

Please make this "arm,coresight-etm4x-sysreg". Up to now all reference of
"etm" without a version related to ETMv3/PTM1.1. If we start mixing things it
will be come insanely confusing.

Thanks,
Mathieu

> +
> - Coresight programmable Replicator :
> "arm,coresight-dynamic-replicator", "arm,primecell";
>
> --
> 2.24.1
>

2020-11-10 10:14:01

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 22/26] coresight: etm4x: Add necessary synchronization for sysreg access

On 11/9/20 6:32 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:41PM +0000, Suzuki K Poulose wrote:
>> As per the specification any update to the TRCPRGCTLR must be synchronized
>> by a context synchronization event (in our case an explicist ISB) before
>> the TRCSTATR is checked.
>>
>> Cc: Mike Leach <[email protected]>
>> Cc: Mathieu Poirier <[email protected]>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
>> 1 file changed, 13 insertions(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index e36bc1c722c7..4bc2f15b6332 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -178,6 +178,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>> /* Disable the trace unit before programming trace registers */
>> etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
>>
>> + /*
>> + * If we use system instructions, we need to synchronize the
>> + * write to the TRCPRGCTLR, before accessing the TRCSTATR.
>> + * See ARM IHI0064F, section
>> + * "4.3.7 Synchronization of register updates"
>> + */
>> + if (!csa->io_mem)
>> + isb();
>> +
>
> When I first read the documentation on system instruction section 4.3.7 really
> got me thinking...
>
> At the very top, right after the title "Synchronization of register updates" one
> can read "Software running on the PE...". Later in the text, when specifying
> the synchronisation rules, the term "trace analyzer" is used. _Typically_ a trace
> analyzer is an external box.
>

Very good point. The trace analyzer could still use the system register
to program the ETM and causing a context synchronization event is tricky
from within the trace analyzer. And I agree that there is a bit of
confusion around the synchronization from a self-hosted point of view.
I believe this is true for the self-hosted case too and should be
clarified in the TRM.

> Arm documentation is precise and usually doesn't overlook that kind of detail.
> The question is to understand if a context synchronisation event is also needed
> when programming is done on the PE. If so I think the documentation should be
> amended.
>
> In that case:
>
> Reviewed-by: Mathieu Poirier <[email protected]>
>

Thanks
Suzuki

2020-11-10 10:50:24

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 19/26] coresight: etm4x: Detect access early on the target CPU

On 11/6/20 8:46 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:38PM +0000, Suzuki K Poulose wrote:
>> In preparation to detect the support for system instruction
>> support, move the detection of the device access to the target
>> CPU.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> .../coresight/coresight-etm4x-core.c | 45 ++++++++++++++++---
>> 1 file changed, 40 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> index f038bb10bc78..308674ab746c 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>> @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
>>
>> static enum cpuhp_state hp_online;
>>
>> +struct etm_init_arg {
>> + struct etmv4_drvdata *drvdata;
>> + struct csdev_access *csa;
>> +};
>> +
>> u64 etm4x_sysreg_read(struct csdev_access *csa,
>> u32 offset,
>> bool _relaxed,
>> @@ -669,6 +674,22 @@ static const struct coresight_ops etm4_cs_ops = {
>> .source_ops = &etm4_source_ops,
>> };
>>
>> +static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata,
>> + struct csdev_access *csa)
>> +{
>> + *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
>> + return true;
>> +}
>> +
>> +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata,
>> + struct csdev_access *csa)
>> +{
>> + if (drvdata->base)
>> + return etm_init_iomem_access(drvdata, csa);
>> +
>> + return false;
>> +}
>
> I would also prefix the above two functions with "etm4_" rather than "etm_" to
> follow what is already done in this file.

sure, will do.

suzuki

2020-11-10 10:53:40

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 26/26] dts: bindings: coresight: ETM system register access only units

On 11/9/20 8:50 PM, Mathieu Poirier wrote:
> On Wed, Oct 28, 2020 at 10:09:45PM +0000, Suzuki K Poulose wrote:
>> Document the bindings for ETMs with system register accesses.
>>
>> Cc: [email protected]
>> Cc: Mathieu Poirier <[email protected]>
>> Cc: Mike Leach <[email protected]>
>> Cc: Rob Herring <[email protected]>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> Documentation/devicetree/bindings/arm/coresight.txt | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
>> index d711676b4a51..bff96a550102 100644
>> --- a/Documentation/devicetree/bindings/arm/coresight.txt
>> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
>> @@ -34,9 +34,12 @@ its hardware characteristcs.
>> Program Flow Trace Macrocell:
>> "arm,coresight-etm3x", "arm,primecell";
>>
>> - - Embedded Trace Macrocell (version 4.x):
>> + - Embedded Trace Macrocell (version 4.x), with memory mapped access.
>> "arm,coresight-etm4x", "arm,primecell";
>>
>> + - Embedded Trace Macrocell with system register access only.
>> + "arm,coresight-etm-sysreg";
>
> Please make this "arm,coresight-etm4x-sysreg". Up to now all reference of
> "etm" without a version related to ETMv3/PTM1.1. If we start mixing things it
> will be come insanely confusing.

Agreed. will rename it.

Suzuki

2020-11-10 11:44:29

by John Horley

[permalink] [raw]
Subject: RE: [PATCH v3 22/26] coresight: etm4x: Add necessary synchronization for sysreg access

On 11/10/20 10:11 AM, Suzuki K Poulose wrote:
> On 11/9/20 6:32 PM, Mathieu Poirier wrote:
>> On Wed, Oct 28, 2020 at 10:09:41PM +0000, Suzuki K Poulose wrote:
>>> As per the specification any update to the TRCPRGCTLR must be
>>> synchronized by a context synchronization event (in our case an
>>> explicist ISB) before the TRCSTATR is checked.
>>>
>>> Cc: Mike Leach <[email protected]>
>>> Cc: Mathieu Poirier <[email protected]>
>>> Signed-off-by: Suzuki K Poulose <[email protected]>
>>> ---
>>> drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
>>> 1 file changed, 13 insertions(+)
>>>
>>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> index e36bc1c722c7..4bc2f15b6332 100644
>>> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
>>> @@ -178,6 +178,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
>>> /* Disable the trace unit before programming trace registers */
>>> etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
>>>
>>> + /*
>>> + * If we use system instructions, we need to synchronize the
>>> + * write to the TRCPRGCTLR, before accessing the TRCSTATR.
>>> + * See ARM IHI0064F, section
>>> + * "4.3.7 Synchronization of register updates"
>>> + */
>>> + if (!csa->io_mem)
>>> + isb();
>>> +
>>
>> When I first read the documentation on system instruction section
>> 4.3.7 really got me thinking...
>>
>> At the very top, right after the title "Synchronization of register
>> updates" one can read "Software running on the PE...". Later in the
>> text, when specifying the synchronisation rules, the term "trace
>> analyzer" is used. _Typically_ a trace analyzer is an external box.
>>
>
>Very good point. The trace analyzer could still use the system register to
>program the ETM and causing a context synchronization event is tricky from
>within the trace analyzer. And I agree that there is a bit of confusion
>around the synchronization from a self-hosted point of view.
>I believe this is true for the self-hosted case too and should be clarified
>in the TRM.
>

The ETM architecture uses "trace analyzer" to mean self-hosted software and an external debugger. It's a useful term that generically covers "the thing that's in charge of tracing" and "the thing that's capturing and/or decoding the trace", regardless of whether either of these are external or self-hosted (or even a mixture!).

So in 4.3.7, yes this does mean that context synchronization events are needed to synchronize register updates when using system instructions to program the trace unit.

I'll take a look at what we can improve here :-)

Cheers, John.

>> Arm documentation is precise and usually doesn't overlook that kind of detail.
>> The question is to understand if a context synchronisation event is
>> also needed when programming is done on the PE. If so I think the
>> documentation should be amended.
>>
>> In that case:
>>
>> Reviewed-by: Mathieu Poirier <[email protected]>
>>
>
>Thanks
>Suzuki
>_______________________________________________
>CoreSight mailing list
>[email protected]
>https://lists.linaro.org/mailman/listinfo/coresight

2020-11-10 17:38:23

by Mathieu Poirier

[permalink] [raw]
Subject: Re: [PATCH v3 22/26] coresight: etm4x: Add necessary synchronization for sysreg access

On Tue, Nov 10, 2020 at 10:11:23AM +0000, Suzuki K Poulose wrote:
> On 11/9/20 6:32 PM, Mathieu Poirier wrote:
> > On Wed, Oct 28, 2020 at 10:09:41PM +0000, Suzuki K Poulose wrote:
> > > As per the specification any update to the TRCPRGCTLR must be synchronized
> > > by a context synchronization event (in our case an explicist ISB) before
> > > the TRCSTATR is checked.
> > >
> > > Cc: Mike Leach <[email protected]>
> > > Cc: Mathieu Poirier <[email protected]>
> > > Signed-off-by: Suzuki K Poulose <[email protected]>
> > > ---
> > > drivers/hwtracing/coresight/coresight-etm4x-core.c | 13 +++++++++++++
> > > 1 file changed, 13 insertions(+)
> > >
> > > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > index e36bc1c722c7..4bc2f15b6332 100644
> > > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > > @@ -178,6 +178,15 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> > > /* Disable the trace unit before programming trace registers */
> > > etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
> > > + /*
> > > + * If we use system instructions, we need to synchronize the
> > > + * write to the TRCPRGCTLR, before accessing the TRCSTATR.
> > > + * See ARM IHI0064F, section
> > > + * "4.3.7 Synchronization of register updates"
> > > + */
> > > + if (!csa->io_mem)
> > > + isb();
> > > +
> >
> > When I first read the documentation on system instruction section 4.3.7 really
> > got me thinking...
> >
> > At the very top, right after the title "Synchronization of register updates" one
> > can read "Software running on the PE...". Later in the text, when specifying
> > the synchronisation rules, the term "trace analyzer" is used. _Typically_ a trace
> > analyzer is an external box.
> >
>
> Very good point. The trace analyzer could still use the system register
> to program the ETM and causing a context synchronization event is tricky
> from within the trace analyzer. And I agree that there is a bit of
> confusion around the synchronization from a self-hosted point of view.
> I believe this is true for the self-hosted case too and should be
> clarified in the TRM.

I think John has given us the final answer here - the current implementation
stands.

>
> > Arm documentation is precise and usually doesn't overlook that kind of detail.
> > The question is to understand if a context synchronisation event is also needed
> > when programming is done on the PE. If so I think the documentation should be
> > amended.
> >
> > In that case:
> >
> > Reviewed-by: Mathieu Poirier <[email protected]>
> >
>
> Thanks
> Suzuki

2020-11-10 23:21:48

by Suzuki K Poulose

[permalink] [raw]
Subject: Re: [PATCH v3 18/26] coresight: etm4x: Clean up exception level masks

On 11/6/20 6:52 PM, Mathieu Poirier wrote:
> Good morning,
>
> On Wed, Oct 28, 2020 at 10:09:37PM +0000, Suzuki K Poulose wrote:
>> etm4_get_access_type() calculates the exception level bits
>> for use in address comparator registers. This is also used
>> by the TRCVICTLR register by shifting to the required position.
>>
>> This patch cleans up the logic to make etm4_get_access_type()
>> calcualte a generic mask which can be used by all users by
>> shifting to their field.
>>
>> No functional changes, only code cleanups.
>>
>> Signed-off-by: Suzuki K Poulose <[email protected]>
>> ---
>> Changes since previous version:
>> - Fix the duplicate shift. More commentary
>> ---


>> diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
>> index 2ac4ecb0af61..f1251ddf1984 100644
>> --- a/drivers/hwtracing/coresight/coresight-etm4x.h
>> +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
>> @@ -548,24 +548,38 @@
>>
>> #define TRCACATR_EXLEVEL_SHIFT 8
>>
>> -/* secure state access levels - TRCACATRn */
>> -#define ETM_EXLEVEL_S_APP BIT(8)
>> -#define ETM_EXLEVEL_S_OS BIT(9)
>> -#define ETM_EXLEVEL_S_HYP BIT(10)
>> -#define ETM_EXLEVEL_S_MON BIT(11)
>> -/* non-secure state access levels - TRCACATRn */
>> -#define ETM_EXLEVEL_NS_APP BIT(12)
>> -#define ETM_EXLEVEL_NS_OS BIT(13)
>> -#define ETM_EXLEVEL_NS_HYP BIT(14)
>> -#define ETM_EXLEVEL_NS_NA BIT(15)
>> -
>> -/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */
>> -#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8
>> +/*
>> + * Exception level mask for Secure and Non-Secure ELs.
>> + * ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn).
>> + * The Secure and Non-Secure ELs are always to gether.
>> + * Non-secure EL3 is never implemented.
>> + * We use the following generic mask as they appear in different
>> + * registers and this can be shifted for the appropriate
>> + * fields.
>> + */
>> +#define ETM_EXLEVEL_S_APP BIT(0) /* Secure EL0 */
>> +#define ETM_EXLEVEL_S_OS BIT(1) /* Secure EL1 */
>> +#define ETM_EXLEVEL_S_HYP BIT(2) /* Secure EL2 */
>> +#define ETM_EXLEVEL_S_MON BIT(3) /* Secure EL3/Montor */
>
> s/Montor/Monitor
>
>> +#define ETM_EXLEVEL_NS_APP BIT(4) /* NonSecure EL0 */
>> +#define ETM_EXLEVEL_NS_OS BIT(5) /* NonSecure EL1 */
>> +#define ETM_EXLEVEL_NS_HYP BIT(6) /* NonSecure EL2 */
>> +
>> +#define ETM_EXLEVEL_MASK (GENMASK(6, 0))
>
> Not used.
>

I have updated the patch to use this for creating the TRCVICTLR_EXLEVEL_MASK
(see below), which is used to clear all the EXLEVEL bits from TRCVICTLR.

>> +#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0))
>> +#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4))
>
> This needs to be GENMASK(2, 0) in order TRCVICTLR_EXLEVEL_NS_SHIFT to be 20.
> Otherwise the resulting mask is 4 bit off to the left.

I have retained the ETM_EXLEVEL_NS_MASK as it is above, to keep the defintions
above consistent. I have fixed the problem by using TRCVICTLR_EXLEVEL_SHIFT whenever
we use ETM_EXLEVEL_*_MASK.

And TRCVICTLR_EXLEVEL_*_SHIFT is used when we set a given value from the sysfs, respectively.
e.g :

@@ -795,10 +795,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,

spin_lock(&drvdata->spinlock);
/* clear EXLEVEL_NS bits */
- config->vinst_ctrl &= ~(ETM_EXLEVEL_NS_VICTLR_MASK);
+ config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK);
/* enable instruction tracing for corresponding exception level */
val &= drvdata->ns_ex_level;
- config->vinst_ctrl |= (val << 20);
+ config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT);
spin_unlock(&drvdata->spinlock);
return size;
}

>
>> +
>> +/* access level controls in TRCACATRn */
>> +#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 ETM_EXLEVEL_S_VICTLR_MASK GENMASK(19, 16)
>> -/* NS MON (EL3) mode never implemented */
>> -#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
>> +#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT)
>> +#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)

And the above has been updated to :

+#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)

Suzuki