static int etm4_parse_event_config()

in coresight/coresight-etm4x-core.c [607:697]


static int etm4_parse_event_config(struct coresight_device *csdev,
				   struct perf_event *event)
{
	int ret = 0;
	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
	struct etmv4_config *config = &drvdata->config;
	struct perf_event_attr *attr = &event->attr;
	unsigned long cfg_hash;
	int preset;

	/* Clear configuration from previous run */
	memset(config, 0, sizeof(struct etmv4_config));

	if (attr->exclude_kernel)
		config->mode = ETM_MODE_EXCL_KERN;

	if (attr->exclude_user)
		config->mode = ETM_MODE_EXCL_USER;

	/* Always start from the default config */
	etm4_set_default_config(config);

	/* Configure filters specified on the perf cmd line, if any. */
	ret = etm4_set_event_filters(drvdata, event);
	if (ret)
		goto out;

	/* Go from generic option to ETMv4 specifics */
	if (attr->config & BIT(ETM_OPT_CYCACC)) {
		config->cfg |= BIT(4);
		/* TRM: Must program this for cycacc to work */
		config->ccctlr = ETM_CYC_THRESHOLD_DEFAULT;
	}
	if (attr->config & BIT(ETM_OPT_TS)) {
		/*
		 * Configure timestamps to be emitted at regular intervals in
		 * order to correlate instructions executed on different CPUs
		 * (CPU-wide trace scenarios).
		 */
		ret = etm4_config_timestamp_event(drvdata);

		/*
		 * No need to go further if timestamp intervals can't
		 * be configured.
		 */
		if (ret)
			goto out;

		/* bit[11], Global timestamp tracing bit */
		config->cfg |= BIT(11);
	}

	if (attr->config & BIT(ETM_OPT_CTXTID))
		/* bit[6], Context ID tracing bit */
		config->cfg |= BIT(ETM4_CFG_BIT_CTXTID);

	/*
	 * If set bit ETM_OPT_CTXTID2 in perf config, this asks to trace VMID
	 * for recording CONTEXTIDR_EL2.  Do not enable VMID tracing if the
	 * kernel is not running in EL2.
	 */
	if (attr->config & BIT(ETM_OPT_CTXTID2)) {
		if (!is_kernel_in_hyp_mode()) {
			ret = -EINVAL;
			goto out;
		}
		config->cfg |= BIT(ETM4_CFG_BIT_VMID) | BIT(ETM4_CFG_BIT_VMID_OPT);
	}

	/* return stack - enable if selected and supported */
	if ((attr->config & BIT(ETM_OPT_RETSTK)) && drvdata->retstack)
		/* bit[12], Return stack enable bit */
		config->cfg |= BIT(12);

	/*
	 * Set any selected configuration and preset.
	 *
	 * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
	 * in the perf attributes defined in coresight-etm-perf.c.
	 * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
	 * A zero configid means no configuration active, preset = 0 means no preset selected.
	 */
	if (attr->config2 & GENMASK_ULL(63, 32)) {
		cfg_hash = (u32)(attr->config2 >> 32);
		preset = attr->config & 0xF;
		ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
	}

out:
	return ret;
}