Commit 28eb3b36 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'coresight-next-v5.16.v3' of...

Merge tag 'coresight-next-v5.16.v3' of gitolite.kernel.org:pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Mathieu writes:

Coresight changes for v5.16

- A new option to make coresight cpu-debug capabilities available as early
as possible in the kernel boot process.

- Make trace sessions more enduring by coping with scenarios where events
are scheduled on CPUs that can't reach the selected sink.

- A set of improvement to make the TMC-ETR driver more efficient.

- Enhancements to the TRBE driver to correct several errata.

- An enhancement to make the AXI burts size configurable for TMC devices
that can't work with the default value.

- A fix in the CTI module to use the correct device when calling
pm_runtime_put()

- The addition of the Kryo-5xx device to the list of support ETMs.
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>

* tag 'coresight-next-v5.16.v3' of gitolite.kernel.org:pub/scm/linux/kernel/git/coresight/linux: (39 commits)
  arm64: errata: Enable TRBE workaround for write to out-of-range address
  arm64: errata: Enable workaround for TRBE overwrite in FILL mode
  coresight: trbe: Work around write to out of range
  coresight: trbe: Make sure we have enough space
  coresight: trbe: Add a helper to determine the minimum buffer size
  coresight: trbe: Workaround TRBE errata overwrite in FILL mode
  coresight: trbe: Add infrastructure for Errata handling
  coresight: trbe: Allow driver to choose a different alignment
  coresight: trbe: Decouple buffer base from the hardware base
  coresight: trbe: Add a helper to pad a given buffer area
  coresight: trbe: Add a helper to calculate the trace generated
  coresight: trbe: Defer the probe on offline CPUs
  coresight: trbe: Fix incorrect access of the sink specific data
  coresight: etm4x: Add ETM PID for Kryo-5XX
  coresight: trbe: Prohibit trace before disabling TRBE
  coresight: trbe: End the AUX handle on truncation
  coresight: trbe: Do not truncate buffer on IRQ
  coresight: trbe: Fix handling of spurious interrupts
  coresight: trbe: irq handler: Do not disable TRBE if no action is needed
  coresight: trbe: Unify the enabling sequence
  ...
