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