Commit 096dcfb9 authored by Mike Leach's avatar Mike Leach Committed by Greg Kroah-Hartman
Browse files

coresight: etm4x: Ensure default perf settings filter user/kernel



Moving from using an address filter to trace the default "all addresses"
range to no filtering to acheive the same result, has caused the perf
filtering of kernel/user address spaces from not working unless an
explicit address filter was used.

This is due to the original code using a side-effect of the address
filtering rather than setting the global TRCVICTLR exception level
filtering.

The use of the mode sysfs file is also similarly affected.

A helper function is added to fix both instances.

Fixes: ae204151 ("coresight: etmv4: Update default filter and initialisation")
Reported-by: default avatarLeo Yan <leo.yan@linaro.org>
Tested-by: default avatarLeo Yan <leo.yan@linaro.org>
Reviewed-by: default avatarLeo Yan <leo.yan@linaro.org>
Signed-off-by: default avatarMike Leach <mike.leach@linaro.org>
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20200916191737.4001561-8-mathieu.poirier@linaro.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6e8836c6
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
static void etm4_set_default_config(struct etmv4_config *config);
static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
				  struct perf_event *event);
static u64 etm4_get_access_type(struct etmv4_config *config);

static enum cpuhp_state hp_online;

@@ -783,6 +784,22 @@ static void etm4_init_arch_data(void *info)
	CS_LOCK(drvdata->base);
}

/* Set ELx trace filter access in the TRCVICTLR register */
static void etm4_set_victlr_access(struct etmv4_config *config)
{
	u64 access_type;

	config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK | ETM_EXLEVEL_NS_VICTLR_MASK);

	/*
	 * TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering
	 * bits in vinst_ctrl, same bit pattern as TRCACATRn values returned by
	 * etm4_get_access_type() but with a relative shift in this register.
	 */
	access_type = etm4_get_access_type(config) << ETM_EXLEVEL_LSHIFT_TRCVICTLR;
	config->vinst_ctrl |= (u32)access_type;
}

static void etm4_set_default_config(struct etmv4_config *config)
{
	/* disable all events tracing */
@@ -800,6 +817,9 @@ static void etm4_set_default_config(struct etmv4_config *config)

	/* TRCVICTLR::EVENT = 0x01, select the always on logic */
	config->vinst_ctrl = BIT(0);

	/* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering */
	etm4_set_victlr_access(config);
}

static u64 etm4_get_ns_access_type(struct etmv4_config *config)
@@ -1064,7 +1084,7 @@ out:

void etm4_config_trace_mode(struct etmv4_config *config)
{
	u32 addr_acc, mode;
	u32 mode;

	mode = config->mode;
	mode &= (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER);
@@ -1076,15 +1096,7 @@ void etm4_config_trace_mode(struct etmv4_config *config)
	if (!(mode & ETM_MODE_EXCL_KERN) && !(mode & ETM_MODE_EXCL_USER))
		return;

	addr_acc = config->addr_acc[ETM_DEFAULT_ADDR_COMP];
	/* clear default config */
	addr_acc &= ~(ETM_EXLEVEL_NS_APP | ETM_EXLEVEL_NS_OS |
		      ETM_EXLEVEL_NS_HYP);

	addr_acc |= etm4_get_ns_access_type(config);

	config->addr_acc[ETM_DEFAULT_ADDR_COMP] = addr_acc;
	config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] = addr_acc;
	etm4_set_victlr_access(config);
}

static int etm4_online_cpu(unsigned int cpu)
+3 −0
Original line number Diff line number Diff line
@@ -192,6 +192,9 @@
#define ETM_EXLEVEL_NS_HYP		BIT(14)
#define ETM_EXLEVEL_NS_NA		BIT(15)

/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */
#define ETM_EXLEVEL_LSHIFT_TRCVICTLR	8

/* secure / non secure masks - TRCVICTLR, IDR3 */
#define ETM_EXLEVEL_S_VICTLR_MASK	GENMASK(19, 16)
/* NS MON (EL3) mode never implemented */