coresight: etm4x: Add support for PE OS lock
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Mon, 5 Apr 2021 16:42:58 +0000 (17:42 +0100)
committerMathieu Poirier <mathieu.poirier@linaro.org>
Tue, 6 Apr 2021 22:05:37 +0000 (16:05 -0600)
ETE may not implement the OS lock and instead could rely on
the PE OS Lock for the trace unit access. This is indicated
by the TRCOLSR.OSM == 0b100. Add support for handling the
PE OS lock

Cc: Mike Leach <mike.leach@linaro.org>
Reviewed-by: mike.leach <mike.leach@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20210405164307.1720226-12-suzuki.poulose@arm.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
drivers/hwtracing/coresight/coresight-etm4x-core.c
drivers/hwtracing/coresight/coresight-etm4x.h

index 0029790..35802ca 100644 (file)
@@ -115,30 +115,59 @@ void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit)
        }
 }
 
-static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa)
+static void etm_detect_os_lock(struct etmv4_drvdata *drvdata,
+                              struct csdev_access *csa)
 {
-       /* Writing 0 to TRCOSLAR unlocks the trace registers */
-       etm4x_relaxed_write32(csa, 0x0, TRCOSLAR);
-       drvdata->os_unlock = true;
+       u32 oslsr = etm4x_relaxed_read32(csa, TRCOSLSR);
+
+       drvdata->os_lock_model = ETM_OSLSR_OSLM(oslsr);
+}
+
+static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
+                             struct csdev_access *csa, u32 val)
+{
+       val = !!val;
+
+       switch (drvdata->os_lock_model) {
+       case ETM_OSLOCK_PRESENT:
+               etm4x_relaxed_write32(csa, val, TRCOSLAR);
+               break;
+       case ETM_OSLOCK_PE:
+               write_sysreg_s(val, SYS_OSLAR_EL1);
+               break;
+       default:
+               pr_warn_once("CPU%d: Unsupported Trace OSLock model: %x\n",
+                            smp_processor_id(), drvdata->os_lock_model);
+               fallthrough;
+       case ETM_OSLOCK_NI:
+               return;
+       }
        isb();
 }
 
+static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
+                                     struct csdev_access *csa)
+{
+       WARN_ON(drvdata->cpu != smp_processor_id());
+
+       /* Writing 0 to OS Lock unlocks the trace unit registers */
+       etm_write_os_lock(drvdata, csa, 0x0);
+       drvdata->os_unlock = true;
+}
+
 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 */
-       etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR);
+       /* Writing 0x1 to OS Lock locks the trace registers */
+       etm_write_os_lock(drvdata, &drvdata->csdev->access, 0x1);
        drvdata->os_unlock = false;
-       isb();
 }
 
 static void etm4_cs_lock(struct etmv4_drvdata *drvdata,
@@ -937,6 +966,9 @@ static void etm4_init_arch_data(void *info)
        if (!etm4_init_csdev_access(drvdata, csa))
                return;
 
+       /* Detect the support for OS Lock before we actually use it */
+       etm_detect_os_lock(drvdata, csa);
+
        /* Make sure all registers are accessible */
        etm4_os_unlock_csa(drvdata, csa);
        etm4_cs_unlock(drvdata, csa);
index f6478ef..5b961c5 100644 (file)
                                         ETM_MODE_EXCL_KERN | \
                                         ETM_MODE_EXCL_USER)
 
+/*
+ * TRCOSLSR.OSLM advertises the OS Lock model.
+ * OSLM[2:0] = TRCOSLSR[4:3,0]
+ *
+ *     0b000 - Trace OS Lock is not implemented.
+ *     0b010 - Trace OS Lock is implemented.
+ *     0b100 - Trace OS Lock is not implemented, unit is controlled by PE OS Lock.
+ */
+#define ETM_OSLOCK_NI          0b000
+#define ETM_OSLOCK_PRESENT     0b010
+#define ETM_OSLOCK_PE          0b100
+
+#define ETM_OSLSR_OSLM(oslsr)  ((((oslsr) & GENMASK(4, 3)) >> 2) | (oslsr & 0x1))
+
 /*
  * TRCDEVARCH Bit field definitions
  * Bits[31:21] - ARCHITECT = Always Arm Ltd.
@@ -898,6 +912,7 @@ struct etmv4_drvdata {
        u8                              s_ex_level;
        u8                              ns_ex_level;
        u8                              q_support;
+       u8                              os_lock_model;
        bool                            sticky_enable;
        bool                            boot_enable;
        bool                            os_unlock;