]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
coresight: etm4x: Safe access for TRCQCLTR
authorSuzuki K Poulose <suzuki.poulose@arm.com>
Fri, 12 Apr 2024 14:27:01 +0000 (15:27 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jun 2024 11:39:37 +0000 (13:39 +0200)
[ Upstream commit 46bf8d7cd8530eca607379033b9bc4ac5590a0cd ]

ETM4x implements TRCQCLTR only when the Q elements are supported
and the Q element filtering is supported (TRCIDR0.QFILT). Access
to the register otherwise could be fatal. Fix this by tracking the
availability, like the others.

Fixes: f188b5e76aae ("coresight: etm4x: Save/restore state across CPU low power states")
Reported-by: Yabin Cui <yabinc@google.com>
Reviewed-by: Mike Leach <mike.leach@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Tested-by: Yabin Cui <yabinc@google.com>
Link: https://lore.kernel.org/r/20240412142702.2882478-4-suzuki.poulose@arm.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hwtracing/coresight/coresight-etm4x-core.c
drivers/hwtracing/coresight/coresight-etm4x.h

index ed5b38013dc140c46821a9d22ad5da09827cc2ae..130e9030a8bef9d0dc705607b9cafe70cf2b5290 100644 (file)
@@ -1061,6 +1061,8 @@ static void etm4_init_arch_data(void *info)
        drvdata->nr_event = FIELD_GET(TRCIDR0_NUMEVENT_MASK, etmidr0);
        /* QSUPP, bits[16:15] Q element support field */
        drvdata->q_support = FIELD_GET(TRCIDR0_QSUPP_MASK, etmidr0);
+       if (drvdata->q_support)
+               drvdata->q_filt = !!(etmidr0 & TRCIDR0_QFILT);
        /* TSSIZE, bits[28:24] Global timestamp size field */
        drvdata->ts_size = FIELD_GET(TRCIDR0_TSSIZE_MASK, etmidr0);
 
@@ -1582,7 +1584,8 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
        state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
        state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
        state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
-       state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
+       if (drvdata->q_filt)
+               state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
 
        state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
        state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
@@ -1696,7 +1699,8 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
        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);
+       if (drvdata->q_filt)
+               etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
 
        etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
        etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
index c463dab350397aba0ceaa5b58c7b8aad7faa9c86..3ab528c6b91f1b543c01cf56e60ee89a81c22a6f 100644 (file)
 #define TRCIDR0_TRCCCI                         BIT(7)
 #define TRCIDR0_RETSTACK                       BIT(9)
 #define TRCIDR0_NUMEVENT_MASK                  GENMASK(11, 10)
+#define TRCIDR0_QFILT                          BIT(14)
 #define TRCIDR0_QSUPP_MASK                     GENMASK(16, 15)
 #define TRCIDR0_TSSIZE_MASK                    GENMASK(28, 24)
 
@@ -880,6 +881,7 @@ struct etmv4_save_state {
  * @os_unlock:  True if access to management registers is allowed.
  * @instrp0:   Tracing of load and store instructions
  *             as P0 elements is supported.
+ * @q_filt:    Q element filtering support, if Q elements are supported.
  * @trcbb:     Indicates if the trace unit supports branch broadcast tracing.
  * @trccond:   If the trace unit supports conditional
  *             instruction tracing.
@@ -938,6 +940,7 @@ struct etmv4_drvdata {
        bool                            boot_enable;
        bool                            os_unlock;
        bool                            instrp0;
+       bool                            q_filt;
        bool                            trcbb;
        bool                            trccond;
        bool                            retstack;