Commit 937d3f58 authored by Suzuki K Poulose's avatar Suzuki K Poulose Committed by Mathieu Poirier
Browse files

coresight: etm4x: Save restore TRFCR_EL1



When the CPU enters a low power mode, the TRFCR_EL1 contents could be
reset. Thus we need to save/restore the TRFCR_EL1 along with the ETM4x
registers to allow the tracing.

The TRFCR related helpers are in a new header file, as we need to use
them for TRBE in the later patches.

Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Leo Yan <leo.yan@linaro.org>
Reviewed-by: default avatarAnshuman Khandual <anshuman.khandual@arm.com>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20210914102641.1852544-2-suzuki.poulose@arm.com


[Fixed cosmetic details]
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
parent 8c60acbc
Loading
Loading
Loading
Loading
+31 −12
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "coresight-etm4x.h"
#include "coresight-etm-perf.h"
#include "coresight-etm4x-cfg.h"
#include "coresight-self-hosted-trace.h"
#include "coresight-syscfg.h"

static int boot_enable;
@@ -1011,7 +1012,7 @@ static void cpu_enable_tracing(struct etmv4_drvdata *drvdata)
	if (is_kernel_in_hyp_mode())
		trfcr |= TRFCR_EL2_CX;

	write_sysreg_s(trfcr, SYS_TRFCR_EL1);
	write_trfcr(trfcr);
}

static void etm4_init_arch_data(void *info)
@@ -1554,7 +1555,7 @@ static void etm4_init_trace_id(struct etmv4_drvdata *drvdata)
	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;
	struct etmv4_save_state *state;
@@ -1693,7 +1694,23 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
	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->trfc)
		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;
	struct etmv4_save_state *state = drvdata->save_state;
@@ -1789,6 +1806,14 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
	etm4_cs_lock(drvdata, csa);
}

static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
{
	if (drvdata->trfc)
		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,
			      void *v)
{
@@ -1800,22 +1825,16 @@ static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,

	drvdata = etmdrvdata[cpu];

	if (!drvdata->save_state)
		return NOTIFY_OK;

	if (WARN_ON_ONCE(drvdata->cpu != cpu))
		return NOTIFY_BAD;

	switch (cmd) {
	case CPU_PM_ENTER:
		/* save the state if self-hosted coresight is in use */
		if (local_read(&drvdata->mode))
		if (etm4_cpu_save(drvdata))
			return NOTIFY_BAD;
		break;
	case CPU_PM_EXIT:
	case CPU_PM_ENTER_FAILED:
		if (drvdata->state_needs_restore)
		etm4_cpu_restore(drvdata);
		break;
	default:
+2 −0
Original line number Diff line number Diff line
@@ -921,6 +921,7 @@ struct etmv4_save_state {
 * @lpoverride:	If the implementation can support low-power state over.
 * @trfc:	If the implementation supports Arm v8.4 trace filter controls.
 * @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
 * @state_needs_restore: True when there is context to restore after PM exit
 * @skip_power_up: Indicates if an implementation can skip powering up
@@ -973,6 +974,7 @@ struct etmv4_drvdata {
	bool				lpoverride;
	bool				trfc;
	struct etmv4_config		config;
	u64				save_trfcr;
	struct etmv4_save_state		*save_state;
	bool				state_needs_restore;
	bool				skip_power_up;
+24 −0
Original line number Diff line number Diff line
/* 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();
}

#endif /*  __CORESIGHT_SELF_HOSTED_TRACE_H */