File Index
Files and directories
Sign in
FILE

arm-spe-decoder.c

File preview with syntax highlighting.

linux-6.19.14/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * arm_spe_decoder.c: ARM SPE support
  4 */
  5
  6#ifndef _GNU_SOURCE
  7#define _GNU_SOURCE
  8#endif
  9#include <errno.h>
 10#include <inttypes.h>
 11#include <stdbool.h>
 12#include <string.h>
 13#include <stdint.h>
 14#include <stdlib.h>
 15#include <linux/bitops.h>
 16#include <linux/compiler.h>
 17#include <linux/zalloc.h>
 18
 19#include "../auxtrace.h"
 20#include "../debug.h"
 21#include "../util.h"
 22
 23#include "arm-spe-decoder.h"
 24
 25static u64 arm_spe_calc_ip(int index, u64 payload)
 26{
 27	u64 ns, el, val;
 28
 29	/* Instruction virtual address or Branch target address */
 30	if (index == SPE_ADDR_PKT_HDR_INDEX_INS ||
 31	    index == SPE_ADDR_PKT_HDR_INDEX_BRANCH ||
 32	    index == SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH) {
 33		ns = SPE_ADDR_PKT_GET_NS(payload);
 34		el = SPE_ADDR_PKT_GET_EL(payload);
 35
 36		/* Clean highest byte */
 37		payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
 38
 39		/* Fill highest byte for EL1 or EL2 (VHE) mode */
 40		if (ns && (el == SPE_ADDR_PKT_EL1 || el == SPE_ADDR_PKT_EL2))
 41			payload |= 0xffULL << SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;
 42
 43	/* Data access virtual address */
 44	} else if (index == SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT) {
 45
 46		/* Clean tags */
 47		payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
 48
 49		/*
 50		 * Armv8 ARM (ARM DDI 0487F.c), chapter "D10.2.1 Address packet"
 51		 * defines the data virtual address payload format, the top byte
 52		 * (bits [63:56]) is assigned as top-byte tag; so we only can
 53		 * retrieve address value from bits [55:0].
 54		 *
 55		 * According to Documentation/arch/arm64/memory.rst, if detects the
 56		 * specific pattern in bits [55:52] of payload which falls in
 57		 * the kernel space, should fixup the top byte and this allows
 58		 * perf tool to parse DSO symbol for data address correctly.
 59		 *
 60		 * For this reason, if detects the bits [55:52] is 0xf, will
 61		 * fill 0xff into the top byte.
 62		 */
 63		val = SPE_ADDR_PKT_ADDR_GET_BYTE_6(payload);
 64		if ((val & 0xf0ULL) == 0xf0ULL)
 65			payload |= 0xffULL << SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;
 66
 67	/* Data access physical address */
 68	} else if (index == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS) {
 69		/* Clean highest byte */
 70		payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
 71	} else {
 72		static u32 seen_idx = 0;
 73		if (!(seen_idx & BIT(index))) {
 74			seen_idx |= BIT(index);
 75			pr_warning("ignoring unsupported address packet index: 0x%x\n", index);
 76		}
 77	}
 78
 79	return payload;
 80}
 81
 82struct arm_spe_decoder *arm_spe_decoder_new(struct arm_spe_params *params)
 83{
 84	struct arm_spe_decoder *decoder;
 85
 86	if (!params->get_trace)
 87		return NULL;
 88
 89	decoder = zalloc(sizeof(struct arm_spe_decoder));
 90	if (!decoder)
 91		return NULL;
 92
 93	decoder->get_trace = params->get_trace;
 94	decoder->data = params->data;
 95
 96	return decoder;
 97}
 98
 99void arm_spe_decoder_free(struct arm_spe_decoder *decoder)
