brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 4abe416 Raw
194 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * File for any parts of the Coresight decoding that don't require4 * OpenCSD.5 */6 7#include <errno.h>8#include <inttypes.h>9 10#include "cs-etm.h"11 12static const char * const cs_etm_global_header_fmts[] = {13	[CS_HEADER_VERSION]	= "	Header version		       %llx\n",14	[CS_PMU_TYPE_CPUS]	= "	PMU type/num cpus	       %llx\n",15	[CS_ETM_SNAPSHOT]	= "	Snapshot		       %llx\n",16};17 18static const char * const cs_etm_priv_fmts[] = {19	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",20	[CS_ETM_CPU]		= "	CPU			       %lld\n",21	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",22	[CS_ETM_ETMCR]		= "	ETMCR			       %llx\n",23	[CS_ETM_ETMTRACEIDR]	= "	ETMTRACEIDR		       %llx\n",24	[CS_ETM_ETMCCER]	= "	ETMCCER			       %llx\n",25	[CS_ETM_ETMIDR]		= "	ETMIDR			       %llx\n",26};27 28static const char * const cs_etmv4_priv_fmts[] = {29	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",30	[CS_ETM_CPU]		= "	CPU			       %lld\n",31	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",32	[CS_ETMV4_TRCCONFIGR]	= "	TRCCONFIGR		       %llx\n",33	[CS_ETMV4_TRCTRACEIDR]	= "	TRCTRACEIDR		       %llx\n",34	[CS_ETMV4_TRCIDR0]	= "	TRCIDR0			       %llx\n",35	[CS_ETMV4_TRCIDR1]	= "	TRCIDR1			       %llx\n",36	[CS_ETMV4_TRCIDR2]	= "	TRCIDR2			       %llx\n",37	[CS_ETMV4_TRCIDR8]	= "	TRCIDR8			       %llx\n",38	[CS_ETMV4_TRCAUTHSTATUS] = "	TRCAUTHSTATUS		       %llx\n",39	[CS_ETMV4_TS_SOURCE]	= "	TS_SOURCE		       %lld\n",40};41 42static const char * const cs_ete_priv_fmts[] = {43	[CS_ETM_MAGIC]		= "	Magic number		       %llx\n",44	[CS_ETM_CPU]		= "	CPU			       %lld\n",45	[CS_ETM_NR_TRC_PARAMS]	= "	NR_TRC_PARAMS		       %llx\n",46	[CS_ETE_TRCCONFIGR]	= "	TRCCONFIGR		       %llx\n",47	[CS_ETE_TRCTRACEIDR]	= "	TRCTRACEIDR		       %llx\n",48	[CS_ETE_TRCIDR0]	= "	TRCIDR0			       %llx\n",49	[CS_ETE_TRCIDR1]	= "	TRCIDR1			       %llx\n",50	[CS_ETE_TRCIDR2]	= "	TRCIDR2			       %llx\n",51	[CS_ETE_TRCIDR8]	= "	TRCIDR8			       %llx\n",52	[CS_ETE_TRCAUTHSTATUS]	= "	TRCAUTHSTATUS		       %llx\n",53	[CS_ETE_TRCDEVARCH]	= "	TRCDEVARCH                     %llx\n",54	[CS_ETE_TS_SOURCE]	= "	TS_SOURCE                      %lld\n",55};56 57static const char * const param_unk_fmt =58	"	Unknown parameter [%d]	       %"PRIx64"\n";59static const char * const magic_unk_fmt =60	"	Magic number Unknown	       %"PRIx64"\n";61 62static int cs_etm__print_cpu_metadata_v0(u64 *val, int *offset)63{64	int i = *offset, j, nr_params = 0, fmt_offset;65	u64 magic;66 67	/* check magic value */68	magic = val[i + CS_ETM_MAGIC];69	if ((magic != __perf_cs_etmv3_magic) &&70	    (magic != __perf_cs_etmv4_magic)) {71		/* failure - note bad magic value */72		fprintf(stdout, magic_unk_fmt, magic);73		return -EINVAL;74	}75 76	/* print common header block */77	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_MAGIC], val[i++]);78	fprintf(stdout, cs_etm_priv_fmts[CS_ETM_CPU], val[i++]);79 80	if (magic == __perf_cs_etmv3_magic) {81		nr_params = CS_ETM_NR_TRC_PARAMS_V0;82		fmt_offset = CS_ETM_ETMCR;83		/* after common block, offset format index past NR_PARAMS */84		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)85			fprintf(stdout, cs_etm_priv_fmts[j], val[i]);86	} else if (magic == __perf_cs_etmv4_magic) {87		nr_params = CS_ETMV4_NR_TRC_PARAMS_V0;88		fmt_offset = CS_ETMV4_TRCCONFIGR;89		/* after common block, offset format index past NR_PARAMS */90		for (j = fmt_offset; j < nr_params + fmt_offset; j++, i++)91			fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);92	}93	*offset = i;94	return 0;95}96 97static int cs_etm__print_cpu_metadata_v1(u64 *val, int *offset)98{99	int i = *offset, j, total_params = 0;100	u64 magic;101 102	magic = val[i + CS_ETM_MAGIC];103	/* total params to print is NR_PARAMS + common block size for v1 */104	total_params = val[i + CS_ETM_NR_TRC_PARAMS] + CS_ETM_COMMON_BLK_MAX_V1;105 106	if (magic == __perf_cs_etmv3_magic) {107		for (j = 0; j < total_params; j++, i++) {108			/* if newer record - could be excess params */109			if (j >= CS_ETM_PRIV_MAX)110				fprintf(stdout, param_unk_fmt, j, val[i]);111			else112				fprintf(stdout, cs_etm_priv_fmts[j], val[i]);113		}114	} else if (magic == __perf_cs_etmv4_magic) {115		for (j = 0; j < total_params; j++, i++) {116			/* if newer record - could be excess params */117			if (j >= CS_ETMV4_PRIV_MAX)118				fprintf(stdout, param_unk_fmt, j, val[i]);119			else120				fprintf(stdout, cs_etmv4_priv_fmts[j], val[i]);121		}122	} else if (magic == __perf_cs_ete_magic) {123		for (j = 0; j < total_params; j++, i++) {124			/* if newer record - could be excess params */125			if (j >= CS_ETE_PRIV_MAX)126				fprintf(stdout, param_unk_fmt, j, val[i]);127			else128				fprintf(stdout, cs_ete_priv_fmts[j], val[i]);129		}130	} else {131		/* failure - note bad magic value and error out */132		fprintf(stdout, magic_unk_fmt, magic);133		return -EINVAL;134	}135	*offset = i;136	return 0;137}138 139static void cs_etm__print_auxtrace_info(u64 *val, int num)140{141	int i, cpu = 0, version, err;142 143	version = val[0];144 145	for (i = 0; i < CS_HEADER_VERSION_MAX; i++)146		fprintf(stdout, cs_etm_global_header_fmts[i], val[i]);147 148	for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {149		if (version == 0)150			err = cs_etm__print_cpu_metadata_v0(val, &i);151		/* printing same for both, but value bit flags added on v2 */152		else if ((version == 1) || (version == 2))153			err = cs_etm__print_cpu_metadata_v1(val, &i);154		if (err)155			return;156	}157}158 159/*160 * Do some basic checks and print the auxtrace info header before calling161 * into cs_etm__process_auxtrace_info_full() which requires OpenCSD to be162 * linked in. This allows some basic debugging if OpenCSD is missing.163 */164int cs_etm__process_auxtrace_info(union perf_event *event,165				  struct perf_session *session)166{167	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;168	int event_header_size = sizeof(struct perf_event_header);169	int num_cpu;170	u64 *ptr = NULL;171	u64 hdr_version;172 173	if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE))174		return -EINVAL;175 176	/* First the global part */177	ptr = (u64 *) auxtrace_info->priv;178 179	/* Look for version of the header */180	hdr_version = ptr[0];181	if (hdr_version > CS_HEADER_CURRENT_VERSION) {182		pr_err("\nCS ETM Trace: Unknown Header Version = %#" PRIx64, hdr_version);183		pr_err(", version supported <= %x\n", CS_HEADER_CURRENT_VERSION);184		return -EINVAL;185	}186 187	if (dump_trace) {188		num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;189		cs_etm__print_auxtrace_info(ptr, num_cpu);190	}191 192	return cs_etm__process_auxtrace_info_full(event, session);193}194