Skip to content

Commit be7fc88

Browse files
Yuanfang ZhangTreehugger Robot
authored andcommitted
UPSTREAM: coresight-etm4x: add isb() before reading the TRCSTATR
As recommended by section 4.3.7 ("Synchronization when using system instructions to progrom the trace unit") of ARM IHI 0064H.b, the self-hosted trace analyzer must perform a Context synchronization event between writing to the TRCPRGCTLR and reading the TRCSTATR. Additionally, add an ISB between the each read of TRCSTATR on coresight_timeout() when using system instructions to program the trace unit. Bug: 254441685 Fixes: 1ab3bb9df5e3 ("coresight: etm4x: Add necessary synchronization for sysreg access") Signed-off-by: Yuanfang Zhang <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected] (cherry picked from commit 4ff6039ffb79a4a8a44b63810a8a2f2b43264856) Signed-off-by: Lee Jones <[email protected]> Change-Id: Ieb1b69cea7534455213a9f928a358605d33acdbc
1 parent e386309 commit be7fc88

File tree

3 files changed

+62
-10
lines changed

3 files changed

+62
-10
lines changed

drivers/hwtracing/coresight/coresight-core.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,18 +1447,20 @@ static void coresight_remove_conns(struct coresight_device *csdev)
14471447
}
14481448

14491449
/**
1450-
* coresight_timeout - loop until a bit has changed to a specific register
1451-
* state.
1450+
* coresight_timeout_action - loop until a bit has changed to a specific register
1451+
* state, with a callback after every trial.
14521452
* @csa: coresight device access for the device
14531453
* @offset: Offset of the register from the base of the device.
14541454
* @position: the position of the bit of interest.
14551455
* @value: the value the bit should have.
1456+
* @cb: Call back after each trial.
14561457
*
14571458
* Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
14581459
* TIMEOUT_US has elapsed, which ever happens first.
14591460
*/
1460-
int coresight_timeout(struct csdev_access *csa, u32 offset,
1461-
int position, int value)
1461+
int coresight_timeout_action(struct csdev_access *csa, u32 offset,
1462+
int position, int value,
1463+
coresight_timeout_cb_t cb)
14621464
{
14631465
int i;
14641466
u32 val;
@@ -1474,7 +1476,8 @@ int coresight_timeout(struct csdev_access *csa, u32 offset,
14741476
if (!(val & BIT(position)))
14751477
return 0;
14761478
}
1477-
1479+
if (cb)
1480+
cb(csa, offset, position, value);
14781481
/*
14791482
* Delay is arbitrary - the specification doesn't say how long
14801483
* we are expected to wait. Extra check required to make sure
@@ -1486,6 +1489,13 @@ int coresight_timeout(struct csdev_access *csa, u32 offset,
14861489

14871490
return -EAGAIN;
14881491
}
1492+
EXPORT_SYMBOL_GPL(coresight_timeout_action);
1493+
1494+
int coresight_timeout(struct csdev_access *csa, u32 offset,
1495+
int position, int value)
1496+
{
1497+
return coresight_timeout_action(csa, offset, position, value, NULL);
1498+
}
14891499
EXPORT_SYMBOL_GPL(coresight_timeout);
14901500

14911501
u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset)

drivers/hwtracing/coresight/coresight-etm4x-core.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,29 @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata,
367367
}
368368
#endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
369369

370+
static void etm4x_sys_ins_barrier(struct csdev_access *csa, u32 offset, int pos, int val)
371+
{
372+
if (!csa->io_mem)
373+
isb();
374+
}
375+
376+
/*
377+
* etm4x_wait_status: Poll for TRCSTATR.<pos> == <val>. While using system
378+
* instruction to access the trace unit, each access must be separated by a
379+
* synchronization barrier. See ARM IHI0064H.b section "4.3.7 Synchronization of
380+
* register updates", for system instructions section, in "Notes":
381+
*
382+
* "In particular, whenever disabling or enabling the trace unit, a poll of
383+
* TRCSTATR needs explicit synchronization between each read of TRCSTATR"
384+
*/
385+
static int etm4x_wait_status(struct csdev_access *csa, int pos, int val)
386+
{
387+
if (!csa->io_mem)
388+
return coresight_timeout_action(csa, TRCSTATR, pos, val,
389+
etm4x_sys_ins_barrier);
390+
return coresight_timeout(csa, TRCSTATR, pos, val);
391+
}
392+
370393
static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
371394
{
372395
int i, rc;
@@ -398,7 +421,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
398421
isb();
399422

400423
/* wait for TRCSTATR.IDLE to go up */
401-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
424+
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1))
402425
dev_err(etm_dev,
403426
"timeout while waiting for Idle Trace Status\n");
404427
if (drvdata->nr_pe)
@@ -489,7 +512,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
489512
isb();
490513

491514
/* wait for TRCSTATR.IDLE to go back down to '0' */
492-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
515+
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0))
493516
dev_err(etm_dev,
494517
"timeout while waiting for Idle Trace Status\n");
495518

@@ -802,10 +825,25 @@ static void etm4_disable_hw(void *info)
802825
tsb_csync();
803826
etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
804827

828+
/*
829+
* As recommended by section 4.3.7 ("Synchronization when using system
830+
* instructions to progrom the trace unit") of ARM IHI 0064H.b, the
831+
* self-hosted trace analyzer must perform a Context synchronization
832+
* event between writing to the TRCPRGCTLR and reading the TRCSTATR.
833+
*/
834+
if (!csa->io_mem)
835+
isb();
836+
805837
/* wait for TRCSTATR.PMSTABLE to go to '1' */
806-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
838+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1))
807839
dev_err(etm_dev,
808840
"timeout while waiting for PM stable Trace Status\n");
841+
/*
842+
* As recommended by section 4.3.7 (Synchronization of register updates)
843+
* of ARM IHI 0064H.b.
844+
*/
845+
isb();
846+
809847
/* read the status of the single shot comparators */
810848
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
811849
config->ss_status[i] =
@@ -1582,7 +1620,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
15821620
etm4_os_lock(drvdata);
15831621

15841622
/* wait for TRCSTATR.PMSTABLE to go up */
1585-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) {
1623+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) {
15861624
dev_err(etm_dev,
15871625
"timeout while waiting for PM Stable Status\n");
15881626
etm4_os_unlock(drvdata);
@@ -1672,7 +1710,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
16721710
state->trcpdcr = etm4x_read32(csa, TRCPDCR);
16731711

16741712
/* wait for TRCSTATR.IDLE to go up */
1675-
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
1713+
if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) {
16761714
dev_err(etm_dev,
16771715
"timeout while waiting for Idle Trace Status\n");
16781716
etm4_os_unlock(drvdata);

include/linux/coresight.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ extern int coresight_enable(struct coresight_device *csdev);
475475
extern void coresight_disable(struct coresight_device *csdev);
476476
extern int coresight_timeout(struct csdev_access *csa, u32 offset,
477477
int position, int value);
478+
typedef void (*coresight_timeout_cb_t) (struct csdev_access *, u32, int, int);
479+
extern int coresight_timeout_action(struct csdev_access *csa, u32 offset,
480+
int position, int value,
481+
coresight_timeout_cb_t cb);
478482

479483
extern int coresight_claim_device(struct coresight_device *csdev);
480484
extern int coresight_claim_device_unlocked(struct coresight_device *csdev);

0 commit comments

Comments
 (0)