2020-09-03 11:57:07

by liuqi (BA)

[permalink] [raw]
Subject: [PATCH] coresight: etm4x: Modify core-commit of cpu to avoid the overflow of HiSilicon ETM

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