xref: /openbmc/linux/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c (revision 7ea6856d6f5629d742edc23b8b76e6263371ef45)
1a4e92590SAdrian Hunter /*
2a4e92590SAdrian Hunter  * intel_pt_pkt_decoder.c: Intel Processor Trace support
3a4e92590SAdrian Hunter  * Copyright (c) 2013-2014, Intel Corporation.
4a4e92590SAdrian Hunter  *
5a4e92590SAdrian Hunter  * This program is free software; you can redistribute it and/or modify it
6a4e92590SAdrian Hunter  * under the terms and conditions of the GNU General Public License,
7a4e92590SAdrian Hunter  * version 2, as published by the Free Software Foundation.
8a4e92590SAdrian Hunter  *
9a4e92590SAdrian Hunter  * This program is distributed in the hope it will be useful, but WITHOUT
10a4e92590SAdrian Hunter  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11a4e92590SAdrian Hunter  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12a4e92590SAdrian Hunter  * more details.
13a4e92590SAdrian Hunter  *
14a4e92590SAdrian Hunter  */
15a4e92590SAdrian Hunter 
16a4e92590SAdrian Hunter #include <stdio.h>
17a4e92590SAdrian Hunter #include <string.h>
18a4e92590SAdrian Hunter #include <endian.h>
19a4e92590SAdrian Hunter #include <byteswap.h>
20*7ea6856dSArnaldo Carvalho de Melo #include <linux/compiler.h>
21a4e92590SAdrian Hunter 
22a4e92590SAdrian Hunter #include "intel-pt-pkt-decoder.h"
23a4e92590SAdrian Hunter 
24a4e92590SAdrian Hunter #define BIT(n)		(1 << (n))
25a4e92590SAdrian Hunter 
26a4e92590SAdrian Hunter #define BIT63		((uint64_t)1 << 63)
27a4e92590SAdrian Hunter 
283d498078SAdrian Hunter #define NR_FLAG		BIT63
293d498078SAdrian Hunter 
30a4e92590SAdrian Hunter #if __BYTE_ORDER == __BIG_ENDIAN
31a4e92590SAdrian Hunter #define le16_to_cpu bswap_16
32a4e92590SAdrian Hunter #define le32_to_cpu bswap_32
33a4e92590SAdrian Hunter #define le64_to_cpu bswap_64
34a4e92590SAdrian Hunter #define memcpy_le64(d, s, n) do { \
35a4e92590SAdrian Hunter 	memcpy((d), (s), (n));    \
36a4e92590SAdrian Hunter 	*(d) = le64_to_cpu(*(d)); \
37a4e92590SAdrian Hunter } while (0)
38a4e92590SAdrian Hunter #else
39a4e92590SAdrian Hunter #define le16_to_cpu
40a4e92590SAdrian Hunter #define le32_to_cpu
41a4e92590SAdrian Hunter #define le64_to_cpu
42a4e92590SAdrian Hunter #define memcpy_le64 memcpy
43a4e92590SAdrian Hunter #endif
44a4e92590SAdrian Hunter 
45a4e92590SAdrian Hunter static const char * const packet_name[] = {
46a4e92590SAdrian Hunter 	[INTEL_PT_BAD]		= "Bad Packet!",
47a4e92590SAdrian Hunter 	[INTEL_PT_PAD]		= "PAD",
48a4e92590SAdrian Hunter 	[INTEL_PT_TNT]		= "TNT",
49a4e92590SAdrian Hunter 	[INTEL_PT_TIP_PGD]	= "TIP.PGD",
50a4e92590SAdrian Hunter 	[INTEL_PT_TIP_PGE]	= "TIP.PGE",
51a4e92590SAdrian Hunter 	[INTEL_PT_TSC]		= "TSC",
523d498078SAdrian Hunter 	[INTEL_PT_TMA]		= "TMA",
53a4e92590SAdrian Hunter 	[INTEL_PT_MODE_EXEC]	= "MODE.Exec",
54a4e92590SAdrian Hunter 	[INTEL_PT_MODE_TSX]	= "MODE.TSX",
553d498078SAdrian Hunter 	[INTEL_PT_MTC]		= "MTC",
56a4e92590SAdrian Hunter 	[INTEL_PT_TIP]		= "TIP",
57a4e92590SAdrian Hunter 	[INTEL_PT_FUP]		= "FUP",
583d498078SAdrian Hunter 	[INTEL_PT_CYC]		= "CYC",
593d498078SAdrian Hunter 	[INTEL_PT_VMCS]		= "VMCS",
60a4e92590SAdrian Hunter 	[INTEL_PT_PSB]		= "PSB",
61a4e92590SAdrian Hunter 	[INTEL_PT_PSBEND]	= "PSBEND",
62a4e92590SAdrian Hunter 	[INTEL_PT_CBR]		= "CBR",
633d498078SAdrian Hunter 	[INTEL_PT_TRACESTOP]	= "TraceSTOP",
64a4e92590SAdrian Hunter 	[INTEL_PT_PIP]		= "PIP",
65a4e92590SAdrian Hunter 	[INTEL_PT_OVF]		= "OVF",
663d498078SAdrian Hunter 	[INTEL_PT_MNT]		= "MNT",
67a4e92590SAdrian Hunter };
68a4e92590SAdrian Hunter 
69a4e92590SAdrian Hunter const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
70a4e92590SAdrian Hunter {
71a4e92590SAdrian Hunter 	return packet_name[type];
72a4e92590SAdrian Hunter }
73a4e92590SAdrian Hunter 
74a4e92590SAdrian Hunter static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len,
75a4e92590SAdrian Hunter 				 struct intel_pt_pkt *packet)
76a4e92590SAdrian Hunter {
77a4e92590SAdrian Hunter 	uint64_t payload;
78a4e92590SAdrian Hunter 	int count;
79a4e92590SAdrian Hunter 
80a4e92590SAdrian Hunter 	if (len < 8)
81a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
82a4e92590SAdrian Hunter 
83a4e92590SAdrian Hunter 	payload = le64_to_cpu(*(uint64_t *)buf);
84a4e92590SAdrian Hunter 
85a4e92590SAdrian Hunter 	for (count = 47; count; count--) {
86a4e92590SAdrian Hunter 		if (payload & BIT63)
87a4e92590SAdrian Hunter 			break;
88a4e92590SAdrian Hunter 		payload <<= 1;
89a4e92590SAdrian Hunter 	}
90a4e92590SAdrian Hunter 
91a4e92590SAdrian Hunter 	packet->type = INTEL_PT_TNT;
92a4e92590SAdrian Hunter 	packet->count = count;
93a4e92590SAdrian Hunter 	packet->payload = payload << 1;
94a4e92590SAdrian Hunter 	return 8;
95a4e92590SAdrian Hunter }
96a4e92590SAdrian Hunter 
97a4e92590SAdrian Hunter static int intel_pt_get_pip(const unsigned char *buf, size_t len,
98a4e92590SAdrian Hunter 			    struct intel_pt_pkt *packet)
99a4e92590SAdrian Hunter {
100a4e92590SAdrian Hunter 	uint64_t payload = 0;
101a4e92590SAdrian Hunter 
102a4e92590SAdrian Hunter 	if (len < 8)
103a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
104a4e92590SAdrian Hunter 
105a4e92590SAdrian Hunter 	packet->type = INTEL_PT_PIP;
106a4e92590SAdrian Hunter 	memcpy_le64(&payload, buf + 2, 6);
107a4e92590SAdrian Hunter 	packet->payload = payload >> 1;
1083d498078SAdrian Hunter 	if (payload & 1)
1093d498078SAdrian Hunter 		packet->payload |= NR_FLAG;
110a4e92590SAdrian Hunter 
111a4e92590SAdrian Hunter 	return 8;
112a4e92590SAdrian Hunter }
113a4e92590SAdrian Hunter 
1143d498078SAdrian Hunter static int intel_pt_get_tracestop(struct intel_pt_pkt *packet)
1153d498078SAdrian Hunter {
1163d498078SAdrian Hunter 	packet->type = INTEL_PT_TRACESTOP;
1173d498078SAdrian Hunter 	return 2;
1183d498078SAdrian Hunter }
1193d498078SAdrian Hunter 
120a4e92590SAdrian Hunter static int intel_pt_get_cbr(const unsigned char *buf, size_t len,
121a4e92590SAdrian Hunter 			    struct intel_pt_pkt *packet)
122a4e92590SAdrian Hunter {
123a4e92590SAdrian Hunter 	if (len < 4)
124a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
125a4e92590SAdrian Hunter 	packet->type = INTEL_PT_CBR;
126a4e92590SAdrian Hunter 	packet->payload = buf[2];
127a4e92590SAdrian Hunter 	return 4;
128a4e92590SAdrian Hunter }
129a4e92590SAdrian Hunter 
1303d498078SAdrian Hunter static int intel_pt_get_vmcs(const unsigned char *buf, size_t len,
1313d498078SAdrian Hunter 			     struct intel_pt_pkt *packet)
1323d498078SAdrian Hunter {
1333d498078SAdrian Hunter 	unsigned int count = (52 - 5) >> 3;
1343d498078SAdrian Hunter 
1353d498078SAdrian Hunter 	if (count < 1 || count > 7)
1363d498078SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
1373d498078SAdrian Hunter 
1383d498078SAdrian Hunter 	if (len < count + 2)
1393d498078SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
1403d498078SAdrian Hunter 
1413d498078SAdrian Hunter 	packet->type = INTEL_PT_VMCS;
1423d498078SAdrian Hunter 	packet->count = count;
1433d498078SAdrian Hunter 	memcpy_le64(&packet->payload, buf + 2, count);
1443d498078SAdrian Hunter 
1453d498078SAdrian Hunter 	return count + 2;
1463d498078SAdrian Hunter }
1473d498078SAdrian Hunter 
148a4e92590SAdrian Hunter static int intel_pt_get_ovf(struct intel_pt_pkt *packet)
149a4e92590SAdrian Hunter {
150a4e92590SAdrian Hunter 	packet->type = INTEL_PT_OVF;
151a4e92590SAdrian Hunter 	return 2;
152a4e92590SAdrian Hunter }
153a4e92590SAdrian Hunter 
154a4e92590SAdrian Hunter static int intel_pt_get_psb(const unsigned char *buf, size_t len,
155a4e92590SAdrian Hunter 			    struct intel_pt_pkt *packet)
156a4e92590SAdrian Hunter {
157a4e92590SAdrian Hunter 	int i;
158a4e92590SAdrian Hunter 
159a4e92590SAdrian Hunter 	if (len < 16)
160a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
161a4e92590SAdrian Hunter 
162a4e92590SAdrian Hunter 	for (i = 2; i < 16; i += 2) {
163a4e92590SAdrian Hunter 		if (buf[i] != 2 || buf[i + 1] != 0x82)
164a4e92590SAdrian Hunter 			return INTEL_PT_BAD_PACKET;
165a4e92590SAdrian Hunter 	}
166a4e92590SAdrian Hunter 
167a4e92590SAdrian Hunter 	packet->type = INTEL_PT_PSB;
168a4e92590SAdrian Hunter 	return 16;
169a4e92590SAdrian Hunter }
170a4e92590SAdrian Hunter 
171a4e92590SAdrian Hunter static int intel_pt_get_psbend(struct intel_pt_pkt *packet)
172a4e92590SAdrian Hunter {
173a4e92590SAdrian Hunter 	packet->type = INTEL_PT_PSBEND;
174a4e92590SAdrian Hunter 	return 2;
175a4e92590SAdrian Hunter }
176a4e92590SAdrian Hunter 
1773d498078SAdrian Hunter static int intel_pt_get_tma(const unsigned char *buf, size_t len,
1783d498078SAdrian Hunter 			    struct intel_pt_pkt *packet)
1793d498078SAdrian Hunter {
1803d498078SAdrian Hunter 	if (len < 7)
1813d498078SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
1823d498078SAdrian Hunter 
1833d498078SAdrian Hunter 	packet->type = INTEL_PT_TMA;
1843d498078SAdrian Hunter 	packet->payload = buf[2] | (buf[3] << 8);
1853d498078SAdrian Hunter 	packet->count = buf[5] | ((buf[6] & BIT(0)) << 8);
1863d498078SAdrian Hunter 	return 7;
1873d498078SAdrian Hunter }
1883d498078SAdrian Hunter 
189a4e92590SAdrian Hunter static int intel_pt_get_pad(struct intel_pt_pkt *packet)
190a4e92590SAdrian Hunter {
191a4e92590SAdrian Hunter 	packet->type = INTEL_PT_PAD;
192a4e92590SAdrian Hunter 	return 1;
193a4e92590SAdrian Hunter }
194a4e92590SAdrian Hunter 
1953d498078SAdrian Hunter static int intel_pt_get_mnt(const unsigned char *buf, size_t len,
1963d498078SAdrian Hunter 			    struct intel_pt_pkt *packet)
1973d498078SAdrian Hunter {
1983d498078SAdrian Hunter 	if (len < 11)
1993d498078SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
2003d498078SAdrian Hunter 	packet->type = INTEL_PT_MNT;
2013d498078SAdrian Hunter 	memcpy_le64(&packet->payload, buf + 3, 8);
2023d498078SAdrian Hunter 	return 11
2033d498078SAdrian Hunter ;
2043d498078SAdrian Hunter }
2053d498078SAdrian Hunter 
2063d498078SAdrian Hunter static int intel_pt_get_3byte(const unsigned char *buf, size_t len,
2073d498078SAdrian Hunter 			      struct intel_pt_pkt *packet)
2083d498078SAdrian Hunter {
2093d498078SAdrian Hunter 	if (len < 3)
2103d498078SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
2113d498078SAdrian Hunter 
2123d498078SAdrian Hunter 	switch (buf[2]) {
2133d498078SAdrian Hunter 	case 0x88: /* MNT */
2143d498078SAdrian Hunter 		return intel_pt_get_mnt(buf, len, packet);
2153d498078SAdrian Hunter 	default:
2163d498078SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
2173d498078SAdrian Hunter 	}
2183d498078SAdrian Hunter }
2193d498078SAdrian Hunter 
220a4e92590SAdrian Hunter static int intel_pt_get_ext(const unsigned char *buf, size_t len,
221a4e92590SAdrian Hunter 			    struct intel_pt_pkt *packet)
222a4e92590SAdrian Hunter {
223a4e92590SAdrian Hunter 	if (len < 2)
224a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
225a4e92590SAdrian Hunter 
226a4e92590SAdrian Hunter 	switch (buf[1]) {
227a4e92590SAdrian Hunter 	case 0xa3: /* Long TNT */
228a4e92590SAdrian Hunter 		return intel_pt_get_long_tnt(buf, len, packet);
229a4e92590SAdrian Hunter 	case 0x43: /* PIP */
230a4e92590SAdrian Hunter 		return intel_pt_get_pip(buf, len, packet);
2313d498078SAdrian Hunter 	case 0x83: /* TraceStop */
2323d498078SAdrian Hunter 		return intel_pt_get_tracestop(packet);
233a4e92590SAdrian Hunter 	case 0x03: /* CBR */
234a4e92590SAdrian Hunter 		return intel_pt_get_cbr(buf, len, packet);
2353d498078SAdrian Hunter 	case 0xc8: /* VMCS */
2363d498078SAdrian Hunter 		return intel_pt_get_vmcs(buf, len, packet);
237a4e92590SAdrian Hunter 	case 0xf3: /* OVF */
238a4e92590SAdrian Hunter 		return intel_pt_get_ovf(packet);
239a4e92590SAdrian Hunter 	case 0x82: /* PSB */
240a4e92590SAdrian Hunter 		return intel_pt_get_psb(buf, len, packet);
241a4e92590SAdrian Hunter 	case 0x23: /* PSBEND */
242a4e92590SAdrian Hunter 		return intel_pt_get_psbend(packet);
2433d498078SAdrian Hunter 	case 0x73: /* TMA */
2443d498078SAdrian Hunter 		return intel_pt_get_tma(buf, len, packet);
2453d498078SAdrian Hunter 	case 0xC3: /* 3-byte header */
2463d498078SAdrian Hunter 		return intel_pt_get_3byte(buf, len, packet);
247a4e92590SAdrian Hunter 	default:
248a4e92590SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
249a4e92590SAdrian Hunter 	}
250a4e92590SAdrian Hunter }
251a4e92590SAdrian Hunter 
252a4e92590SAdrian Hunter static int intel_pt_get_short_tnt(unsigned int byte,
253a4e92590SAdrian Hunter 				  struct intel_pt_pkt *packet)
254a4e92590SAdrian Hunter {
255a4e92590SAdrian Hunter 	int count;
256a4e92590SAdrian Hunter 
257a4e92590SAdrian Hunter 	for (count = 6; count; count--) {
258a4e92590SAdrian Hunter 		if (byte & BIT(7))
259a4e92590SAdrian Hunter 			break;
260a4e92590SAdrian Hunter 		byte <<= 1;
261a4e92590SAdrian Hunter 	}
262a4e92590SAdrian Hunter 
263a4e92590SAdrian Hunter 	packet->type = INTEL_PT_TNT;
264a4e92590SAdrian Hunter 	packet->count = count;
265a4e92590SAdrian Hunter 	packet->payload = (uint64_t)byte << 57;
266a4e92590SAdrian Hunter 
267a4e92590SAdrian Hunter 	return 1;
268a4e92590SAdrian Hunter }
269a4e92590SAdrian Hunter 
2703d498078SAdrian Hunter static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf,
2713d498078SAdrian Hunter 			    size_t len, struct intel_pt_pkt *packet)
2723d498078SAdrian Hunter {
2733d498078SAdrian Hunter 	unsigned int offs = 1, shift;
2743d498078SAdrian Hunter 	uint64_t payload = byte >> 3;
2753d498078SAdrian Hunter 
2763d498078SAdrian Hunter 	byte >>= 2;
2773d498078SAdrian Hunter 	len -= 1;
2783d498078SAdrian Hunter 	for (shift = 5; byte & 1; shift += 7) {
2793d498078SAdrian Hunter 		if (offs > 9)
2803d498078SAdrian Hunter 			return INTEL_PT_BAD_PACKET;
2813d498078SAdrian Hunter 		if (len < offs)
2823d498078SAdrian Hunter 			return INTEL_PT_NEED_MORE_BYTES;
2833d498078SAdrian Hunter 		byte = buf[offs++];
2843d498078SAdrian Hunter 		payload |= (byte >> 1) << shift;
2853d498078SAdrian Hunter 	}
2863d498078SAdrian Hunter 
2873d498078SAdrian Hunter 	packet->type = INTEL_PT_CYC;
2883d498078SAdrian Hunter 	packet->payload = payload;
2893d498078SAdrian Hunter 	return offs;
2903d498078SAdrian Hunter }
2913d498078SAdrian Hunter 
292a4e92590SAdrian Hunter static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
293a4e92590SAdrian Hunter 			   const unsigned char *buf, size_t len,
294a4e92590SAdrian Hunter 			   struct intel_pt_pkt *packet)
295a4e92590SAdrian Hunter {
296e1717e04SAdrian Hunter 	int ip_len;
297e1717e04SAdrian Hunter 
298e1717e04SAdrian Hunter 	packet->count = byte >> 5;
299e1717e04SAdrian Hunter 
300e1717e04SAdrian Hunter 	switch (packet->count) {
301a4e92590SAdrian Hunter 	case 0:
302e1717e04SAdrian Hunter 		ip_len = 0;
303a4e92590SAdrian Hunter 		break;
304a4e92590SAdrian Hunter 	case 1:
305a4e92590SAdrian Hunter 		if (len < 3)
306a4e92590SAdrian Hunter 			return INTEL_PT_NEED_MORE_BYTES;
307e1717e04SAdrian Hunter 		ip_len = 2;
308a4e92590SAdrian Hunter 		packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
309a4e92590SAdrian Hunter 		break;
310a4e92590SAdrian Hunter 	case 2:
311a4e92590SAdrian Hunter 		if (len < 5)
312a4e92590SAdrian Hunter 			return INTEL_PT_NEED_MORE_BYTES;
313e1717e04SAdrian Hunter 		ip_len = 4;
314a4e92590SAdrian Hunter 		packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
315a4e92590SAdrian Hunter 		break;
316a4e92590SAdrian Hunter 	case 3:
317e1717e04SAdrian Hunter 	case 4:
318a4e92590SAdrian Hunter 		if (len < 7)
319a4e92590SAdrian Hunter 			return INTEL_PT_NEED_MORE_BYTES;
320e1717e04SAdrian Hunter 		ip_len = 6;
321a4e92590SAdrian Hunter 		memcpy_le64(&packet->payload, buf + 1, 6);
322a4e92590SAdrian Hunter 		break;
323e1717e04SAdrian Hunter 	case 6:
324e1717e04SAdrian Hunter 		if (len < 9)
325e1717e04SAdrian Hunter 			return INTEL_PT_NEED_MORE_BYTES;
326e1717e04SAdrian Hunter 		ip_len = 8;
327e1717e04SAdrian Hunter 		packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
328e1717e04SAdrian Hunter 		break;
329a4e92590SAdrian Hunter 	default:
330a4e92590SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
331a4e92590SAdrian Hunter 	}
332a4e92590SAdrian Hunter 
333a4e92590SAdrian Hunter 	packet->type = type;
334a4e92590SAdrian Hunter 
335e1717e04SAdrian Hunter 	return ip_len + 1;
336a4e92590SAdrian Hunter }
337a4e92590SAdrian Hunter 
338a4e92590SAdrian Hunter static int intel_pt_get_mode(const unsigned char *buf, size_t len,
339a4e92590SAdrian Hunter 			     struct intel_pt_pkt *packet)
340a4e92590SAdrian Hunter {
341a4e92590SAdrian Hunter 	if (len < 2)
342a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
343a4e92590SAdrian Hunter 
344a4e92590SAdrian Hunter 	switch (buf[1] >> 5) {
345a4e92590SAdrian Hunter 	case 0:
346a4e92590SAdrian Hunter 		packet->type = INTEL_PT_MODE_EXEC;
347a4e92590SAdrian Hunter 		switch (buf[1] & 3) {
348a4e92590SAdrian Hunter 		case 0:
349a4e92590SAdrian Hunter 			packet->payload = 16;
350a4e92590SAdrian Hunter 			break;
351a4e92590SAdrian Hunter 		case 1:
352a4e92590SAdrian Hunter 			packet->payload = 64;
353a4e92590SAdrian Hunter 			break;
354a4e92590SAdrian Hunter 		case 2:
355a4e92590SAdrian Hunter 			packet->payload = 32;
356a4e92590SAdrian Hunter 			break;
357a4e92590SAdrian Hunter 		default:
358a4e92590SAdrian Hunter 			return INTEL_PT_BAD_PACKET;
359a4e92590SAdrian Hunter 		}
360a4e92590SAdrian Hunter 		break;
361a4e92590SAdrian Hunter 	case 1:
362a4e92590SAdrian Hunter 		packet->type = INTEL_PT_MODE_TSX;
363a4e92590SAdrian Hunter 		if ((buf[1] & 3) == 3)
364a4e92590SAdrian Hunter 			return INTEL_PT_BAD_PACKET;
365a4e92590SAdrian Hunter 		packet->payload = buf[1] & 3;
366a4e92590SAdrian Hunter 		break;
367a4e92590SAdrian Hunter 	default:
368a4e92590SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
369a4e92590SAdrian Hunter 	}
370a4e92590SAdrian Hunter 
371a4e92590SAdrian Hunter 	return 2;
372a4e92590SAdrian Hunter }
373a4e92590SAdrian Hunter 
374a4e92590SAdrian Hunter static int intel_pt_get_tsc(const unsigned char *buf, size_t len,
375a4e92590SAdrian Hunter 			    struct intel_pt_pkt *packet)
376a4e92590SAdrian Hunter {
377a4e92590SAdrian Hunter 	if (len < 8)
378a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
379a4e92590SAdrian Hunter 	packet->type = INTEL_PT_TSC;
380a4e92590SAdrian Hunter 	memcpy_le64(&packet->payload, buf + 1, 7);
381a4e92590SAdrian Hunter 	return 8;
382a4e92590SAdrian Hunter }
383a4e92590SAdrian Hunter 
3843d498078SAdrian Hunter static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
3853d498078SAdrian Hunter 			    struct intel_pt_pkt *packet)
3863d498078SAdrian Hunter {
3873d498078SAdrian Hunter 	if (len < 2)
3883d498078SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
3893d498078SAdrian Hunter 	packet->type = INTEL_PT_MTC;
3903d498078SAdrian Hunter 	packet->payload = buf[1];
3913d498078SAdrian Hunter 	return 2;
3923d498078SAdrian Hunter }
3933d498078SAdrian Hunter 
394a4e92590SAdrian Hunter static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
395a4e92590SAdrian Hunter 				  struct intel_pt_pkt *packet)
396a4e92590SAdrian Hunter {
397a4e92590SAdrian Hunter 	unsigned int byte;
398a4e92590SAdrian Hunter 
399a4e92590SAdrian Hunter 	memset(packet, 0, sizeof(struct intel_pt_pkt));
400a4e92590SAdrian Hunter 
401a4e92590SAdrian Hunter 	if (!len)
402a4e92590SAdrian Hunter 		return INTEL_PT_NEED_MORE_BYTES;
403a4e92590SAdrian Hunter 
404a4e92590SAdrian Hunter 	byte = buf[0];
405a4e92590SAdrian Hunter 	if (!(byte & BIT(0))) {
406a4e92590SAdrian Hunter 		if (byte == 0)
407a4e92590SAdrian Hunter 			return intel_pt_get_pad(packet);
408a4e92590SAdrian Hunter 		if (byte == 2)
409a4e92590SAdrian Hunter 			return intel_pt_get_ext(buf, len, packet);
410a4e92590SAdrian Hunter 		return intel_pt_get_short_tnt(byte, packet);
411a4e92590SAdrian Hunter 	}
412a4e92590SAdrian Hunter 
4133d498078SAdrian Hunter 	if ((byte & 2))
4143d498078SAdrian Hunter 		return intel_pt_get_cyc(byte, buf, len, packet);
4153d498078SAdrian Hunter 
416a4e92590SAdrian Hunter 	switch (byte & 0x1f) {
417a4e92590SAdrian Hunter 	case 0x0D:
418a4e92590SAdrian Hunter 		return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
419a4e92590SAdrian Hunter 	case 0x11:
420a4e92590SAdrian Hunter 		return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
421a4e92590SAdrian Hunter 				       packet);
422a4e92590SAdrian Hunter 	case 0x01:
423a4e92590SAdrian Hunter 		return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
424a4e92590SAdrian Hunter 				       packet);
425a4e92590SAdrian Hunter 	case 0x1D:
426a4e92590SAdrian Hunter 		return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
427a4e92590SAdrian Hunter 	case 0x19:
428a4e92590SAdrian Hunter 		switch (byte) {
429a4e92590SAdrian Hunter 		case 0x99:
430a4e92590SAdrian Hunter 			return intel_pt_get_mode(buf, len, packet);
431a4e92590SAdrian Hunter 		case 0x19:
432a4e92590SAdrian Hunter 			return intel_pt_get_tsc(buf, len, packet);
4333d498078SAdrian Hunter 		case 0x59:
4343d498078SAdrian Hunter 			return intel_pt_get_mtc(buf, len, packet);
435a4e92590SAdrian Hunter 		default:
436a4e92590SAdrian Hunter 			return INTEL_PT_BAD_PACKET;
437a4e92590SAdrian Hunter 		}
438a4e92590SAdrian Hunter 	default:
439a4e92590SAdrian Hunter 		return INTEL_PT_BAD_PACKET;
440a4e92590SAdrian Hunter 	}
441a4e92590SAdrian Hunter }
442a4e92590SAdrian Hunter 
443a4e92590SAdrian Hunter int intel_pt_get_packet(const unsigned char *buf, size_t len,
444a4e92590SAdrian Hunter 			struct intel_pt_pkt *packet)
445a4e92590SAdrian Hunter {
446a4e92590SAdrian Hunter 	int ret;
447a4e92590SAdrian Hunter 
448a4e92590SAdrian Hunter 	ret = intel_pt_do_get_packet(buf, len, packet);
449a4e92590SAdrian Hunter 	if (ret > 0) {
450a4e92590SAdrian Hunter 		while (ret < 8 && len > (size_t)ret && !buf[ret])
451a4e92590SAdrian Hunter 			ret += 1;
452a4e92590SAdrian Hunter 	}
453a4e92590SAdrian Hunter 	return ret;
454a4e92590SAdrian Hunter }
455a4e92590SAdrian Hunter 
456a4e92590SAdrian Hunter int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
457a4e92590SAdrian Hunter 		      size_t buf_len)
458a4e92590SAdrian Hunter {
4593d498078SAdrian Hunter 	int ret, i, nr;
460a4e92590SAdrian Hunter 	unsigned long long payload = packet->payload;
461a4e92590SAdrian Hunter 	const char *name = intel_pt_pkt_name(packet->type);
462a4e92590SAdrian Hunter 
463a4e92590SAdrian Hunter 	switch (packet->type) {
464a4e92590SAdrian Hunter 	case INTEL_PT_BAD:
465a4e92590SAdrian Hunter 	case INTEL_PT_PAD:
466a4e92590SAdrian Hunter 	case INTEL_PT_PSB:
467a4e92590SAdrian Hunter 	case INTEL_PT_PSBEND:
4683d498078SAdrian Hunter 	case INTEL_PT_TRACESTOP:
469a4e92590SAdrian Hunter 	case INTEL_PT_OVF:
470a4e92590SAdrian Hunter 		return snprintf(buf, buf_len, "%s", name);
471a4e92590SAdrian Hunter 	case INTEL_PT_TNT: {
472a4e92590SAdrian Hunter 		size_t blen = buf_len;
473a4e92590SAdrian Hunter 
474a4e92590SAdrian Hunter 		ret = snprintf(buf, blen, "%s ", name);
475a4e92590SAdrian Hunter 		if (ret < 0)
476a4e92590SAdrian Hunter 			return ret;
477a4e92590SAdrian Hunter 		buf += ret;
478a4e92590SAdrian Hunter 		blen -= ret;
479a4e92590SAdrian Hunter 		for (i = 0; i < packet->count; i++) {
480a4e92590SAdrian Hunter 			if (payload & BIT63)
481a4e92590SAdrian Hunter 				ret = snprintf(buf, blen, "T");
482a4e92590SAdrian Hunter 			else
483a4e92590SAdrian Hunter 				ret = snprintf(buf, blen, "N");
484a4e92590SAdrian Hunter 			if (ret < 0)
485a4e92590SAdrian Hunter 				return ret;
486a4e92590SAdrian Hunter 			buf += ret;
487a4e92590SAdrian Hunter 			blen -= ret;
488a4e92590SAdrian Hunter 			payload <<= 1;
489a4e92590SAdrian Hunter 		}
490a4e92590SAdrian Hunter 		ret = snprintf(buf, blen, " (%d)", packet->count);
491a4e92590SAdrian Hunter 		if (ret < 0)
492a4e92590SAdrian Hunter 			return ret;
493a4e92590SAdrian Hunter 		blen -= ret;
494a4e92590SAdrian Hunter 		return buf_len - blen;
495a4e92590SAdrian Hunter 	}
496a4e92590SAdrian Hunter 	case INTEL_PT_TIP_PGD:
497a4e92590SAdrian Hunter 	case INTEL_PT_TIP_PGE:
498a4e92590SAdrian Hunter 	case INTEL_PT_TIP:
499a4e92590SAdrian Hunter 	case INTEL_PT_FUP:
500a4e92590SAdrian Hunter 		if (!(packet->count))
501a4e92590SAdrian Hunter 			return snprintf(buf, buf_len, "%s no ip", name);
502*7ea6856dSArnaldo Carvalho de Melo 		__fallthrough;
5033d498078SAdrian Hunter 	case INTEL_PT_CYC:
5043d498078SAdrian Hunter 	case INTEL_PT_VMCS:
5053d498078SAdrian Hunter 	case INTEL_PT_MTC:
5063d498078SAdrian Hunter 	case INTEL_PT_MNT:
507a4e92590SAdrian Hunter 	case INTEL_PT_CBR:
508a4e92590SAdrian Hunter 	case INTEL_PT_TSC:
5093d498078SAdrian Hunter 		return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
5103d498078SAdrian Hunter 	case INTEL_PT_TMA:
5113d498078SAdrian Hunter 		return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name,
5123d498078SAdrian Hunter 				(unsigned)payload, packet->count);
513a4e92590SAdrian Hunter 	case INTEL_PT_MODE_EXEC:
514a4e92590SAdrian Hunter 		return snprintf(buf, buf_len, "%s %lld", name, payload);
515a4e92590SAdrian Hunter 	case INTEL_PT_MODE_TSX:
516a4e92590SAdrian Hunter 		return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
517a4e92590SAdrian Hunter 				name, (unsigned)(payload >> 1) & 1,
518a4e92590SAdrian Hunter 				(unsigned)payload & 1);
519a4e92590SAdrian Hunter 	case INTEL_PT_PIP:
5203d498078SAdrian Hunter 		nr = packet->payload & NR_FLAG ? 1 : 0;
5213d498078SAdrian Hunter 		payload &= ~NR_FLAG;
5223d498078SAdrian Hunter 		ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
5233d498078SAdrian Hunter 			       name, payload, nr);
524a4e92590SAdrian Hunter 		return ret;
525a4e92590SAdrian Hunter 	default:
526a4e92590SAdrian Hunter 		break;
527a4e92590SAdrian Hunter 	}
528a4e92590SAdrian Hunter 	return snprintf(buf, buf_len, "%s 0x%llx (%d)",
529a4e92590SAdrian Hunter 			name, payload, packet->count);
530a4e92590SAdrian Hunter }
531