12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a4e92590SAdrian Hunter /*
3a4e92590SAdrian Hunter * intel_pt_pkt_decoder.c: Intel Processor Trace support
4a4e92590SAdrian Hunter * Copyright (c) 2013-2014, Intel Corporation.
5a4e92590SAdrian Hunter */
6a4e92590SAdrian Hunter
7a4e92590SAdrian Hunter #include <stdio.h>
8a4e92590SAdrian Hunter #include <string.h>
9a4e92590SAdrian Hunter #include <endian.h>
10a4e92590SAdrian Hunter #include <byteswap.h>
11f058fa5bSAdrian Hunter #include <linux/kernel.h>
127ea6856dSArnaldo Carvalho de Melo #include <linux/compiler.h>
133b4fa67fSAdrian Hunter #include <asm-generic/unaligned.h>
14a4e92590SAdrian Hunter
15a4e92590SAdrian Hunter #include "intel-pt-pkt-decoder.h"
16a4e92590SAdrian Hunter
17a4e92590SAdrian Hunter #define BIT(n) (1 << (n))
18a4e92590SAdrian Hunter
19a4e92590SAdrian Hunter #define BIT63 ((uint64_t)1 << 63)
20a4e92590SAdrian Hunter
214e88118cSIlya Leoshkevich #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
22a4e92590SAdrian Hunter #define memcpy_le64(d, s, n) do { \
23a4e92590SAdrian Hunter memcpy((d), (s), (n)); \
24a4e92590SAdrian Hunter *(d) = le64_to_cpu(*(d)); \
25a4e92590SAdrian Hunter } while (0)
26a4e92590SAdrian Hunter #else
27a4e92590SAdrian Hunter #define memcpy_le64 memcpy
28a4e92590SAdrian Hunter #endif
29a4e92590SAdrian Hunter
30a4e92590SAdrian Hunter static const char * const packet_name[] = {
31a4e92590SAdrian Hunter [INTEL_PT_BAD] = "Bad Packet!",
32a4e92590SAdrian Hunter [INTEL_PT_PAD] = "PAD",
33a4e92590SAdrian Hunter [INTEL_PT_TNT] = "TNT",
34a4e92590SAdrian Hunter [INTEL_PT_TIP_PGD] = "TIP.PGD",
35a4e92590SAdrian Hunter [INTEL_PT_TIP_PGE] = "TIP.PGE",
36a4e92590SAdrian Hunter [INTEL_PT_TSC] = "TSC",
373d498078SAdrian Hunter [INTEL_PT_TMA] = "TMA",
38a4e92590SAdrian Hunter [INTEL_PT_MODE_EXEC] = "MODE.Exec",
39a4e92590SAdrian Hunter [INTEL_PT_MODE_TSX] = "MODE.TSX",
403d498078SAdrian Hunter [INTEL_PT_MTC] = "MTC",
41a4e92590SAdrian Hunter [INTEL_PT_TIP] = "TIP",
42a4e92590SAdrian Hunter [INTEL_PT_FUP] = "FUP",
433d498078SAdrian Hunter [INTEL_PT_CYC] = "CYC",
443d498078SAdrian Hunter [INTEL_PT_VMCS] = "VMCS",
45a4e92590SAdrian Hunter [INTEL_PT_PSB] = "PSB",
46a4e92590SAdrian Hunter [INTEL_PT_PSBEND] = "PSBEND",
47a4e92590SAdrian Hunter [INTEL_PT_CBR] = "CBR",
483d498078SAdrian Hunter [INTEL_PT_TRACESTOP] = "TraceSTOP",
49a4e92590SAdrian Hunter [INTEL_PT_PIP] = "PIP",
50a4e92590SAdrian Hunter [INTEL_PT_OVF] = "OVF",
513d498078SAdrian Hunter [INTEL_PT_MNT] = "MNT",
52a472e65fSAdrian Hunter [INTEL_PT_PTWRITE] = "PTWRITE",
53a472e65fSAdrian Hunter [INTEL_PT_PTWRITE_IP] = "PTWRITE",
54a472e65fSAdrian Hunter [INTEL_PT_EXSTOP] = "EXSTOP",
55a472e65fSAdrian Hunter [INTEL_PT_EXSTOP_IP] = "EXSTOP",
56a472e65fSAdrian Hunter [INTEL_PT_MWAIT] = "MWAIT",
57a472e65fSAdrian Hunter [INTEL_PT_PWRE] = "PWRE",
58a472e65fSAdrian Hunter [INTEL_PT_PWRX] = "PWRX",
59edff7809SAdrian Hunter [INTEL_PT_BBP] = "BBP",
60edff7809SAdrian Hunter [INTEL_PT_BIP] = "BIP",
61edff7809SAdrian Hunter [INTEL_PT_BEP] = "BEP",
62edff7809SAdrian Hunter [INTEL_PT_BEP_IP] = "BEP",
632750af50SAdrian Hunter [INTEL_PT_CFE] = "CFE",
642750af50SAdrian Hunter [INTEL_PT_CFE_IP] = "CFE",
652750af50SAdrian Hunter [INTEL_PT_EVD] = "EVD",
66a4e92590SAdrian Hunter };
67a4e92590SAdrian Hunter
intel_pt_pkt_name(enum intel_pt_pkt_type type)68a4e92590SAdrian Hunter const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
69a4e92590SAdrian Hunter {
70a4e92590SAdrian Hunter return packet_name[type];
71a4e92590SAdrian Hunter }
72a4e92590SAdrian Hunter
intel_pt_get_long_tnt(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)73a4e92590SAdrian Hunter static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len,
74a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
75a4e92590SAdrian Hunter {
76a4e92590SAdrian Hunter uint64_t payload;
77a4e92590SAdrian Hunter int count;
78a4e92590SAdrian Hunter
79a4e92590SAdrian Hunter if (len < 8)
80a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
81a4e92590SAdrian Hunter
823b4fa67fSAdrian Hunter payload = get_unaligned_le64(buf);
83a4e92590SAdrian Hunter
84a4e92590SAdrian Hunter for (count = 47; count; count--) {
85a4e92590SAdrian Hunter if (payload & BIT63)
86a4e92590SAdrian Hunter break;
87a4e92590SAdrian Hunter payload <<= 1;
88a4e92590SAdrian Hunter }
89a4e92590SAdrian Hunter
90a4e92590SAdrian Hunter packet->type = INTEL_PT_TNT;
91a4e92590SAdrian Hunter packet->count = count;
92a4e92590SAdrian Hunter packet->payload = payload << 1;
93a4e92590SAdrian Hunter return 8;
94a4e92590SAdrian Hunter }
95a4e92590SAdrian Hunter
intel_pt_get_pip(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)96a4e92590SAdrian Hunter static int intel_pt_get_pip(const unsigned char *buf, size_t len,
97a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
98a4e92590SAdrian Hunter {
99a4e92590SAdrian Hunter uint64_t payload = 0;
100a4e92590SAdrian Hunter
101a4e92590SAdrian Hunter if (len < 8)
102a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
103a4e92590SAdrian Hunter
104a4e92590SAdrian Hunter packet->type = INTEL_PT_PIP;
105a4e92590SAdrian Hunter memcpy_le64(&payload, buf + 2, 6);
10690af7555SAdrian Hunter packet->payload = payload;
107a4e92590SAdrian Hunter
108a4e92590SAdrian Hunter return 8;
109a4e92590SAdrian Hunter }
110a4e92590SAdrian Hunter
intel_pt_get_tracestop(struct intel_pt_pkt * packet)1113d498078SAdrian Hunter static int intel_pt_get_tracestop(struct intel_pt_pkt *packet)
1123d498078SAdrian Hunter {
1133d498078SAdrian Hunter packet->type = INTEL_PT_TRACESTOP;
1143d498078SAdrian Hunter return 2;
1153d498078SAdrian Hunter }
1163d498078SAdrian Hunter
intel_pt_get_cbr(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)117a4e92590SAdrian Hunter static int intel_pt_get_cbr(const unsigned char *buf, size_t len,
118a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
119a4e92590SAdrian Hunter {
120a4e92590SAdrian Hunter if (len < 4)
121a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
122a4e92590SAdrian Hunter packet->type = INTEL_PT_CBR;
1233b4fa67fSAdrian Hunter packet->payload = get_unaligned_le16(buf + 2);
124a4e92590SAdrian Hunter return 4;
125a4e92590SAdrian Hunter }
126a4e92590SAdrian Hunter
intel_pt_get_vmcs(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)1273d498078SAdrian Hunter static int intel_pt_get_vmcs(const unsigned char *buf, size_t len,
1283d498078SAdrian Hunter struct intel_pt_pkt *packet)
1293d498078SAdrian Hunter {
1301d2dbce9SAdrian Hunter if (len < 7)
1313d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
1323d498078SAdrian Hunter
1333d498078SAdrian Hunter packet->type = INTEL_PT_VMCS;
1341d2dbce9SAdrian Hunter packet->count = 5;
1351d2dbce9SAdrian Hunter memcpy_le64(&packet->payload, buf + 2, 5);
1363d498078SAdrian Hunter
1371d2dbce9SAdrian Hunter return 7;
1383d498078SAdrian Hunter }
1393d498078SAdrian Hunter
intel_pt_get_ovf(struct intel_pt_pkt * packet)140a4e92590SAdrian Hunter static int intel_pt_get_ovf(struct intel_pt_pkt *packet)
141a4e92590SAdrian Hunter {
142a4e92590SAdrian Hunter packet->type = INTEL_PT_OVF;
143a4e92590SAdrian Hunter return 2;
144a4e92590SAdrian Hunter }
145a4e92590SAdrian Hunter
intel_pt_get_psb(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)146a4e92590SAdrian Hunter static int intel_pt_get_psb(const unsigned char *buf, size_t len,
147a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
148a4e92590SAdrian Hunter {
149a4e92590SAdrian Hunter int i;
150a4e92590SAdrian Hunter
151a4e92590SAdrian Hunter if (len < 16)
152a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
153a4e92590SAdrian Hunter
154a4e92590SAdrian Hunter for (i = 2; i < 16; i += 2) {
155a4e92590SAdrian Hunter if (buf[i] != 2 || buf[i + 1] != 0x82)
156a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
157a4e92590SAdrian Hunter }
158a4e92590SAdrian Hunter
159a4e92590SAdrian Hunter packet->type = INTEL_PT_PSB;
160a4e92590SAdrian Hunter return 16;
161a4e92590SAdrian Hunter }
162a4e92590SAdrian Hunter
intel_pt_get_psbend(struct intel_pt_pkt * packet)163a4e92590SAdrian Hunter static int intel_pt_get_psbend(struct intel_pt_pkt *packet)
164a4e92590SAdrian Hunter {
165a4e92590SAdrian Hunter packet->type = INTEL_PT_PSBEND;
166a4e92590SAdrian Hunter return 2;
167a4e92590SAdrian Hunter }
168a4e92590SAdrian Hunter
intel_pt_get_tma(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)1693d498078SAdrian Hunter static int intel_pt_get_tma(const unsigned char *buf, size_t len,
1703d498078SAdrian Hunter struct intel_pt_pkt *packet)
1713d498078SAdrian Hunter {
1723d498078SAdrian Hunter if (len < 7)
1733d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
1743d498078SAdrian Hunter
1753d498078SAdrian Hunter packet->type = INTEL_PT_TMA;
1763d498078SAdrian Hunter packet->payload = buf[2] | (buf[3] << 8);
1773d498078SAdrian Hunter packet->count = buf[5] | ((buf[6] & BIT(0)) << 8);
1783d498078SAdrian Hunter return 7;
1793d498078SAdrian Hunter }
1803d498078SAdrian Hunter
intel_pt_get_pad(struct intel_pt_pkt * packet)181a4e92590SAdrian Hunter static int intel_pt_get_pad(struct intel_pt_pkt *packet)
182a4e92590SAdrian Hunter {
183a4e92590SAdrian Hunter packet->type = INTEL_PT_PAD;
184a4e92590SAdrian Hunter return 1;
185a4e92590SAdrian Hunter }
186a4e92590SAdrian Hunter
intel_pt_get_mnt(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)1873d498078SAdrian Hunter static int intel_pt_get_mnt(const unsigned char *buf, size_t len,
1883d498078SAdrian Hunter struct intel_pt_pkt *packet)
1893d498078SAdrian Hunter {
1903d498078SAdrian Hunter if (len < 11)
1913d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
1923d498078SAdrian Hunter packet->type = INTEL_PT_MNT;
193*661ce781SAdrian Hunter packet->payload = get_unaligned_le64(buf + 3);
1946816c254SAdrian Hunter return 11;
1953d498078SAdrian Hunter }
1963d498078SAdrian Hunter
intel_pt_get_3byte(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)1973d498078SAdrian Hunter static int intel_pt_get_3byte(const unsigned char *buf, size_t len,
1983d498078SAdrian Hunter struct intel_pt_pkt *packet)
1993d498078SAdrian Hunter {
2003d498078SAdrian Hunter if (len < 3)
2013d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
2023d498078SAdrian Hunter
2033d498078SAdrian Hunter switch (buf[2]) {
2043d498078SAdrian Hunter case 0x88: /* MNT */
2053d498078SAdrian Hunter return intel_pt_get_mnt(buf, len, packet);
2063d498078SAdrian Hunter default:
2073d498078SAdrian Hunter return INTEL_PT_BAD_PACKET;
2083d498078SAdrian Hunter }
2093d498078SAdrian Hunter }
2103d498078SAdrian Hunter
intel_pt_get_ptwrite(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)211a472e65fSAdrian Hunter static int intel_pt_get_ptwrite(const unsigned char *buf, size_t len,
212a472e65fSAdrian Hunter struct intel_pt_pkt *packet)
213a472e65fSAdrian Hunter {
214a472e65fSAdrian Hunter packet->count = (buf[1] >> 5) & 0x3;
215a472e65fSAdrian Hunter packet->type = buf[1] & BIT(7) ? INTEL_PT_PTWRITE_IP :
216a472e65fSAdrian Hunter INTEL_PT_PTWRITE;
217a472e65fSAdrian Hunter
218a472e65fSAdrian Hunter switch (packet->count) {
219a472e65fSAdrian Hunter case 0:
220a472e65fSAdrian Hunter if (len < 6)
221a472e65fSAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
2223b4fa67fSAdrian Hunter packet->payload = get_unaligned_le32(buf + 2);
223a472e65fSAdrian Hunter return 6;
224a472e65fSAdrian Hunter case 1:
225a472e65fSAdrian Hunter if (len < 10)
226a472e65fSAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
2273b4fa67fSAdrian Hunter packet->payload = get_unaligned_le64(buf + 2);
228a472e65fSAdrian Hunter return 10;
229a472e65fSAdrian Hunter default:
230a472e65fSAdrian Hunter return INTEL_PT_BAD_PACKET;
231a472e65fSAdrian Hunter }
232a472e65fSAdrian Hunter }
233a472e65fSAdrian Hunter
intel_pt_get_exstop(struct intel_pt_pkt * packet)234a472e65fSAdrian Hunter static int intel_pt_get_exstop(struct intel_pt_pkt *packet)
235a472e65fSAdrian Hunter {
236a472e65fSAdrian Hunter packet->type = INTEL_PT_EXSTOP;
237a472e65fSAdrian Hunter return 2;
238a472e65fSAdrian Hunter }
239a472e65fSAdrian Hunter
intel_pt_get_exstop_ip(struct intel_pt_pkt * packet)240a472e65fSAdrian Hunter static int intel_pt_get_exstop_ip(struct intel_pt_pkt *packet)
241a472e65fSAdrian Hunter {
242a472e65fSAdrian Hunter packet->type = INTEL_PT_EXSTOP_IP;
243a472e65fSAdrian Hunter return 2;
244a472e65fSAdrian Hunter }
245a472e65fSAdrian Hunter
intel_pt_get_mwait(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)246a472e65fSAdrian Hunter static int intel_pt_get_mwait(const unsigned char *buf, size_t len,
247a472e65fSAdrian Hunter struct intel_pt_pkt *packet)
248a472e65fSAdrian Hunter {
249a472e65fSAdrian Hunter if (len < 10)
250a472e65fSAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
251a472e65fSAdrian Hunter packet->type = INTEL_PT_MWAIT;
2523b4fa67fSAdrian Hunter packet->payload = get_unaligned_le64(buf + 2);
253a472e65fSAdrian Hunter return 10;
254a472e65fSAdrian Hunter }
255a472e65fSAdrian Hunter
intel_pt_get_pwre(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)256a472e65fSAdrian Hunter static int intel_pt_get_pwre(const unsigned char *buf, size_t len,
257a472e65fSAdrian Hunter struct intel_pt_pkt *packet)
258a472e65fSAdrian Hunter {
259a472e65fSAdrian Hunter if (len < 4)
260a472e65fSAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
261a472e65fSAdrian Hunter packet->type = INTEL_PT_PWRE;
262a472e65fSAdrian Hunter memcpy_le64(&packet->payload, buf + 2, 2);
263a472e65fSAdrian Hunter return 4;
264a472e65fSAdrian Hunter }
265a472e65fSAdrian Hunter
intel_pt_get_pwrx(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)266a472e65fSAdrian Hunter static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
267a472e65fSAdrian Hunter struct intel_pt_pkt *packet)
268a472e65fSAdrian Hunter {
269a472e65fSAdrian Hunter if (len < 7)
270a472e65fSAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
271a472e65fSAdrian Hunter packet->type = INTEL_PT_PWRX;
272a472e65fSAdrian Hunter memcpy_le64(&packet->payload, buf + 2, 5);
273a472e65fSAdrian Hunter return 7;
274a472e65fSAdrian Hunter }
275a472e65fSAdrian Hunter
intel_pt_get_bbp(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)276edff7809SAdrian Hunter static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
277edff7809SAdrian Hunter struct intel_pt_pkt *packet)
278edff7809SAdrian Hunter {
279edff7809SAdrian Hunter if (len < 3)
280edff7809SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
281edff7809SAdrian Hunter packet->type = INTEL_PT_BBP;
282edff7809SAdrian Hunter packet->count = buf[2] >> 7;
283edff7809SAdrian Hunter packet->payload = buf[2] & 0x1f;
284edff7809SAdrian Hunter return 3;
285edff7809SAdrian Hunter }
286edff7809SAdrian Hunter
intel_pt_get_bip_4(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)287edff7809SAdrian Hunter static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
288edff7809SAdrian Hunter struct intel_pt_pkt *packet)
289edff7809SAdrian Hunter {
290edff7809SAdrian Hunter if (len < 5)
291edff7809SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
292edff7809SAdrian Hunter packet->type = INTEL_PT_BIP;
293edff7809SAdrian Hunter packet->count = buf[0] >> 3;
294edff7809SAdrian Hunter memcpy_le64(&packet->payload, buf + 1, 4);
295edff7809SAdrian Hunter return 5;
296edff7809SAdrian Hunter }
297edff7809SAdrian Hunter
intel_pt_get_bip_8(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)298edff7809SAdrian Hunter static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
299edff7809SAdrian Hunter struct intel_pt_pkt *packet)
300edff7809SAdrian Hunter {
301edff7809SAdrian Hunter if (len < 9)
302edff7809SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
303edff7809SAdrian Hunter packet->type = INTEL_PT_BIP;
304edff7809SAdrian Hunter packet->count = buf[0] >> 3;
305*661ce781SAdrian Hunter packet->payload = get_unaligned_le64(buf + 1);
306edff7809SAdrian Hunter return 9;
307edff7809SAdrian Hunter }
308edff7809SAdrian Hunter
intel_pt_get_bep(size_t len,struct intel_pt_pkt * packet)309edff7809SAdrian Hunter static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
310edff7809SAdrian Hunter {
311edff7809SAdrian Hunter if (len < 2)
312edff7809SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
313edff7809SAdrian Hunter packet->type = INTEL_PT_BEP;
314edff7809SAdrian Hunter return 2;
315edff7809SAdrian Hunter }
316edff7809SAdrian Hunter
intel_pt_get_bep_ip(size_t len,struct intel_pt_pkt * packet)317edff7809SAdrian Hunter static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
318edff7809SAdrian Hunter {
319edff7809SAdrian Hunter if (len < 2)
320edff7809SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
321edff7809SAdrian Hunter packet->type = INTEL_PT_BEP_IP;
322edff7809SAdrian Hunter return 2;
323edff7809SAdrian Hunter }
324edff7809SAdrian Hunter
intel_pt_get_cfe(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)3252750af50SAdrian Hunter static int intel_pt_get_cfe(const unsigned char *buf, size_t len,
3262750af50SAdrian Hunter struct intel_pt_pkt *packet)
3272750af50SAdrian Hunter {
3282750af50SAdrian Hunter if (len < 4)
3292750af50SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
3302750af50SAdrian Hunter packet->type = buf[2] & 0x80 ? INTEL_PT_CFE_IP : INTEL_PT_CFE;
3312750af50SAdrian Hunter packet->count = buf[2] & 0x1f;
3322750af50SAdrian Hunter packet->payload = buf[3];
3332750af50SAdrian Hunter return 4;
3342750af50SAdrian Hunter }
3352750af50SAdrian Hunter
intel_pt_get_evd(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)3362750af50SAdrian Hunter static int intel_pt_get_evd(const unsigned char *buf, size_t len,
3372750af50SAdrian Hunter struct intel_pt_pkt *packet)
3382750af50SAdrian Hunter {
3392750af50SAdrian Hunter if (len < 11)
3402750af50SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
3412750af50SAdrian Hunter packet->type = INTEL_PT_EVD;
3422750af50SAdrian Hunter packet->count = buf[2] & 0x3f;
3432750af50SAdrian Hunter packet->payload = buf[3];
344*661ce781SAdrian Hunter packet->payload = get_unaligned_le64(buf + 3);
3452750af50SAdrian Hunter return 11;
3462750af50SAdrian Hunter }
3472750af50SAdrian Hunter
intel_pt_get_ext(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)348a4e92590SAdrian Hunter static int intel_pt_get_ext(const unsigned char *buf, size_t len,
349a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
350a4e92590SAdrian Hunter {
351a4e92590SAdrian Hunter if (len < 2)
352a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
353a4e92590SAdrian Hunter
354a472e65fSAdrian Hunter if ((buf[1] & 0x1f) == 0x12)
355a472e65fSAdrian Hunter return intel_pt_get_ptwrite(buf, len, packet);
356a472e65fSAdrian Hunter
357a4e92590SAdrian Hunter switch (buf[1]) {
358a4e92590SAdrian Hunter case 0xa3: /* Long TNT */
359a4e92590SAdrian Hunter return intel_pt_get_long_tnt(buf, len, packet);
360a4e92590SAdrian Hunter case 0x43: /* PIP */
361a4e92590SAdrian Hunter return intel_pt_get_pip(buf, len, packet);
3623d498078SAdrian Hunter case 0x83: /* TraceStop */
3633d498078SAdrian Hunter return intel_pt_get_tracestop(packet);
364a4e92590SAdrian Hunter case 0x03: /* CBR */
365a4e92590SAdrian Hunter return intel_pt_get_cbr(buf, len, packet);
3663d498078SAdrian Hunter case 0xc8: /* VMCS */
3673d498078SAdrian Hunter return intel_pt_get_vmcs(buf, len, packet);
368a4e92590SAdrian Hunter case 0xf3: /* OVF */
369a4e92590SAdrian Hunter return intel_pt_get_ovf(packet);
370a4e92590SAdrian Hunter case 0x82: /* PSB */
371a4e92590SAdrian Hunter return intel_pt_get_psb(buf, len, packet);
372a4e92590SAdrian Hunter case 0x23: /* PSBEND */
373a4e92590SAdrian Hunter return intel_pt_get_psbend(packet);
3743d498078SAdrian Hunter case 0x73: /* TMA */
3753d498078SAdrian Hunter return intel_pt_get_tma(buf, len, packet);
3763d498078SAdrian Hunter case 0xC3: /* 3-byte header */
3773d498078SAdrian Hunter return intel_pt_get_3byte(buf, len, packet);
378a472e65fSAdrian Hunter case 0x62: /* EXSTOP no IP */
379a472e65fSAdrian Hunter return intel_pt_get_exstop(packet);
380a472e65fSAdrian Hunter case 0xE2: /* EXSTOP with IP */
381a472e65fSAdrian Hunter return intel_pt_get_exstop_ip(packet);
382a472e65fSAdrian Hunter case 0xC2: /* MWAIT */
383a472e65fSAdrian Hunter return intel_pt_get_mwait(buf, len, packet);
384a472e65fSAdrian Hunter case 0x22: /* PWRE */
385a472e65fSAdrian Hunter return intel_pt_get_pwre(buf, len, packet);
386a472e65fSAdrian Hunter case 0xA2: /* PWRX */
387a472e65fSAdrian Hunter return intel_pt_get_pwrx(buf, len, packet);
388edff7809SAdrian Hunter case 0x63: /* BBP */
389edff7809SAdrian Hunter return intel_pt_get_bbp(buf, len, packet);
390edff7809SAdrian Hunter case 0x33: /* BEP no IP */
391edff7809SAdrian Hunter return intel_pt_get_bep(len, packet);
392edff7809SAdrian Hunter case 0xb3: /* BEP with IP */
393edff7809SAdrian Hunter return intel_pt_get_bep_ip(len, packet);
3942750af50SAdrian Hunter case 0x13: /* CFE */
3952750af50SAdrian Hunter return intel_pt_get_cfe(buf, len, packet);
3962750af50SAdrian Hunter case 0x53: /* EVD */
3972750af50SAdrian Hunter return intel_pt_get_evd(buf, len, packet);
398a4e92590SAdrian Hunter default:
399a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
400a4e92590SAdrian Hunter }
401a4e92590SAdrian Hunter }
402a4e92590SAdrian Hunter
intel_pt_get_short_tnt(unsigned int byte,struct intel_pt_pkt * packet)403a4e92590SAdrian Hunter static int intel_pt_get_short_tnt(unsigned int byte,
404a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
405a4e92590SAdrian Hunter {
406a4e92590SAdrian Hunter int count;
407a4e92590SAdrian Hunter
408a4e92590SAdrian Hunter for (count = 6; count; count--) {
409a4e92590SAdrian Hunter if (byte & BIT(7))
410a4e92590SAdrian Hunter break;
411a4e92590SAdrian Hunter byte <<= 1;
412a4e92590SAdrian Hunter }
413a4e92590SAdrian Hunter
414a4e92590SAdrian Hunter packet->type = INTEL_PT_TNT;
415a4e92590SAdrian Hunter packet->count = count;
416a4e92590SAdrian Hunter packet->payload = (uint64_t)byte << 57;
417a4e92590SAdrian Hunter
418a4e92590SAdrian Hunter return 1;
419a4e92590SAdrian Hunter }
420a4e92590SAdrian Hunter
intel_pt_get_cyc(unsigned int byte,const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)4213d498078SAdrian Hunter static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf,
4223d498078SAdrian Hunter size_t len, struct intel_pt_pkt *packet)
4233d498078SAdrian Hunter {
4243d498078SAdrian Hunter unsigned int offs = 1, shift;
4253d498078SAdrian Hunter uint64_t payload = byte >> 3;
4263d498078SAdrian Hunter
4273d498078SAdrian Hunter byte >>= 2;
4283d498078SAdrian Hunter len -= 1;
4293d498078SAdrian Hunter for (shift = 5; byte & 1; shift += 7) {
4303d498078SAdrian Hunter if (offs > 9)
4313d498078SAdrian Hunter return INTEL_PT_BAD_PACKET;
4323d498078SAdrian Hunter if (len < offs)
4333d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
4343d498078SAdrian Hunter byte = buf[offs++];
435621a5a32SAdrian Hunter payload |= ((uint64_t)byte >> 1) << shift;
4363d498078SAdrian Hunter }
4373d498078SAdrian Hunter
4383d498078SAdrian Hunter packet->type = INTEL_PT_CYC;
4393d498078SAdrian Hunter packet->payload = payload;
4403d498078SAdrian Hunter return offs;
4413d498078SAdrian Hunter }
4423d498078SAdrian Hunter
intel_pt_get_ip(enum intel_pt_pkt_type type,unsigned int byte,const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)443a4e92590SAdrian Hunter static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
444a4e92590SAdrian Hunter const unsigned char *buf, size_t len,
445a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
446a4e92590SAdrian Hunter {
447e1717e04SAdrian Hunter int ip_len;
448e1717e04SAdrian Hunter
449e1717e04SAdrian Hunter packet->count = byte >> 5;
450e1717e04SAdrian Hunter
451e1717e04SAdrian Hunter switch (packet->count) {
452a4e92590SAdrian Hunter case 0:
453e1717e04SAdrian Hunter ip_len = 0;
454a4e92590SAdrian Hunter break;
455a4e92590SAdrian Hunter case 1:
456a4e92590SAdrian Hunter if (len < 3)
457a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
458e1717e04SAdrian Hunter ip_len = 2;
4593b4fa67fSAdrian Hunter packet->payload = get_unaligned_le16(buf + 1);
460a4e92590SAdrian Hunter break;
461a4e92590SAdrian Hunter case 2:
462a4e92590SAdrian Hunter if (len < 5)
463a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
464e1717e04SAdrian Hunter ip_len = 4;
4653b4fa67fSAdrian Hunter packet->payload = get_unaligned_le32(buf + 1);
466a4e92590SAdrian Hunter break;
467a4e92590SAdrian Hunter case 3:
468e1717e04SAdrian Hunter case 4:
469a4e92590SAdrian Hunter if (len < 7)
470a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
471e1717e04SAdrian Hunter ip_len = 6;
472a4e92590SAdrian Hunter memcpy_le64(&packet->payload, buf + 1, 6);
473a4e92590SAdrian Hunter break;
474e1717e04SAdrian Hunter case 6:
475e1717e04SAdrian Hunter if (len < 9)
476e1717e04SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
477e1717e04SAdrian Hunter ip_len = 8;
4783b4fa67fSAdrian Hunter packet->payload = get_unaligned_le64(buf + 1);
479e1717e04SAdrian Hunter break;
480a4e92590SAdrian Hunter default:
481a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
482a4e92590SAdrian Hunter }
483a4e92590SAdrian Hunter
484a4e92590SAdrian Hunter packet->type = type;
485a4e92590SAdrian Hunter
486e1717e04SAdrian Hunter return ip_len + 1;
487a4e92590SAdrian Hunter }
488a4e92590SAdrian Hunter
intel_pt_get_mode(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)489a4e92590SAdrian Hunter static int intel_pt_get_mode(const unsigned char *buf, size_t len,
490a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
491a4e92590SAdrian Hunter {
492a4e92590SAdrian Hunter if (len < 2)
493a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
494a4e92590SAdrian Hunter
495a4e92590SAdrian Hunter switch (buf[1] >> 5) {
496a4e92590SAdrian Hunter case 0:
497a4e92590SAdrian Hunter packet->type = INTEL_PT_MODE_EXEC;
498f7934477SAdrian Hunter packet->count = buf[1];
499a4e92590SAdrian Hunter switch (buf[1] & 3) {
500a4e92590SAdrian Hunter case 0:
501a4e92590SAdrian Hunter packet->payload = 16;
502a4e92590SAdrian Hunter break;
503a4e92590SAdrian Hunter case 1:
504a4e92590SAdrian Hunter packet->payload = 64;
505a4e92590SAdrian Hunter break;
506a4e92590SAdrian Hunter case 2:
507a4e92590SAdrian Hunter packet->payload = 32;
508a4e92590SAdrian Hunter break;
509a4e92590SAdrian Hunter default:
510a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
511a4e92590SAdrian Hunter }
512a4e92590SAdrian Hunter break;
513a4e92590SAdrian Hunter case 1:
514a4e92590SAdrian Hunter packet->type = INTEL_PT_MODE_TSX;
515a4e92590SAdrian Hunter if ((buf[1] & 3) == 3)
516a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
517a4e92590SAdrian Hunter packet->payload = buf[1] & 3;
518a4e92590SAdrian Hunter break;
519a4e92590SAdrian Hunter default:
520a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
521a4e92590SAdrian Hunter }
522a4e92590SAdrian Hunter
523a4e92590SAdrian Hunter return 2;
524a4e92590SAdrian Hunter }
525a4e92590SAdrian Hunter
intel_pt_get_tsc(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)526a4e92590SAdrian Hunter static int intel_pt_get_tsc(const unsigned char *buf, size_t len,
527a4e92590SAdrian Hunter struct intel_pt_pkt *packet)
528a4e92590SAdrian Hunter {
529a4e92590SAdrian Hunter if (len < 8)
530a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
531a4e92590SAdrian Hunter packet->type = INTEL_PT_TSC;
532a4e92590SAdrian Hunter memcpy_le64(&packet->payload, buf + 1, 7);
533a4e92590SAdrian Hunter return 8;
534a4e92590SAdrian Hunter }
535a4e92590SAdrian Hunter
intel_pt_get_mtc(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet)5363d498078SAdrian Hunter static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
5373d498078SAdrian Hunter struct intel_pt_pkt *packet)
5383d498078SAdrian Hunter {
5393d498078SAdrian Hunter if (len < 2)
5403d498078SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
5413d498078SAdrian Hunter packet->type = INTEL_PT_MTC;
5423d498078SAdrian Hunter packet->payload = buf[1];
5433d498078SAdrian Hunter return 2;
5443d498078SAdrian Hunter }
5453d498078SAdrian Hunter
intel_pt_do_get_packet(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet,enum intel_pt_pkt_ctx ctx)546a4e92590SAdrian Hunter static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
547edff7809SAdrian Hunter struct intel_pt_pkt *packet,
548edff7809SAdrian Hunter enum intel_pt_pkt_ctx ctx)
549a4e92590SAdrian Hunter {
550a4e92590SAdrian Hunter unsigned int byte;
551a4e92590SAdrian Hunter
552a4e92590SAdrian Hunter memset(packet, 0, sizeof(struct intel_pt_pkt));
553a4e92590SAdrian Hunter
554a4e92590SAdrian Hunter if (!len)
555a4e92590SAdrian Hunter return INTEL_PT_NEED_MORE_BYTES;
556a4e92590SAdrian Hunter
557a4e92590SAdrian Hunter byte = buf[0];
558edff7809SAdrian Hunter
559edff7809SAdrian Hunter switch (ctx) {
560edff7809SAdrian Hunter case INTEL_PT_NO_CTX:
561edff7809SAdrian Hunter break;
562edff7809SAdrian Hunter case INTEL_PT_BLK_4_CTX:
563edff7809SAdrian Hunter if ((byte & 0x7) == 4)
564edff7809SAdrian Hunter return intel_pt_get_bip_4(buf, len, packet);
565edff7809SAdrian Hunter break;
566edff7809SAdrian Hunter case INTEL_PT_BLK_8_CTX:
567edff7809SAdrian Hunter if ((byte & 0x7) == 4)
568edff7809SAdrian Hunter return intel_pt_get_bip_8(buf, len, packet);
569edff7809SAdrian Hunter break;
570edff7809SAdrian Hunter default:
571edff7809SAdrian Hunter break;
5728284bbeaSZou Wei }
573edff7809SAdrian Hunter
574a4e92590SAdrian Hunter if (!(byte & BIT(0))) {
575a4e92590SAdrian Hunter if (byte == 0)
576a4e92590SAdrian Hunter return intel_pt_get_pad(packet);
577a4e92590SAdrian Hunter if (byte == 2)
578a4e92590SAdrian Hunter return intel_pt_get_ext(buf, len, packet);
579a4e92590SAdrian Hunter return intel_pt_get_short_tnt(byte, packet);
580a4e92590SAdrian Hunter }
581a4e92590SAdrian Hunter
5823d498078SAdrian Hunter if ((byte & 2))
5833d498078SAdrian Hunter return intel_pt_get_cyc(byte, buf, len, packet);
5843d498078SAdrian Hunter
585a4e92590SAdrian Hunter switch (byte & 0x1f) {
586a4e92590SAdrian Hunter case 0x0D:
587a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
588a4e92590SAdrian Hunter case 0x11:
589a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
590a4e92590SAdrian Hunter packet);
591a4e92590SAdrian Hunter case 0x01:
592a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
593a4e92590SAdrian Hunter packet);
594a4e92590SAdrian Hunter case 0x1D:
595a4e92590SAdrian Hunter return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
596a4e92590SAdrian Hunter case 0x19:
597a4e92590SAdrian Hunter switch (byte) {
598a4e92590SAdrian Hunter case 0x99:
599a4e92590SAdrian Hunter return intel_pt_get_mode(buf, len, packet);
600a4e92590SAdrian Hunter case 0x19:
601a4e92590SAdrian Hunter return intel_pt_get_tsc(buf, len, packet);
6023d498078SAdrian Hunter case 0x59:
6033d498078SAdrian Hunter return intel_pt_get_mtc(buf, len, packet);
604a4e92590SAdrian Hunter default:
605a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
606a4e92590SAdrian Hunter }
607a4e92590SAdrian Hunter default:
608a4e92590SAdrian Hunter return INTEL_PT_BAD_PACKET;
609a4e92590SAdrian Hunter }
610a4e92590SAdrian Hunter }
611a4e92590SAdrian Hunter
intel_pt_upd_pkt_ctx(const struct intel_pt_pkt * packet,enum intel_pt_pkt_ctx * ctx)612edff7809SAdrian Hunter void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
613edff7809SAdrian Hunter enum intel_pt_pkt_ctx *ctx)
614edff7809SAdrian Hunter {
615edff7809SAdrian Hunter switch (packet->type) {
616edff7809SAdrian Hunter case INTEL_PT_BAD:
617edff7809SAdrian Hunter case INTEL_PT_PAD:
618edff7809SAdrian Hunter case INTEL_PT_TSC:
619edff7809SAdrian Hunter case INTEL_PT_TMA:
620edff7809SAdrian Hunter case INTEL_PT_MTC:
621edff7809SAdrian Hunter case INTEL_PT_FUP:
622edff7809SAdrian Hunter case INTEL_PT_CYC:
623edff7809SAdrian Hunter case INTEL_PT_CBR:
624edff7809SAdrian Hunter case INTEL_PT_MNT:
625edff7809SAdrian Hunter case INTEL_PT_EXSTOP:
626edff7809SAdrian Hunter case INTEL_PT_EXSTOP_IP:
627edff7809SAdrian Hunter case INTEL_PT_PWRE:
628edff7809SAdrian Hunter case INTEL_PT_PWRX:
629edff7809SAdrian Hunter case INTEL_PT_BIP:
630edff7809SAdrian Hunter break;
631edff7809SAdrian Hunter case INTEL_PT_TNT:
632edff7809SAdrian Hunter case INTEL_PT_TIP:
633edff7809SAdrian Hunter case INTEL_PT_TIP_PGD:
634edff7809SAdrian Hunter case INTEL_PT_TIP_PGE:
635edff7809SAdrian Hunter case INTEL_PT_MODE_EXEC:
636edff7809SAdrian Hunter case INTEL_PT_MODE_TSX:
637edff7809SAdrian Hunter case INTEL_PT_PIP:
638edff7809SAdrian Hunter case INTEL_PT_OVF:
639edff7809SAdrian Hunter case INTEL_PT_VMCS:
640edff7809SAdrian Hunter case INTEL_PT_TRACESTOP:
641edff7809SAdrian Hunter case INTEL_PT_PSB:
642edff7809SAdrian Hunter case INTEL_PT_PSBEND:
643edff7809SAdrian Hunter case INTEL_PT_PTWRITE:
644edff7809SAdrian Hunter case INTEL_PT_PTWRITE_IP:
645edff7809SAdrian Hunter case INTEL_PT_MWAIT:
646edff7809SAdrian Hunter case INTEL_PT_BEP:
647edff7809SAdrian Hunter case INTEL_PT_BEP_IP:
6482750af50SAdrian Hunter case INTEL_PT_CFE:
6492750af50SAdrian Hunter case INTEL_PT_CFE_IP:
6502750af50SAdrian Hunter case INTEL_PT_EVD:
651edff7809SAdrian Hunter *ctx = INTEL_PT_NO_CTX;
652edff7809SAdrian Hunter break;
653edff7809SAdrian Hunter case INTEL_PT_BBP:
654edff7809SAdrian Hunter if (packet->count)
655edff7809SAdrian Hunter *ctx = INTEL_PT_BLK_4_CTX;
656edff7809SAdrian Hunter else
657edff7809SAdrian Hunter *ctx = INTEL_PT_BLK_8_CTX;
658edff7809SAdrian Hunter break;
659edff7809SAdrian Hunter default:
660edff7809SAdrian Hunter break;
661edff7809SAdrian Hunter }
662edff7809SAdrian Hunter }
663edff7809SAdrian Hunter
intel_pt_get_packet(const unsigned char * buf,size_t len,struct intel_pt_pkt * packet,enum intel_pt_pkt_ctx * ctx)664a4e92590SAdrian Hunter int intel_pt_get_packet(const unsigned char *buf, size_t len,
665edff7809SAdrian Hunter struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
666a4e92590SAdrian Hunter {
667a4e92590SAdrian Hunter int ret;
668a4e92590SAdrian Hunter
669edff7809SAdrian Hunter ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
670a4e92590SAdrian Hunter if (ret > 0) {
671a4e92590SAdrian Hunter while (ret < 8 && len > (size_t)ret && !buf[ret])
672a4e92590SAdrian Hunter ret += 1;
673edff7809SAdrian Hunter intel_pt_upd_pkt_ctx(packet, ctx);
674a4e92590SAdrian Hunter }
675a4e92590SAdrian Hunter return ret;
676a4e92590SAdrian Hunter }
677a4e92590SAdrian Hunter
intel_pt_pkt_desc(const struct intel_pt_pkt * packet,char * buf,size_t buf_len)678a4e92590SAdrian Hunter int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
679a4e92590SAdrian Hunter size_t buf_len)
680a4e92590SAdrian Hunter {
6813d498078SAdrian Hunter int ret, i, nr;
682a4e92590SAdrian Hunter unsigned long long payload = packet->payload;
683a4e92590SAdrian Hunter const char *name = intel_pt_pkt_name(packet->type);
684a4e92590SAdrian Hunter
685a4e92590SAdrian Hunter switch (packet->type) {
686a4e92590SAdrian Hunter case INTEL_PT_BAD:
687a4e92590SAdrian Hunter case INTEL_PT_PAD:
688a4e92590SAdrian Hunter case INTEL_PT_PSB:
689a4e92590SAdrian Hunter case INTEL_PT_PSBEND:
6903d498078SAdrian Hunter case INTEL_PT_TRACESTOP:
691a4e92590SAdrian Hunter case INTEL_PT_OVF:
692a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s", name);
693a4e92590SAdrian Hunter case INTEL_PT_TNT: {
694a4e92590SAdrian Hunter size_t blen = buf_len;
695a4e92590SAdrian Hunter
696a4e92590SAdrian Hunter ret = snprintf(buf, blen, "%s ", name);
697a4e92590SAdrian Hunter if (ret < 0)
698a4e92590SAdrian Hunter return ret;
699a4e92590SAdrian Hunter buf += ret;
700a4e92590SAdrian Hunter blen -= ret;
701a4e92590SAdrian Hunter for (i = 0; i < packet->count; i++) {
702a4e92590SAdrian Hunter if (payload & BIT63)
703a4e92590SAdrian Hunter ret = snprintf(buf, blen, "T");
704a4e92590SAdrian Hunter else
705a4e92590SAdrian Hunter ret = snprintf(buf, blen, "N");
706a4e92590SAdrian Hunter if (ret < 0)
707a4e92590SAdrian Hunter return ret;
708a4e92590SAdrian Hunter buf += ret;
709a4e92590SAdrian Hunter blen -= ret;
710a4e92590SAdrian Hunter payload <<= 1;
711a4e92590SAdrian Hunter }
712a4e92590SAdrian Hunter ret = snprintf(buf, blen, " (%d)", packet->count);
713a4e92590SAdrian Hunter if (ret < 0)
714a4e92590SAdrian Hunter return ret;
715a4e92590SAdrian Hunter blen -= ret;
716a4e92590SAdrian Hunter return buf_len - blen;
717a4e92590SAdrian Hunter }
718a4e92590SAdrian Hunter case INTEL_PT_TIP_PGD:
719a4e92590SAdrian Hunter case INTEL_PT_TIP_PGE:
720a4e92590SAdrian Hunter case INTEL_PT_TIP:
721a4e92590SAdrian Hunter case INTEL_PT_FUP:
722a4e92590SAdrian Hunter if (!(packet->count))
723a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s no ip", name);
724f7a858bfSLiam Howlett fallthrough;
7253d498078SAdrian Hunter case INTEL_PT_CYC:
7263d498078SAdrian Hunter case INTEL_PT_VMCS:
7273d498078SAdrian Hunter case INTEL_PT_MTC:
7283d498078SAdrian Hunter case INTEL_PT_MNT:
729a4e92590SAdrian Hunter case INTEL_PT_CBR:
730a4e92590SAdrian Hunter case INTEL_PT_TSC:
7313d498078SAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
7323d498078SAdrian Hunter case INTEL_PT_TMA:
7333d498078SAdrian Hunter return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name,
7343d498078SAdrian Hunter (unsigned)payload, packet->count);
735a4e92590SAdrian Hunter case INTEL_PT_MODE_EXEC:
736f7934477SAdrian Hunter return snprintf(buf, buf_len, "%s IF:%d %lld",
737f7934477SAdrian Hunter name, !!(packet->count & 4), payload);
738a4e92590SAdrian Hunter case INTEL_PT_MODE_TSX:
739a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
740a4e92590SAdrian Hunter name, (unsigned)(payload >> 1) & 1,
741a4e92590SAdrian Hunter (unsigned)payload & 1);
742a4e92590SAdrian Hunter case INTEL_PT_PIP:
74390af7555SAdrian Hunter nr = packet->payload & INTEL_PT_VMX_NR_FLAG ? 1 : 0;
74490af7555SAdrian Hunter payload &= ~INTEL_PT_VMX_NR_FLAG;
7453d498078SAdrian Hunter ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
74690af7555SAdrian Hunter name, payload >> 1, nr);
747a4e92590SAdrian Hunter return ret;
748a472e65fSAdrian Hunter case INTEL_PT_PTWRITE:
749a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
750a472e65fSAdrian Hunter case INTEL_PT_PTWRITE_IP:
751a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
752edff7809SAdrian Hunter case INTEL_PT_BEP:
753a472e65fSAdrian Hunter case INTEL_PT_EXSTOP:
754a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s IP:0", name);
755edff7809SAdrian Hunter case INTEL_PT_BEP_IP:
756a472e65fSAdrian Hunter case INTEL_PT_EXSTOP_IP:
757a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s IP:1", name);
758a472e65fSAdrian Hunter case INTEL_PT_MWAIT:
759a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx Hints 0x%x Extensions 0x%x",
760a472e65fSAdrian Hunter name, payload, (unsigned int)(payload & 0xff),
761a472e65fSAdrian Hunter (unsigned int)((payload >> 32) & 0x3));
762a472e65fSAdrian Hunter case INTEL_PT_PWRE:
763a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx HW:%u CState:%u Sub-CState:%u",
764a472e65fSAdrian Hunter name, payload, !!(payload & 0x80),
765a472e65fSAdrian Hunter (unsigned int)((payload >> 12) & 0xf),
766a472e65fSAdrian Hunter (unsigned int)((payload >> 8) & 0xf));
767a472e65fSAdrian Hunter case INTEL_PT_PWRX:
768a472e65fSAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx Last CState:%u Deepest CState:%u Wake Reason 0x%x",
769a472e65fSAdrian Hunter name, payload,
770a472e65fSAdrian Hunter (unsigned int)((payload >> 4) & 0xf),
771a472e65fSAdrian Hunter (unsigned int)(payload & 0xf),
772a472e65fSAdrian Hunter (unsigned int)((payload >> 8) & 0xf));
773edff7809SAdrian Hunter case INTEL_PT_BBP:
774edff7809SAdrian Hunter return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
775edff7809SAdrian Hunter name, packet->count ? "4" : "8", payload);
776edff7809SAdrian Hunter case INTEL_PT_BIP:
777edff7809SAdrian Hunter return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
778edff7809SAdrian Hunter name, packet->count, payload);
7792750af50SAdrian Hunter case INTEL_PT_CFE:
7802750af50SAdrian Hunter case INTEL_PT_CFE_IP:
7812750af50SAdrian Hunter return snprintf(buf, buf_len, "%s IP:%d Type 0x%02x Vector 0x%llx",
7822750af50SAdrian Hunter name, packet->type == INTEL_PT_CFE_IP, packet->count, payload);
7832750af50SAdrian Hunter case INTEL_PT_EVD:
7842750af50SAdrian Hunter return snprintf(buf, buf_len, "%s Type 0x%02x Payload 0x%llx",
7852750af50SAdrian Hunter name, packet->count, payload);
786a4e92590SAdrian Hunter default:
787a4e92590SAdrian Hunter break;
788a4e92590SAdrian Hunter }
789a4e92590SAdrian Hunter return snprintf(buf, buf_len, "%s 0x%llx (%d)",
790a4e92590SAdrian Hunter name, payload, packet->count);
791a4e92590SAdrian Hunter }
792