parents 27182be9 561ced0b
...@@ -92,12 +92,24 @@ stable kernels. ...@@ -92,12 +92,24 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A77 | #1508412 | ARM64_ERRATUM_1508412 | | ARM | Cortex-A77 | #1508412 | ARM64_ERRATUM_1508412 |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 | | ARM | Neoverse-N1 | #1188873,1418040| ARM64_ERRATUM_1418040 |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1349291 | N/A | | ARM | Neoverse-N1 | #1349291 | N/A |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | | ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2139208 | ARM64_ERRATUM_2139208 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2067961 | ARM64_ERRATUM_2067961 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Neoverse-N2 | #2253138 | ARM64_ERRATUM_2253138 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | MMU-500 | #841119,826419 | N/A | | ARM | MMU-500 | #841119,826419 | N/A |
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+
......
...@@ -127,6 +127,11 @@ its hardware characteristcs. ...@@ -127,6 +127,11 @@ its hardware characteristcs.
* arm,scatter-gather: boolean. Indicates that the TMC-ETR can safely * arm,scatter-gather: boolean. Indicates that the TMC-ETR can safely
use the SG mode on this system. use the SG mode on this system.
* arm,max-burst-size: The maximum burst size initiated by TMC on the
AXI master interface. The burst size can be in the range [0..15],
the setting supports one data transfer per burst up to a maximum of
16 data transfers per burst.
* Optional property for CATU : * Optional property for CATU :
* interrupts : Exactly one SPI may be listed for reporting the address * interrupts : Exactly one SPI may be listed for reporting the address
error error
......
...@@ -666,6 +666,117 @@ config ARM64_ERRATUM_1508412 ...@@ -666,6 +666,117 @@ config ARM64_ERRATUM_1508412
If unsure, say Y. If unsure, say Y.
config ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
bool
config ARM64_ERRATUM_2119858
bool "Cortex-A710: 2119858: workaround TRBE overwriting trace data in FILL mode"
default y
depends on CORESIGHT_TRBE
select ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
help
This option adds the workaround for ARM Cortex-A710 erratum 2119858.
Affected Cortex-A710 cores could overwrite up to 3 cache lines of trace
data at the base of the buffer (pointed to by TRBASER_EL1) in FILL mode in
the event of a WRAP event.
Work around the issue by always making sure we move the TRBPTR_EL1 by
256 bytes before enabling the buffer and filling the first 256 bytes of
the buffer with ETM ignore packets upon disabling.
If unsure, say Y.
config ARM64_ERRATUM_2139208
bool "Neoverse-N2: 2139208: workaround TRBE overwriting trace data in FILL mode"
default y
depends on CORESIGHT_TRBE
select ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
help
This option adds the workaround for ARM Neoverse-N2 erratum 2139208.
Affected Neoverse-N2 cores could overwrite up to 3 cache lines of trace
data at the base of the buffer (pointed to by TRBASER_EL1) in FILL mode in
the event of a WRAP event.
Work around the issue by always making sure we move the TRBPTR_EL1 by
256 bytes before enabling the buffer and filling the first 256 bytes of
the buffer with ETM ignore packets upon disabling.
If unsure, say Y.
config ARM64_WORKAROUND_TSB_FLUSH_FAILURE
bool
config ARM64_ERRATUM_2054223
bool "Cortex-A710: 2054223: workaround TSB instruction failing to flush trace"
default y
select ARM64_WORKAROUND_TSB_FLUSH_FAILURE
help
Enable workaround for ARM Cortex-A710 erratum 2054223
Affected cores may fail to flush the trace data on a TSB instruction, when
the PE is in trace prohibited state. This will cause losing a few bytes
of the trace cached.
Workaround is to issue two TSB consecutively on affected cores.
If unsure, say Y.
config ARM64_ERRATUM_2067961
bool "Neoverse-N2: 2067961: workaround TSB instruction failing to flush trace"
default y
select ARM64_WORKAROUND_TSB_FLUSH_FAILURE
help
Enable workaround for ARM Neoverse-N2 erratum 2067961
Affected cores may fail to flush the trace data on a TSB instruction, when
the PE is in trace prohibited state. This will cause losing a few bytes
of the trace cached.
Workaround is to issue two TSB consecutively on affected cores.
If unsure, say Y.
config ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
bool
config ARM64_ERRATUM_2253138
bool "Neoverse-N2: 2253138: workaround TRBE writing to address out-of-range"
depends on CORESIGHT_TRBE
default y
select ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
help
This option adds the workaround for ARM Neoverse-N2 erratum 2253138.
Affected Neoverse-N2 cores might write to an out-of-range address, not reserved
for TRBE. Under some conditions, the TRBE might generate a write to the next
virtually addressed page following the last page of the TRBE address space
(i.e., the TRBLIMITR_EL1.LIMIT), instead of wrapping around to the base.
Work around this in the driver by always making sure that there is a
page beyond the TRBLIMITR_EL1.LIMIT, within the space allowed for the TRBE.
If unsure, say Y.
config ARM64_ERRATUM_2224489
bool "Cortex-A710: 2224489: workaround TRBE writing to address out-of-range"
depends on CORESIGHT_TRBE
default y
select ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
help
This option adds the workaround for ARM Cortex-A710 erratum 2224489.
Affected Cortex-A710 cores might write to an out-of-range address, not reserved
for TRBE. Under some conditions, the TRBE might generate a write to the next
virtually addressed page following the last page of the TRBE address space
(i.e., the TRBLIMITR_EL1.LIMIT), instead of wrapping around to the base.
Work around this in the driver by always making sure that there is a
page beyond the TRBLIMITR_EL1.LIMIT, within the space allowed for the TRBE.
If unsure, say Y.
config CAVIUM_ERRATUM_22375 config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313" bool "Cavium erratum 22375, 24313"
default y default y
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#define dsb(opt) asm volatile("dsb " #opt : : : "memory") #define dsb(opt) asm volatile("dsb " #opt : : : "memory")
#define psb_csync() asm volatile("hint #17" : : : "memory") #define psb_csync() asm volatile("hint #17" : : : "memory")
#define tsb_csync() asm volatile("hint #18" : : : "memory") #define __tsb_csync() asm volatile("hint #18" : : : "memory")
#define csdb() asm volatile("hint #20" : : : "memory") #define csdb() asm volatile("hint #20" : : : "memory")
#ifdef CONFIG_ARM64_PSEUDO_NMI #ifdef CONFIG_ARM64_PSEUDO_NMI
...@@ -46,6 +46,20 @@ ...@@ -46,6 +46,20 @@
#define dma_rmb() dmb(oshld) #define dma_rmb() dmb(oshld)
#define dma_wmb() dmb(oshst) #define dma_wmb() dmb(oshst)
#define tsb_csync() \
do { \
/* \
* CPUs affected by Arm Erratum 2054223 or 2067961 needs \
* another TSB to ensure the trace is flushed. The barriers \
* don't have to be strictly back to back, as long as the \
* CPU is in trace prohibited state. \
*/ \
if (cpus_have_final_cap(ARM64_WORKAROUND_TSB_FLUSH_FAILURE)) \
__tsb_csync(); \
__tsb_csync(); \
} while (0)
/* /*
* Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz * Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz
* and 0 otherwise. * and 0 otherwise.
......
...@@ -73,6 +73,8 @@ ...@@ -73,6 +73,8 @@
#define ARM_CPU_PART_CORTEX_A76 0xD0B #define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C #define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_CORTEX_A77 0xD0D #define ARM_CPU_PART_CORTEX_A77 0xD0D
#define ARM_CPU_PART_CORTEX_A710 0xD47
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define APM_CPU_PART_POTENZA 0x000 #define APM_CPU_PART_POTENZA 0x000
...@@ -113,6 +115,8 @@ ...@@ -113,6 +115,8 @@
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
......
...@@ -340,6 +340,42 @@ static const struct midr_range erratum_1463225[] = { ...@@ -340,6 +340,42 @@ static const struct midr_range erratum_1463225[] = {
}; };
#endif #endif
#ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
static const struct midr_range trbe_overwrite_fill_mode_cpus[] = {
#ifdef CONFIG_ARM64_ERRATUM_2139208
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
#endif
#ifdef CONFIG_ARM64_ERRATUM_2119858
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
#endif
{},
};
#endif /* CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE */
#ifdef CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE
static const struct midr_range tsb_flush_fail_cpus[] = {
#ifdef CONFIG_ARM64_ERRATUM_2067961
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
#endif
#ifdef CONFIG_ARM64_ERRATUM_2054223
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
#endif
{},
};
#endif /* CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE */
#ifdef CONFIG_ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
static struct midr_range trbe_write_out_of_range_cpus[] = {
#ifdef CONFIG_ARM64_ERRATUM_2253138
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
#endif
#ifdef CONFIG_ARM64_ERRATUM_2224489
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
#endif
{},
};
#endif /* CONFIG_ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE */
const struct arm64_cpu_capabilities arm64_errata[] = { const struct arm64_cpu_capabilities arm64_errata[] = {
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
{ {
...@@ -533,6 +569,34 @@ const struct arm64_cpu_capabilities arm64_errata[] = { ...@@ -533,6 +569,34 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
.capability = ARM64_WORKAROUND_NVIDIA_CARMEL_CNP, .capability = ARM64_WORKAROUND_NVIDIA_CARMEL_CNP,
ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL), ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
}, },
#endif
#ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
{
/*
* The erratum work around is handled within the TRBE
* driver and can be applied per-cpu. So, we can allow
* a late CPU to come online with this erratum.
*/
.desc = "ARM erratum 2119858 or 2139208",
.capability = ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE,
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
CAP_MIDR_RANGE_LIST(trbe_overwrite_fill_mode_cpus),
},
#endif
#ifdef CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE
{
.desc = "ARM erratum 2067961 or 2054223",
.capability = ARM64_WORKAROUND_TSB_FLUSH_FAILURE,
ERRATA_MIDR_RANGE_LIST(tsb_flush_fail_cpus),
},
#endif
#ifdef CONFIG_ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
{
.desc = "ARM erratum 2253138 or 2224489",
.capability = ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE,
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus),
},
#endif #endif
{ {
} }
......
...@@ -53,6 +53,9 @@ WORKAROUND_1418040 ...@@ -53,6 +53,9 @@ WORKAROUND_1418040
WORKAROUND_1463225 WORKAROUND_1463225
WORKAROUND_1508412 WORKAROUND_1508412
WORKAROUND_1542419 WORKAROUND_1542419
WORKAROUND_TRBE_OVERWRITE_FILL_MODE
WORKAROUND_TSB_FLUSH_FAILURE
WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
WORKAROUND_CAVIUM_23154 WORKAROUND_CAVIUM_23154
WORKAROUND_CAVIUM_27456 WORKAROUND_CAVIUM_27456
WORKAROUND_CAVIUM_30115 WORKAROUND_CAVIUM_30115
......
...@@ -150,6 +150,19 @@ config CORESIGHT_CPU_DEBUG ...@@ -150,6 +150,19 @@ config CORESIGHT_CPU_DEBUG
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called coresight-cpu-debug. module will be called coresight-cpu-debug.
config CORESIGHT_CPU_DEBUG_DEFAULT_ON
bool "Enable CoreSight CPU Debug by default"
depends on CORESIGHT_CPU_DEBUG
help
Say Y here to enable the CoreSight Debug panic-debug by default. This
can also be enabled via debugfs, but this ensures the debug feature
is enabled as early as possible.
Has the same effect as setting coresight_cpu_debug.enable=1 on the
kernel command line.
Say N if unsure.
config CORESIGHT_CTI config CORESIGHT_CTI
tristate "CoreSight Cross Trigger Interface (CTI) driver" tristate "CoreSight Cross Trigger Interface (CTI) driver"
depends on ARM || ARM64 depends on ARM || ARM64
......
...@@ -105,7 +105,7 @@ static DEFINE_PER_CPU(struct debug_drvdata *, debug_drvdata); ...@@ -105,7 +105,7 @@ static DEFINE_PER_CPU(struct debug_drvdata *, debug_drvdata);
static int debug_count; static int debug_count;
static struct dentry *debug_debugfs_dir; static struct dentry *debug_debugfs_dir;
static bool debug_enable; static bool debug_enable = IS_ENABLED(CONFIG_CORESIGHT_CPU_DEBUG_DEFAULT_ON);
module_param_named(enable, debug_enable, bool, 0600); module_param_named(enable, debug_enable, bool, 0600);
MODULE_PARM_DESC(enable, "Control to enable coresight CPU debug functionality"); MODULE_PARM_DESC(enable, "Control to enable coresight CPU debug functionality");
......
...@@ -175,7 +175,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) ...@@ -175,7 +175,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
coresight_disclaim_device_unlocked(csdev); coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base); CS_LOCK(drvdata->base);
spin_unlock(&drvdata->spinlock); spin_unlock(&drvdata->spinlock);
pm_runtime_put(dev); pm_runtime_put(dev->parent);
return 0; return 0;
/* not disabled this call */ /* not disabled this call */
......
...@@ -557,9 +557,8 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, ...@@ -557,9 +557,8 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev,
/* /*
* In snapshot mode we simply increment the head by the number of byte * In snapshot mode we simply increment the head by the number of byte
* that were written. User space function cs_etm_find_snapshot() will * that were written. User space will figure out how many bytes to get
* figure out how many bytes to get from the AUX buffer based on the * from the AUX buffer based on the position of the head.
* position of the head.
*/ */
if (buf->snapshot) if (buf->snapshot)
handle->head += to_read; handle->head += to_read;
......
...@@ -452,9 +452,14 @@ static void etm_event_start(struct perf_event *event, int flags) ...@@ -452,9 +452,14 @@ static void etm_event_start(struct perf_event *event, int flags)
* sink from this ETM. We can't do much in this case if * sink from this ETM. We can't do much in this case if
* the sink was specified or hinted to the driver. For * the sink was specified or hinted to the driver. For
* now, simply don't record anything on this ETM. * now, simply don't record anything on this ETM.
*
* As such we pretend that everything is fine, and let
* it continue without actually tracing. The event could
* continue tracing when it moves to a CPU where it is
* reachable to a sink.
*/ */
if (!cpumask_test_cpu(cpu, &event_data->mask)) if (!cpumask_test_cpu(cpu, &event_data->mask))
goto fail_end_stop; goto out;
path = etm_event_cpu_path(event_data, cpu); path = etm_event_cpu_path(event_data, cpu);
/* We need a sink, no need to continue without one */ /* We need a sink, no need to continue without one */
...@@ -466,26 +471,32 @@ static void etm_event_start(struct perf_event *event, int flags) ...@@ -466,26 +471,32 @@ static void etm_event_start(struct perf_event *event, int flags)
if (coresight_enable_path(path, CS_MODE_PERF, handle)) if (coresight_enable_path(path, CS_MODE_PERF, handle))
goto fail_end_stop; goto fail_end_stop;
/* Tell the perf core the event is alive */
event->hw.state = 0;
/* Finally enable the tracer */ /* Finally enable the tracer */
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF)) if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
goto fail_disable_path; goto fail_disable_path;
out:
/* Tell the perf core the event is alive */
event->hw.state = 0;
/* Save the event_data for this ETM */ /* Save the event_data for this ETM */
ctxt->event_data = event_data; ctxt->event_data = event_data;
out:
return; return;
fail_disable_path: fail_disable_path:
coresight_disable_path(path); coresight_disable_path(path);
fail_end_stop: fail_end_stop:
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED); /*
perf_aux_output_end(handle, 0); * Check if the handle is still associated with the event,
* to handle cases where if the sink failed to start the
* trace and TRUNCATED the handle already.
*/
if (READ_ONCE(handle->event)) {
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
perf_aux_output_end(handle, 0);
}
fail: fail:
event->hw.state = PERF_HES_STOPPED; event->hw.state = PERF_HES_STOPPED;
goto out; return;
} }
static void etm_event_stop(struct perf_event *event, int mode) static void etm_event_stop(struct perf_event *event, int mode)
...@@ -517,6 +528,19 @@ static void etm_event_stop(struct perf_event *event, int mode) ...@@ -517,6 +528,19 @@ static void etm_event_stop(struct perf_event *event, int mode)
if (WARN_ON(!event_data)) if (WARN_ON(!event_data))
return; return;
/*
* Check if this ETM was allowed to trace, as decided at
* etm_setup_aux(). If it wasn't allowed to trace, then
* nothing needs to be torn down other than outputting a
* zero sized record.
*/
if (handle->event && (mode & PERF_EF_UPDATE) &&
!cpumask_test_cpu(cpu, &event_data->mask)) {
event->hw.state = PERF_HES_STOPPED;
perf_aux_output_end(handle, 0);
return;
}
if (!csdev) if (!csdev)
return; return;
...@@ -550,7 +574,21 @@ static void etm_event_stop(struct perf_event *event, int mode) ...@@ -550,7 +574,21 @@ static void etm_event_stop(struct perf_event *event, int mode)
size = sink_ops(sink)->update_buffer(sink, handle, size = sink_ops(sink)->update_buffer(sink, handle,
event_data->snk_config); event_data->snk_config);
perf_aux_output_end(handle, size); /*
* Make sure the handle is still valid as the
* sink could have closed it from an IRQ.
* The sink driver must handle the race with
* update_buffer() and IRQ. Thus either we
* should get a valid handle and valid size
* (which may be 0).
*
* But we should never get a non-zero size with
* an invalid handle.
*/
if (READ_ONCE(handle->event))
perf_aux_output_end(handle, size);
else
WARN_ON(size);
} }
/* Disabling the path make its elements available to other sessions */ /* Disabling the path make its elements available to other sessions */
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "coresight-etm4x.h" #include "coresight-etm4x.h"
#include "coresight-etm-perf.h" #include "coresight-etm-perf.h"
#include "coresight-etm4x-cfg.h" #include "coresight-etm4x-cfg.h"
#include "coresight-self-hosted-trace.h"
#include "coresight-syscfg.h" #include "coresight-syscfg.h"
static int boot_enable; static int boot_enable;
...@@ -238,6 +239,45 @@ struct etm4_enable_arg { ...@@ -238,6 +239,45 @@ struct etm4_enable_arg {
int rc; int rc;
}; };
/*
* etm4x_prohibit_trace - Prohibit the CPU from tracing at all ELs.
* When the CPU supports FEAT_TRF, we could move the ETM to a trace
* prohibited state by filtering the Exception levels via TRFCR_EL1.
*/
static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
{
/* If the CPU doesn't support FEAT_TRF, nothing to do */
if (!drvdata->trfcr)
return;
cpu_prohibit_trace();
}
/*
* etm4x_allow_trace - Allow CPU tracing in the respective ELs,
* as configured by the drvdata->config.mode for the current
* session. Even though we have TRCVICTLR bits to filter the
* trace in the ELs, it doesn't prevent the ETM from generating
* a packet (e.g, TraceInfo) that might contain the addresses from
* the excluded levels. Thus we use the additional controls provided
* via the Trace Filtering controls (FEAT_TRF) to make sure no trace
* is generated for the excluded ELs.
*/
static void etm4x_allow_trace(struct etmv4_drvdata *drvdata)
{
u64 trfcr = drvdata->trfcr;
/* If the CPU doesn't support FEAT_TRF, nothing to do */
if (!trfcr)
return;
if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
trfcr &= ~TRFCR_ELx_ExTRE;
if (drvdata->config.mode & ETM_MODE_EXCL_USER)
trfcr &= ~TRFCR_ELx_E0TRE;
write_trfcr(trfcr);
}
#ifdef CONFIG_ETM4X_IMPDEF_FEATURE #ifdef CONFIG_ETM4X_IMPDEF_FEATURE
#define HISI_HIP08_AMBA_ID 0x000b6d01 #define HISI_HIP08_AMBA_ID 0x000b6d01
...@@ -442,6 +482,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) ...@@ -442,6 +482,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
if (etm4x_is_ete(drvdata)) if (etm4x_is_ete(drvdata))
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR); etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
etm4x_allow_trace(drvdata);
/* Enable the trace unit */ /* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR); etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
...@@ -737,7 +778,6 @@ static int etm4_enable(struct coresight_device *csdev, ...@@ -737,7 +778,6 @@ static int etm4_enable(struct coresight_device *csdev,
static void etm4_disable_hw(void *info) static void etm4_disable_hw(void *info)
{ {
u32 control; u32 control;
u64 trfcr;
struct etmv4_drvdata *drvdata = info; struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config; struct etmv4_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev; struct coresight_device *csdev = drvdata->csdev;
...@@ -764,12 +804,7 @@ static void etm4_disable_hw(void *info) ...@@ -764,12 +804,7 @@ static void etm4_disable_hw(void *info)
* If the CPU supports v8.4 Trace filter Control, * If the CPU supports v8.4 Trace filter Control,
* set the ETM to trace prohibited region. * set the ETM to trace prohibited region.
*/ */
if (drvdata->trfc) { etm4x_prohibit_trace(drvdata);
trfcr = read_sysreg_s(SYS_TRFCR_EL1);
write_sysreg_s(trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE),
SYS_TRFCR_EL1);
isb();
}
/* /*
* Make sure everything completes before disabling, as recommended * Make sure everything completes before disabling, as recommended
* by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register, * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
...@@ -785,9 +820,6 @@ static void etm4_disable_hw(void *info) ...@@ -785,9 +820,6 @@ static void etm4_disable_hw(void *info)
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
dev_err(etm_dev, dev_err(etm_dev,
"timeout while waiting for PM stable Trace Status\n"); "timeout while waiting for PM stable Trace Status\n");
if (drvdata->trfc)
write_sysreg_s(trfcr, SYS_TRFCR_EL1);
/* read the status of the single shot comparators */ /* read the status of the single shot comparators */
for (i = 0; i < drvdata->nr_ss_cmp; i++) { for (i = 0; i < drvdata->nr_ss_cmp; i++) {
config->ss_status[i] = config->ss_status[i] =
...@@ -989,15 +1021,15 @@ static bool etm4_init_csdev_access(struct etmv4_drvdata *drvdata, ...@@ -989,15 +1021,15 @@ static bool etm4_init_csdev_access(struct etmv4_drvdata *drvdata,
return false; return false;
} }
static void cpu_enable_tracing(struct etmv4_drvdata *drvdata) static void cpu_detect_trace_filtering(struct etmv4_drvdata *drvdata)
{ {
u64 dfr0 = read_sysreg(id_aa64dfr0_el1); u64 dfr0 = read_sysreg(id_aa64dfr0_el1);
u64 trfcr; u64 trfcr;
drvdata->trfcr = 0;
if (!cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_TRACE_FILT_SHIFT)) if (!cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_TRACE_FILT_SHIFT))
return; return;
drvdata->trfc = true;
/* /*
* If the CPU supports v8.4 SelfHosted Tracing, enable * If the CPU supports v8.4 SelfHosted Tracing, enable
* tracing at the kernel EL and EL0, forcing to use the * tracing at the kernel EL and EL0, forcing to use the
...@@ -1011,7 +1043,7 @@ static void cpu_enable_tracing(struct etmv4_drvdata *drvdata) ...@@ -1011,7 +1043,7 @@ static void cpu_enable_tracing(struct etmv4_drvdata *drvdata)
if (is_kernel_in_hyp_mode()) if (is_kernel_in_hyp_mode())
trfcr |= TRFCR_EL2_CX; trfcr |= TRFCR_EL2_CX;
write_sysreg_s(trfcr, SYS_TRFCR_EL1); drvdata->trfcr = trfcr;
} }
static void etm4_init_arch_data(void *info) static void etm4_init_arch_data(void *info)
...@@ -1202,7 +1234,7 @@ static void etm4_init_arch_data(void *info) ...@@ -1202,7 +1234,7 @@ static void etm4_init_arch_data(void *info)
/* NUMCNTR, bits[30:28] number of counters available for tracing */ /* NUMCNTR, bits[30:28] number of counters available for tracing */
drvdata->nr_cntr = BMVAL(etmidr5, 28, 30); drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
etm4_cs_lock(drvdata, csa); etm4_cs_lock(drvdata, csa);
cpu_enable_tracing(drvdata); cpu_detect_trace_filtering(drvdata);
} }
static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config) static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
...@@ -1554,7 +1586,7 @@ static void etm4_init_trace_id(struct etmv4_drvdata *drvdata) ...@@ -1554,7 +1586,7 @@ static void etm4_init_trace_id(struct etmv4_drvdata *drvdata)
drvdata->trcid = coresight_get_trace_id(drvdata->cpu); drvdata->trcid = coresight_get_trace_id(drvdata->cpu);
} }
static int etm4_cpu_save(struct etmv4_drvdata *drvdata) static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
{ {
int i, ret = 0; int i, ret = 0;
struct etmv4_save_state *state; struct etmv4_save_state *state;
...@@ -1693,7 +1725,23 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) ...@@ -1693,7 +1725,23 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
return ret; return ret;
} }
static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
{
int ret = 0;
/* Save the TRFCR irrespective of whether the ETM is ON */
if (drvdata->trfcr)
drvdata->save_trfcr = read_trfcr();
/*
* Save and restore the ETM Trace registers only if
* the ETM is active.
*/
if (local_read(&drvdata->mode) && drvdata->save_state)
ret = __etm4_cpu_save(drvdata);
return ret;
}
static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
{ {
int i; int i;
struct etmv4_save_state *state = drvdata->save_state; struct etmv4_save_state *state = drvdata->save_state;
...@@ -1789,6 +1837,14 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) ...@@ -1789,6 +1837,14 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
etm4_cs_lock(drvdata, csa); etm4_cs_lock(drvdata, csa);
} }
static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
{
if (drvdata->trfcr)
write_trfcr(drvdata->save_trfcr);
if (drvdata->state_needs_restore)
__etm4_cpu_restore(drvdata);
}
static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
void *v) void *v)
{ {
...@@ -1800,23 +1856,17 @@ static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, ...@@ -1800,23 +1856,17 @@ static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
drvdata = etmdrvdata[cpu]; drvdata = etmdrvdata[cpu];
if (!drvdata->save_state)
return NOTIFY_OK;
if (WARN_ON_ONCE(drvdata->cpu != cpu)) if (WARN_ON_ONCE(drvdata->cpu != cpu))
return NOTIFY_BAD; return NOTIFY_BAD;
switch (cmd) { switch (cmd) {
case CPU_PM_ENTER: case CPU_PM_ENTER:
/* save the state if self-hosted coresight is in use */ if (etm4_cpu_save(drvdata))
if (local_read(&drvdata->mode)) return NOTIFY_BAD;
if (etm4_cpu_save(drvdata))
return NOTIFY_BAD;
break; break;
case CPU_PM_EXIT: case CPU_PM_EXIT:
case CPU_PM_ENTER_FAILED: case CPU_PM_ENTER_FAILED:
if (drvdata->state_needs_restore) etm4_cpu_restore(drvdata);
etm4_cpu_restore(drvdata);
break; break;
default: default:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -2099,6 +2149,7 @@ static const struct amba_id etm4_ids[] = { ...@@ -2099,6 +2149,7 @@ static const struct amba_id etm4_ids[] = {
CS_AMBA_UCI_ID(0x000bb803, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A75 */ CS_AMBA_UCI_ID(0x000bb803, uci_id_etm4),/* Qualcomm Kryo 385 Cortex-A75 */
CS_AMBA_UCI_ID(0x000bb805, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A55 */ CS_AMBA_UCI_ID(0x000bb805, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A55 */
CS_AMBA_UCI_ID(0x000bb804, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A76 */ CS_AMBA_UCI_ID(0x000bb804, uci_id_etm4),/* Qualcomm Kryo 4XX Cortex-A76 */
CS_AMBA_UCI_ID(0x000bbd0d, uci_id_etm4),/* Qualcomm Kryo 5XX Cortex-A77 */
CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */ CS_AMBA_UCI_ID(0x000cc0af, uci_id_etm4),/* Marvell ThunderX2 */
CS_AMBA_UCI_ID(0x000b6d01, uci_id_etm4),/* HiSilicon-Hip08 */ CS_AMBA_UCI_ID(0x000b6d01, uci_id_etm4),/* HiSilicon-Hip08 */
CS_AMBA_UCI_ID(0x000b6d02, uci_id_etm4),/* HiSilicon-Hip09 */ CS_AMBA_UCI_ID(0x000b6d02, uci_id_etm4),/* HiSilicon-Hip09 */
......
...@@ -919,8 +919,12 @@ struct etmv4_save_state { ...@@ -919,8 +919,12 @@ struct etmv4_save_state {
* @nooverflow: Indicate if overflow prevention is supported. * @nooverflow: Indicate if overflow prevention is supported.
* @atbtrig: If the implementation can support ATB triggers * @atbtrig: If the implementation can support ATB triggers
* @lpoverride: If the implementation can support low-power state over. * @lpoverride: If the implementation can support low-power state over.
* @trfc: If the implementation supports Arm v8.4 trace filter controls. * @trfcr: If the CPU supports FEAT_TRF, value of the TRFCR_ELx that
* allows tracing at all ELs. We don't want to compute this
* at runtime, due to the additional setting of TRFCR_CX when
* in EL2. Otherwise, 0.
* @config: structure holding configuration parameters. * @config: structure holding configuration parameters.
* @save_trfcr: Saved TRFCR_EL1 register during a CPU PM event.
* @save_state: State to be preserved across power loss * @save_state: State to be preserved across power loss
* @state_needs_restore: True when there is context to restore after PM exit * @state_needs_restore: True when there is context to restore after PM exit
* @skip_power_up: Indicates if an implementation can skip powering up * @skip_power_up: Indicates if an implementation can skip powering up
...@@ -971,8 +975,9 @@ struct etmv4_drvdata { ...@@ -971,8 +975,9 @@ struct etmv4_drvdata {
bool nooverflow; bool nooverflow;
bool atbtrig; bool atbtrig;
bool lpoverride; bool lpoverride;
bool trfc; u64 trfcr;
struct etmv4_config config; struct etmv4_config config;
u64 save_trfcr;
struct etmv4_save_state *save_state; struct etmv4_save_state *save_state;
bool state_needs_restore; bool state_needs_restore;
bool skip_power_up; bool skip_power_up;
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Arm v8 Self-Hosted trace support.
*
* Copyright (C) 2021 ARM Ltd.
*/
#ifndef __CORESIGHT_SELF_HOSTED_TRACE_H
#define __CORESIGHT_SELF_HOSTED_TRACE_H
#include <asm/sysreg.h>
static inline u64 read_trfcr(void)
{
return read_sysreg_s(SYS_TRFCR_EL1);
}
static inline void write_trfcr(u64 val)
{
write_sysreg_s(val, SYS_TRFCR_EL1);
isb();
}
static inline u64 cpu_prohibit_trace(void)
{
u64 trfcr = read_trfcr();
/* Prohibit tracing at EL0 & the kernel EL */
write_trfcr(trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE));
/* Return the original value of the TRFCR */
return trfcr;
}
#endif /* __CORESIGHT_SELF_HOSTED_TRACE_H */
...@@ -432,6 +432,21 @@ static u32 tmc_etr_get_default_buffer_size(struct device *dev) ...@@ -432,6 +432,21 @@ static u32 tmc_etr_get_default_buffer_size(struct device *dev)
return size; return size;
} }
static u32 tmc_etr_get_max_burst_size(struct device *dev)
{
u32 burst_size;
if (fwnode_property_read_u32(dev->fwnode, "arm,max-burst-size",
&burst_size))
return TMC_AXICTL_WR_BURST_16;
/* Only permissible values are 0 to 15 */
if (burst_size > 0xF)
burst_size = TMC_AXICTL_WR_BURST_16;
return burst_size;
}
static int tmc_probe(struct amba_device *adev, const struct amba_id *id) static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
{ {
int ret = 0; int ret = 0;
...@@ -469,10 +484,12 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -469,10 +484,12 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
/* This device is not associated with a session */ /* This device is not associated with a session */
drvdata->pid = -1; drvdata->pid = -1;
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
drvdata->size = tmc_etr_get_default_buffer_size(dev); drvdata->size = tmc_etr_get_default_buffer_size(dev);
else drvdata->max_burst_size = tmc_etr_get_max_burst_size(dev);
} else {
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4; drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
}
desc.dev = dev; desc.dev = dev;
desc.groups = coresight_tmc_groups; desc.groups = coresight_tmc_groups;
......
...@@ -546,13 +546,17 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, ...@@ -546,13 +546,17 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev,
/* /*
* In snapshot mode we simply increment the head by the number of byte * In snapshot mode we simply increment the head by the number of byte
* that were written. User space function cs_etm_find_snapshot() will * that were written. User space will figure out how many bytes to get
* figure out how many bytes to get from the AUX buffer based on the * from the AUX buffer based on the position of the head.
* position of the head.
*/ */
if (buf->snapshot) if (buf->snapshot)
handle->head += to_read; handle->head += to_read;
/*
* CS_LOCK() contains mb() so it can ensure visibility of the AUX trace
* data before the aux_head is updated via perf_aux_output_end(), which
* is expected by the perf ring buffer.
*/
CS_LOCK(drvdata->base); CS_LOCK(drvdata->base);
out: out:
spin_unlock_irqrestore(&drvdata->spinlock, flags); spin_unlock_irqrestore(&drvdata->spinlock, flags);
......
...@@ -32,7 +32,6 @@ struct etr_flat_buf { ...@@ -32,7 +32,6 @@ struct etr_flat_buf {
* @etr_buf - Actual buffer used by the ETR * @etr_buf - Actual buffer used by the ETR
* @pid - The PID this etr_perf_buffer belongs to. * @pid - The PID this etr_perf_buffer belongs to.
* @snaphost - Perf session mode * @snaphost - Perf session mode
* @head - handle->head at the beginning of the session.
* @nr_pages - Number of pages in the ring buffer. * @nr_pages - Number of pages in the ring buffer.
* @pages - Array of Pages in the ring buffer. * @pages - Array of Pages in the ring buffer.
*/ */
...@@ -41,7 +40,6 @@ struct etr_perf_buffer { ...@@ -41,7 +40,6 @@ struct etr_perf_buffer {
struct etr_buf *etr_buf; struct etr_buf *etr_buf;
pid_t pid; pid_t pid;
bool snapshot; bool snapshot;
unsigned long head;
int nr_pages; int nr_pages;
void **pages; void **pages;
}; };
...@@ -609,8 +607,9 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata, ...@@ -609,8 +607,9 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata,
if (!flat_buf) if (!flat_buf)
return -ENOMEM; return -ENOMEM;
flat_buf->vaddr = dma_alloc_coherent(real_dev, etr_buf->size, flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size,
&flat_buf->daddr, GFP_KERNEL); &flat_buf->daddr,
DMA_FROM_DEVICE, GFP_KERNEL);
if (!flat_buf->vaddr) { if (!flat_buf->vaddr) {
kfree(flat_buf); kfree(flat_buf);
return -ENOMEM; return -ENOMEM;
...@@ -631,14 +630,18 @@ static void tmc_etr_free_flat_buf(struct etr_buf *etr_buf) ...@@ -631,14 +630,18 @@ static void tmc_etr_free_flat_buf(struct etr_buf *etr_buf)
if (flat_buf && flat_buf->daddr) { if (flat_buf && flat_buf->daddr) {
struct device *real_dev = flat_buf->dev->parent; struct device *real_dev = flat_buf->dev->parent;
dma_free_coherent(real_dev, flat_buf->size, dma_free_noncoherent(real_dev, etr_buf->size,
flat_buf->vaddr, flat_buf->daddr); flat_buf->vaddr, flat_buf->daddr,
DMA_FROM_DEVICE);
} }
kfree(flat_buf); kfree(flat_buf);
} }
static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp) static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
{ {
struct etr_flat_buf *flat_buf = etr_buf->private;
struct device *real_dev = flat_buf->dev->parent;
/* /*
* Adjust the buffer to point to the beginning of the trace data * Adjust the buffer to point to the beginning of the trace data
* and update the available trace data. * and update the available trace data.
...@@ -648,6 +651,19 @@ static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp) ...@@ -648,6 +651,19 @@ static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
etr_buf->len = etr_buf->size; etr_buf->len = etr_buf->size;
else else
etr_buf->len = rwp - rrp; etr_buf->len = rwp - rrp;
/*
* The driver always starts tracing at the beginning of the buffer,
* the only reason why we would get a wrap around is when the buffer
* is full. Sync the entire buffer in one go for this case.
*/
if (etr_buf->offset + etr_buf->len > etr_buf->size)
dma_sync_single_for_cpu(real_dev, flat_buf->daddr,
etr_buf->size, DMA_FROM_DEVICE);
else
dma_sync_single_for_cpu(real_dev,
flat_buf->daddr + etr_buf->offset,
etr_buf->len, DMA_FROM_DEVICE);
} }
static ssize_t tmc_etr_get_data_flat_buf(struct etr_buf *etr_buf, static ssize_t tmc_etr_get_data_flat_buf(struct etr_buf *etr_buf,
...@@ -982,7 +998,8 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) ...@@ -982,7 +998,8 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
axictl = readl_relaxed(drvdata->base + TMC_AXICTL); axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
axictl &= ~TMC_AXICTL_CLEAR_MASK; axictl &= ~TMC_AXICTL_CLEAR_MASK;
axictl |= (TMC_AXICTL_PROT_CTL_B1 | TMC_AXICTL_WR_BURST_16); axictl |= TMC_AXICTL_PROT_CTL_B1;
axictl |= TMC_AXICTL_WR_BURST(drvdata->max_burst_size);
axictl |= TMC_AXICTL_AXCACHE_OS; axictl |= TMC_AXICTL_AXCACHE_OS;
if (tmc_etr_has_cap(drvdata, TMC_ETR_AXI_ARCACHE)) { if (tmc_etr_has_cap(drvdata, TMC_ETR_AXI_ARCACHE)) {
...@@ -1437,16 +1454,16 @@ static void tmc_free_etr_buffer(void *config) ...@@ -1437,16 +1454,16 @@ static void tmc_free_etr_buffer(void *config)
* buffer to the perf ring buffer. * buffer to the perf ring buffer.
*/ */
static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf, static void tmc_etr_sync_perf_buffer(struct etr_perf_buffer *etr_perf,
unsigned long head,
unsigned long src_offset, unsigned long src_offset,
unsigned long to_copy) unsigned long to_copy)
{ {
long bytes; long bytes;
long pg_idx, pg_offset; long pg_idx, pg_offset;
unsigned long head = etr_perf->head;
char **dst_pages, *src_buf; char **dst_pages, *src_buf;
struct etr_buf *etr_buf = etr_perf->etr_buf; struct etr_buf *etr_buf = etr_perf->etr_buf;
head = etr_perf->head; head = PERF_IDX2OFF(head, etr_perf);
pg_idx = head >> PAGE_SHIFT; pg_idx = head >> PAGE_SHIFT;
pg_offset = head & (PAGE_SIZE - 1); pg_offset = head & (PAGE_SIZE - 1);
dst_pages = (char **)etr_perf->pages; dst_pages = (char **)etr_perf->pages;
...@@ -1553,16 +1570,23 @@ tmc_update_etr_buffer(struct coresight_device *csdev, ...@@ -1553,16 +1570,23 @@ tmc_update_etr_buffer(struct coresight_device *csdev,
/* Insert barrier packets at the beginning, if there was an overflow */ /* Insert barrier packets at the beginning, if there was an overflow */
if (lost) if (lost)
tmc_etr_buf_insert_barrier_packet(etr_buf, offset); tmc_etr_buf_insert_barrier_packet(etr_buf, offset);
tmc_etr_sync_perf_buffer(etr_perf, offset, size); tmc_etr_sync_perf_buffer(etr_perf, handle->head, offset, size);
/* /*
* In snapshot mode we simply increment the head by the number of byte * In snapshot mode we simply increment the head by the number of byte
* that were written. User space function cs_etm_find_snapshot() will * that were written. User space will figure out how many bytes to get
* figure out how many bytes to get from the AUX buffer based on the * from the AUX buffer based on the position of the head.
* position of the head.
*/ */
if (etr_perf->snapshot) if (etr_perf->snapshot)
handle->head += size; handle->head += size;
/*
* Ensure that the AUX trace data is visible before the aux_head
* is updated via perf_aux_output_end(), as expected by the
* perf ring buffer.
*/
smp_wmb();
out: out:
/* /*
* Don't set the TRUNCATED flag in snapshot mode because 1) the * Don't set the TRUNCATED flag in snapshot mode because 1) the
...@@ -1605,8 +1629,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) ...@@ -1605,8 +1629,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
goto unlock_out; goto unlock_out;
} }
etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf);
/* /*
* No HW configuration is needed if the sink is already in * No HW configuration is needed if the sink is already in
* use for this session. * use for this session.
......
...@@ -70,7 +70,8 @@ ...@@ -70,7 +70,8 @@
#define TMC_AXICTL_PROT_CTL_B0 BIT(0) #define TMC_AXICTL_PROT_CTL_B0 BIT(0)
#define TMC_AXICTL_PROT_CTL_B1 BIT(1) #define TMC_AXICTL_PROT_CTL_B1 BIT(1)
#define TMC_AXICTL_SCT_GAT_MODE BIT(7) #define TMC_AXICTL_SCT_GAT_MODE BIT(7)
#define TMC_AXICTL_WR_BURST_16 0xF00 #define TMC_AXICTL_WR_BURST(v) (((v) & 0xf) << 8)
#define TMC_AXICTL_WR_BURST_16 0xf
/* Write-back Read and Write-allocate */ /* Write-back Read and Write-allocate */
#define TMC_AXICTL_AXCACHE_OS (0xf << 2) #define TMC_AXICTL_AXCACHE_OS (0xf << 2)
#define TMC_AXICTL_ARCACHE_OS (0xf << 16) #define TMC_AXICTL_ARCACHE_OS (0xf << 16)
...@@ -174,6 +175,8 @@ struct etr_buf { ...@@ -174,6 +175,8 @@ struct etr_buf {
* @etr_buf: details of buffer used in TMC-ETR * @etr_buf: details of buffer used in TMC-ETR
* @len: size of the available trace for ETF/ETB. * @len: size of the available trace for ETF/ETB.
* @size: trace buffer size for this TMC (common for all modes). * @size: trace buffer size for this TMC (common for all modes).
* @max_burst_size: The maximum burst size that can be initiated by
* TMC-ETR on AXI bus.
* @mode: how this TMC is being used. * @mode: how this TMC is being used.
* @config_type: TMC variant, must be of type @tmc_config_type. * @config_type: TMC variant, must be of type @tmc_config_type.
* @memwidth: width of the memory interface databus, in bytes. * @memwidth: width of the memory interface databus, in bytes.
...@@ -198,6 +201,7 @@ struct tmc_drvdata { ...@@ -198,6 +201,7 @@ struct tmc_drvdata {
}; };
u32 len; u32 len;
u32 size; u32 size;
u32 max_burst_size;
u32 mode; u32 mode;
enum tmc_config_type config_type; enum tmc_config_type config_type;
enum tmc_mem_intf_width memwidth; enum tmc_mem_intf_width memwidth;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment