The ETM device can't keep up with the core pipeline when cpu core is at full speed. This may cause overflow within core and its ETM. This is a common phenomenon on ETM devices.
On HiSilicon Hip08 platform, a specific feature is added to set core pipeline. So commit rate can be reduced manually to avoid ETM overflow. Signed-off-by: Qi Liu <[email protected]> --- link of the RFC patch: https://lore.kernel.org/linux-arm-kernel/[email protected]/ drivers/hwtracing/coresight/coresight-etm4x.c | 46 +++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7bcac88..5833be1 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -45,6 +45,10 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, static enum cpuhp_state hp_online; +#define HISI_HIP08_CORE_COMMIT_CLEAR 0x3000 +#define HISI_HIP08_CORE_COMMIT_SHIFT 12 +#define HISI_HIP08_ETM_ID 0x000b6d01 + static void etm4_os_unlock(struct etmv4_drvdata *drvdata) { /* Writing any value to ETMOSLAR unlocks the trace registers */ @@ -84,12 +88,38 @@ struct etm4_enable_arg { int rc; }; +static void etm4_hisi_config_core_commit(int flag) +{ + u64 val; + + asm volatile("mrs %0,s3_1_c15_c2_5" : "=r"(val)); + val &= ~HISI_HIP08_CORE_COMMIT_CLEAR; + val |= flag << HISI_HIP08_CORE_COMMIT_SHIFT; + asm volatile("msr s3_1_c15_c2_5,%0" : : "r"(val)); +} + +static void etm4_enable_arch_specific(struct etmv4_drvdata *drvdata) +{ + struct device *dev = drvdata->csdev->dev.parent; + struct amba_device *adev; + + adev = container_of(dev, struct amba_device, dev); + + /* + * If ETM device is HiSilicon ETM device, reduce the + * core-commit to avoid ETM overflow. + */ + if (adev->periphid == HISI_HIP08_ETM_ID) + etm4_hisi_config_core_commit(1); +} + 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; + etm4_enable_arch_specific(drvdata); CS_UNLOCK(drvdata->base); etm4_os_unlock(drvdata); @@ -436,11 +466,27 @@ static int etm4_enable(struct coresight_device *csdev, return ret; } +static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata) +{ + struct device *dev = drvdata->csdev->dev.parent; + struct amba_device *adev; + + adev = container_of(dev, struct amba_device, dev); + + /* + * If ETM device is HiSilicon ETM device, resume the + * core-commit after ETM trace is complete. + */ + if (adev->periphid == HISI_HIP08_ETM_ID) + etm4_hisi_config_core_commit(0); +} + static void etm4_disable_hw(void *info) { u32 control; struct etmv4_drvdata *drvdata = info; + etm4_disable_arch_specific(drvdata); CS_UNLOCK(drvdata->base); /* power can be removed from the trace unit now */ -- 2.8.1

