Skip to content

Commit 8a10651

Browse files
Suzuki K Poulosemathieupoirier
authored andcommitted
coresight: trbe: Add infrastructure for Errata handling
Add a minimal infrastructure to keep track of the errata affecting the given TRBE instance. Given that we have heterogeneous CPUs, we have to manage the list per-TRBE instance to be able to apply the work around as needed. Thus we will need to check if individual CPUs are affected by the erratum. We rely on the arm64 errata framework for the actual description and the discovery of a given erratum, to keep the Erratum work around at a central place and benefit from the code and the advertisement from the kernel. Though we could reuse the "this_cpu_has_cap()" to apply an erratum work around, it is a bit of a heavy operation, as it must go through the "erratum" detection check on the CPU every time it is called (e.g, scanning through a table of affected MIDRs). Since we need to do this check for every session, may be multiple times (depending on the wrok around), we could save the cycles by caching the affected errata per-CPU instance in the per-CPU struct trbe_cpudata. Since we are only interested in the errata affecting the TRBE driver, we only need to track a very few of them per-CPU. Thus we use a local mapping of the CPUCAP for the erratum to avoid bloating up a bitmap for trbe_cpudata. i.e, each arm64 TRBE erratum bit is assigned a "index" within the driver to track. Each trbe instance updates the list of affected erratum at probe time on the CPU. This makes sure that we can easily access the list of errata on a given TRBE instance without much overhead. Cc: Mathieu Poirier <[email protected]> Cc: Mike Leach <[email protected]> Cc: Leo Yan <[email protected]> Cc: Anshuman Khandual <[email protected]> Reviewed-by: Anshuman Khandual <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mathieu Poirier <[email protected]>
1 parent e4bc882 commit 8a10651

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

drivers/hwtracing/coresight/coresight-trbe.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#define pr_fmt(fmt) DRVNAME ": " fmt
1717

1818
#include <asm/barrier.h>
19+
#include <asm/cpufeature.h>
20+
1921
#include "coresight-self-hosted-trace.h"
2022
#include "coresight-trbe.h"
2123

@@ -67,6 +69,34 @@ struct trbe_buf {
6769
struct trbe_cpudata *cpudata;
6870
};
6971

72+
/*
73+
* TRBE erratum list
74+
*
75+
* The errata are defined in arm64 generic cpu_errata framework.
76+
* Since the errata work arounds could be applied individually
77+
* to the affected CPUs inside the TRBE driver, we need to know if
78+
* a given CPU is affected by the erratum. Unlike the other erratum
79+
* work arounds, TRBE driver needs to check multiple times during
80+
* a trace session. Thus we need a quicker access to per-CPU
81+
* errata and not issue costly this_cpu_has_cap() everytime.
82+
* We keep a set of the affected errata in trbe_cpudata, per TRBE.
83+
*
84+
* We rely on the corresponding cpucaps to be defined for a given
85+
* TRBE erratum. We map the given cpucap into a TRBE internal number
86+
* to make the tracking of the errata lean.
87+
*
88+
* This helps in :
89+
* - Not duplicating the detection logic
90+
* - Streamlined detection of erratum across the system
91+
*/
92+
93+
static int trbe_errata_cpucaps[] = {
94+
-1, /* Sentinel, must be the last entry */
95+
};
96+
97+
/* The total number of listed errata in trbe_errata_cpucaps */
98+
#define TRBE_ERRATA_MAX (ARRAY_SIZE(trbe_errata_cpucaps) - 1)
99+
70100
/*
71101
* struct trbe_cpudata: TRBE instance specific data
72102
* @trbe_flag - TRBE dirty/access flag support
@@ -75,6 +105,7 @@ struct trbe_buf {
75105
* @cpu - CPU this TRBE belongs to.
76106
* @mode - Mode of current operation. (perf/disabled)
77107
* @drvdata - TRBE specific drvdata
108+
* @errata - Bit map for the errata on this TRBE.
78109
*/
79110
struct trbe_cpudata {
80111
bool trbe_flag;
@@ -84,6 +115,7 @@ struct trbe_cpudata {
84115
enum cs_mode mode;
85116
struct trbe_buf *buf;
86117
struct trbe_drvdata *drvdata;
118+
DECLARE_BITMAP(errata, TRBE_ERRATA_MAX);
87119
};
88120

89121
struct trbe_drvdata {
@@ -96,6 +128,25 @@ struct trbe_drvdata {
96128
struct platform_device *pdev;
97129
};
98130

131+
static void trbe_check_errata(struct trbe_cpudata *cpudata)
132+
{
133+
int i;
134+
135+
for (i = 0; i < TRBE_ERRATA_MAX; i++) {
136+
int cap = trbe_errata_cpucaps[i];
137+
138+
if (WARN_ON_ONCE(cap < 0))
139+
return;
140+
if (this_cpu_has_cap(cap))
141+
set_bit(i, cpudata->errata);
142+
}
143+
}
144+
145+
static inline bool trbe_has_erratum(struct trbe_cpudata *cpudata, int i)
146+
{
147+
return (i < TRBE_ERRATA_MAX) && test_bit(i, cpudata->errata);
148+
}
149+
99150
static int trbe_alloc_node(struct perf_event *event)
100151
{
101152
if (event->cpu == -1)
@@ -956,6 +1007,9 @@ static void arm_trbe_register_coresight_cpu(struct trbe_drvdata *drvdata, int cp
9561007
cpumask_clear_cpu(cpu, &drvdata->supported_cpus);
9571008
}
9581009

1010+
/*
1011+
* Must be called with preemption disabled, for trbe_check_errata().
1012+
*/
9591013
static void arm_trbe_probe_cpu(void *info)
9601014
{
9611015
struct trbe_drvdata *drvdata = info;
@@ -983,6 +1037,12 @@ static void arm_trbe_probe_cpu(void *info)
9831037
goto cpu_clear;
9841038
}
9851039

1040+
/*
1041+
* Run the TRBE erratum checks, now that we know
1042+
* this instance is about to be registered.
1043+
*/
1044+
trbe_check_errata(cpudata);
1045+
9861046
cpudata->trbe_align = cpudata->trbe_hw_align;
9871047
cpudata->trbe_flag = get_trbe_flag_update(trbidr);
9881048
cpudata->cpu = cpu;
@@ -1038,6 +1098,13 @@ static int arm_trbe_remove_coresight(struct trbe_drvdata *drvdata)
10381098
return 0;
10391099
}
10401100

1101+
static void arm_trbe_probe_hotplugged_cpu(struct trbe_drvdata *drvdata)
1102+
{
1103+
preempt_disable();
1104+
arm_trbe_probe_cpu(drvdata);
1105+
preempt_enable();
1106+
}
1107+
10411108
static int arm_trbe_cpu_startup(unsigned int cpu, struct hlist_node *node)
10421109
{
10431110
struct trbe_drvdata *drvdata = hlist_entry_safe(node, struct trbe_drvdata, hotplug_node);
@@ -1049,7 +1116,7 @@ static int arm_trbe_cpu_startup(unsigned int cpu, struct hlist_node *node)
10491116
* initialize it now.
10501117
*/
10511118
if (!coresight_get_percpu_sink(cpu)) {
1052-
arm_trbe_probe_cpu(drvdata);
1119+
arm_trbe_probe_hotplugged_cpu(drvdata);
10531120
if (cpumask_test_cpu(cpu, &drvdata->supported_cpus))
10541121
arm_trbe_register_coresight_cpu(drvdata, cpu);
10551122
if (cpumask_test_cpu(cpu, &drvdata->supported_cpus))

0 commit comments

Comments
 (0)