100{
101	free(decoder);
102}
103
104static int arm_spe_get_data(struct arm_spe_decoder *decoder)
105{
106	struct arm_spe_buffer buffer = { .buf = 0, };
107	int ret;
108
109	pr_debug("Getting more data\n");
110	ret = decoder->get_trace(&buffer, decoder->data);
111	if (ret < 0)
112		return ret;
113
114	decoder->buf = buffer.buf;
115	decoder->len = buffer.len;
116
117	if (!decoder->len)
118		pr_debug("No more data\n");
119
120	return decoder->len;
121}
122
123static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)
124{
125	int ret;
126
127	do {
128		if (!decoder->len) {
129			ret = arm_spe_get_data(decoder);
130
131			/* Failed to read out trace data */
132			if (ret <= 0)
133				return ret;
134		}
135
136		ret = arm_spe_get_packet(decoder->buf, decoder->len,
137					 &decoder->packet);
138		if (ret <= 0) {
139			/* Move forward for 1 byte */
140			decoder->buf += 1;
141			decoder->len -= 1;
142			return -EBADMSG;
143		}
144
145		decoder->buf += ret;
146		decoder->len -= ret;
147	} while (decoder->packet.type == ARM_SPE_PAD);
148
149	return 1;
150}
151
152static int arm_spe_read_record(struct arm_spe_decoder *decoder)
153{
154	int err;
155	int idx;
156	u64 payload, ip;
157
158	memset(&decoder->record, 0x0, sizeof(decoder->record));
159	decoder->record.context_id = (u64)-1;
160
161	while (1) {
162		err = arm_spe_get_next_packet(decoder);
163		if (err <= 0)
164			return err;
165
166		idx = decoder->packet.index;
167		payload = decoder->packet.payload;
168
169		switch (decoder->packet.type) {
170		case ARM_SPE_TIMESTAMP:
171			decoder->record.timestamp = payload;
172			return 1;
173		case ARM_SPE_END:
174			return 1;
175		case ARM_SPE_ADDRESS:
176			ip = arm_spe_calc_ip(idx, payload);
177			if (idx == SPE_ADDR_PKT_HDR_INDEX_INS)
178				decoder->record.from_ip = ip;
179			else if (idx == SPE_ADDR_PKT_HDR_INDEX_BRANCH)
180				decoder->record.to_ip = ip;
181			else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT)
182				decoder->record.virt_addr = ip;
183			else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS)
184				decoder->record.phys_addr = ip;
185			else if (idx == SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH)
186				decoder->record.prev_br_tgt = ip;
187			break;
188		case ARM_SPE_COUNTER:
189			if (idx == SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT)
190				decoder->record.latency = payload;
191			break;
192		case ARM_SPE_CONTEXT:
193			decoder->record.context_id = payload;
194			break;
195		case ARM_SPE_OP_TYPE:
196			switch (idx) {
197			case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
198				decoder->record.op |= ARM_SPE_OP_LDST;
199				if (payload & SPE_OP_PKT_ST)
200					decoder->record.op |= ARM_SPE_OP_ST;
201				else
202					decoder->record.op |= ARM_SPE_OP_LD;
203
204				if (SPE_OP_PKT_LDST_SUBCLASS_GP_REG(payload)) {
205					decoder->record.op |= ARM_SPE_OP_GP_REG;
206				} else if (SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP(payload)) {
207					decoder->record.op |= ARM_SPE_OP_SIMD_FP;
208				} else if (SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG(payload)) {
209					decoder->record.op |= ARM_SPE_OP_UNSPEC_REG;
210				} else if (SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG(payload)) {
211					decoder->record.op |= ARM_SPE_OP_NV_SYSREG;
212				} else if (SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG(payload)) {
213					decoder->record.op |= ARM_SPE_OP_MTE_TAG;
214				} else if (SPE_OP_PKT_LDST_SUBCLASS_EXTENDED(payload)) {
215					if (payload & SPE_OP_PKT_AR)
216						decoder->record.op |= ARM_SPE_OP_AR;
217					if (payload & SPE_OP_PKT_EXCL)
218						decoder->record.op |= ARM_SPE_OP_EXCL;
219					if (payload & SPE_OP_PKT_AT)
220						decoder->record.op |= ARM_SPE_OP_ATOMIC;
221				} else if (SPE_OP_PKT_LDST_SUBCLASS_SVE_SME_REG(payload)) {
222					decoder->record.op |= ARM_SPE_OP_SVE;
223					if (payload & SPE_OP_PKT_SVE_PRED)
224						decoder->record.op |= ARM_SPE_OP_PRED;
225					if (payload & SPE_OP_PKT_SVE_SG)
226						decoder->record.op |= ARM_SPE_OP_SG;
227				} else if (SPE_OP_PKT_LDST_SUBCLASS_MEMCPY(payload)) {
228					decoder->record.op |= ARM_SPE_OP_MEMCPY;
229				} else if (SPE_OP_PKT_LDST_SUBCLASS_MEMSET(payload)) {
230					decoder->record.op |= ARM_SPE_OP_MEMSET;
231				} else if (SPE_OP_PKT_LDST_SUBCLASS_GCS(payload)) {
232					decoder->record.op |= ARM_SPE_OP_GCS;
233					if (payload & SPE_OP_PKT_GCS_COMM)
234						decoder->record.op |= ARM_SPE_OP_COMM;
235				}
236
237				break;
238			case SPE_OP_PKT_HDR_CLASS_OTHER:
239				decoder->record.op |= ARM_SPE_OP_OTHER;
240				if (SPE_OP_PKT_OTHER_SUBCLASS_SVE(payload)) {
241					decoder->record.op |= ARM_SPE_OP_SVE | ARM_SPE_OP_DP;
242					if (payload & SPE_OP_PKT_OTHER_FP)
243						decoder->record.op |= ARM_SPE_OP_FP;
244					if (payload & SPE_OP_PKT_SVE_PRED)
245						decoder->record.op |= ARM_SPE_OP_PRED;
246				} else if (SPE_OP_PKT_OTHER_SUBCLASS_SME(payload)) {
247					decoder->record.op |= ARM_SPE_OP_SME;
248					if (payload & SPE_OP_PKT_OTHER_FP)
249						decoder->record.op |= ARM_SPE_OP_FP;
250				} else if (SPE_OP_PKT_OTHER_SUBCLASS_OTHER(payload)) {
251					if (payload & SPE_OP_PKT_OTHER_ASE)
252						decoder->record.op |= ARM_SPE_OP_ASE;
253					if (payload & SPE_OP_PKT_OTHER_FP)
254						decoder->record.op |= ARM_SPE_OP_FP;
255					if (payload & SPE_OP_PKT_COND)
256						decoder->record.op |= ARM_SPE_OP_COND;
257				}
258				break;
259			case SPE_OP_PKT_HDR_CLASS_BR_ERET:
260				decoder->record.op |= ARM_SPE_OP_BRANCH_ERET;
261				if (payload & SPE_OP_PKT_COND)
262					decoder->record.op |= ARM_SPE_OP_BR_COND;
263				if (payload & SPE_OP_PKT_INDIRECT_BRANCH)
264					decoder->record.op |= ARM_SPE_OP_BR_INDIRECT;
265				if (payload & SPE_OP_PKT_GCS)
266					decoder->record.op |= ARM_SPE_OP_BR_GCS;
267				if (SPE_OP_PKT_CR_BL(payload))
268					decoder->record.op |= ARM_SPE_OP_BR_CR_BL;
269				if (SPE_OP_PKT_CR_RET(payload))
270					decoder->record.op |= ARM_SPE_OP_BR_CR_RET;
271				if (SPE_OP_PKT_CR_NON_BL_RET(payload))
272					decoder->record.op |= ARM_SPE_OP_BR_CR_NON_BL_RET;
273				break;
274			default:
275				pr_err("Get packet error!\n");
276				return -1;
277			}
278			break;
279		case ARM_SPE_EVENTS:
280			decoder->record.type = payload;
281			break;
282		case ARM_SPE_DATA_SOURCE:
283			decoder->record.source = payload;
284			break;
285		case ARM_SPE_BAD:
286			break;
287		case ARM_SPE_PAD:
288			break;
289		default:
290			pr_err("Get packet error!\n");
291			return -1;
292		}
293	}
294
295	return 0;
296}
297
298int arm_spe_decode(struct arm_spe_decoder *decoder)
299{
300	return arm_spe_read_record(decoder);
301}
~/ Read-only file preview.