162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * intel_pt_pkt_decoder.c: Intel Processor Trace support
462306a36Sopenharmony_ci * Copyright (c) 2013-2014, Intel Corporation.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <stdio.h>
862306a36Sopenharmony_ci#include <string.h>
962306a36Sopenharmony_ci#include <endian.h>
1062306a36Sopenharmony_ci#include <byteswap.h>
1162306a36Sopenharmony_ci#include <linux/compiler.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "intel-pt-pkt-decoder.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define BIT(n)		(1 << (n))
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define BIT63		((uint64_t)1 << 63)
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
2062306a36Sopenharmony_ci#define le16_to_cpu bswap_16
2162306a36Sopenharmony_ci#define le32_to_cpu bswap_32
2262306a36Sopenharmony_ci#define le64_to_cpu bswap_64
2362306a36Sopenharmony_ci#define memcpy_le64(d, s, n) do { \
2462306a36Sopenharmony_ci	memcpy((d), (s), (n));    \
2562306a36Sopenharmony_ci	*(d) = le64_to_cpu(*(d)); \
2662306a36Sopenharmony_ci} while (0)
2762306a36Sopenharmony_ci#else
2862306a36Sopenharmony_ci#define le16_to_cpu
2962306a36Sopenharmony_ci#define le32_to_cpu
3062306a36Sopenharmony_ci#define le64_to_cpu
3162306a36Sopenharmony_ci#define memcpy_le64 memcpy
3262306a36Sopenharmony_ci#endif
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic const char * const packet_name[] = {
3562306a36Sopenharmony_ci	[INTEL_PT_BAD]		= "Bad Packet!",
3662306a36Sopenharmony_ci	[INTEL_PT_PAD]		= "PAD",
3762306a36Sopenharmony_ci	[INTEL_PT_TNT]		= "TNT",
3862306a36Sopenharmony_ci	[INTEL_PT_TIP_PGD]	= "TIP.PGD",
3962306a36Sopenharmony_ci	[INTEL_PT_TIP_PGE]	= "TIP.PGE",
4062306a36Sopenharmony_ci	[INTEL_PT_TSC]		= "TSC",
4162306a36Sopenharmony_ci	[INTEL_PT_TMA]		= "TMA",
4262306a36Sopenharmony_ci	[INTEL_PT_MODE_EXEC]	= "MODE.Exec",
4362306a36Sopenharmony_ci	[INTEL_PT_MODE_TSX]	= "MODE.TSX",
4462306a36Sopenharmony_ci	[INTEL_PT_MTC]		= "MTC",
4562306a36Sopenharmony_ci	[INTEL_PT_TIP]		= "TIP",
4662306a36Sopenharmony_ci	[INTEL_PT_FUP]		= "FUP",
4762306a36Sopenharmony_ci	[INTEL_PT_CYC]		= "CYC",
4862306a36Sopenharmony_ci	[INTEL_PT_VMCS]		= "VMCS",
4962306a36Sopenharmony_ci	[INTEL_PT_PSB]		= "PSB",
5062306a36Sopenharmony_ci	[INTEL_PT_PSBEND]	= "PSBEND",
5162306a36Sopenharmony_ci	[INTEL_PT_CBR]		= "CBR",
5262306a36Sopenharmony_ci	[INTEL_PT_TRACESTOP]	= "TraceSTOP",
5362306a36Sopenharmony_ci	[INTEL_PT_PIP]		= "PIP",
5462306a36Sopenharmony_ci	[INTEL_PT_OVF]		= "OVF",
5562306a36Sopenharmony_ci	[INTEL_PT_MNT]		= "MNT",
5662306a36Sopenharmony_ci	[INTEL_PT_PTWRITE]	= "PTWRITE",
5762306a36Sopenharmony_ci	[INTEL_PT_PTWRITE_IP]	= "PTWRITE",
5862306a36Sopenharmony_ci	[INTEL_PT_EXSTOP]	= "EXSTOP",
5962306a36Sopenharmony_ci	[INTEL_PT_EXSTOP_IP]	= "EXSTOP",
6062306a36Sopenharmony_ci	[INTEL_PT_MWAIT]	= "MWAIT",
6162306a36Sopenharmony_ci	[INTEL_PT_PWRE]		= "PWRE",
6262306a36Sopenharmony_ci	[INTEL_PT_PWRX]		= "PWRX",
6362306a36Sopenharmony_ci	[INTEL_PT_BBP]		= "BBP",
6462306a36Sopenharmony_ci	[INTEL_PT_BIP]		= "BIP",
6562306a36Sopenharmony_ci	[INTEL_PT_BEP]		= "BEP",
6662306a36Sopenharmony_ci	[INTEL_PT_BEP_IP]	= "BEP",
6762306a36Sopenharmony_ci	[INTEL_PT_CFE]		= "CFE",
6862306a36Sopenharmony_ci	[INTEL_PT_CFE_IP]	= "CFE",
6962306a36Sopenharmony_ci	[INTEL_PT_EVD]		= "EVD",
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ciconst char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	return packet_name[type];
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic int intel_pt_get_long_tnt(const unsigned char *buf, size_t len,
7862306a36Sopenharmony_ci				 struct intel_pt_pkt *packet)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	uint64_t payload;
8162306a36Sopenharmony_ci	int count;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	if (len < 8)
8462306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	payload = le64_to_cpu(*(uint64_t *)buf);
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	for (count = 47; count; count--) {
8962306a36Sopenharmony_ci		if (payload & BIT63)
9062306a36Sopenharmony_ci			break;
9162306a36Sopenharmony_ci		payload <<= 1;
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	packet->type = INTEL_PT_TNT;
9562306a36Sopenharmony_ci	packet->count = count;
9662306a36Sopenharmony_ci	packet->payload = payload << 1;
9762306a36Sopenharmony_ci	return 8;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic int intel_pt_get_pip(const unsigned char *buf, size_t len,
10162306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	uint64_t payload = 0;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	if (len < 8)
10662306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	packet->type = INTEL_PT_PIP;
10962306a36Sopenharmony_ci	memcpy_le64(&payload, buf + 2, 6);
11062306a36Sopenharmony_ci	packet->payload = payload;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return 8;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int intel_pt_get_tracestop(struct intel_pt_pkt *packet)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	packet->type = INTEL_PT_TRACESTOP;
11862306a36Sopenharmony_ci	return 2;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic int intel_pt_get_cbr(const unsigned char *buf, size_t len,
12262306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	if (len < 4)
12562306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
12662306a36Sopenharmony_ci	packet->type = INTEL_PT_CBR;
12762306a36Sopenharmony_ci	packet->payload = le16_to_cpu(*(uint16_t *)(buf + 2));
12862306a36Sopenharmony_ci	return 4;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic int intel_pt_get_vmcs(const unsigned char *buf, size_t len,
13262306a36Sopenharmony_ci			     struct intel_pt_pkt *packet)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	unsigned int count = (52 - 5) >> 3;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	if (count < 1 || count > 7)
13762306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	if (len < count + 2)
14062306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	packet->type = INTEL_PT_VMCS;
14362306a36Sopenharmony_ci	packet->count = count;
14462306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 2, count);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return count + 2;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic int intel_pt_get_ovf(struct intel_pt_pkt *packet)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	packet->type = INTEL_PT_OVF;
15262306a36Sopenharmony_ci	return 2;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic int intel_pt_get_psb(const unsigned char *buf, size_t len,
15662306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	int i;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	if (len < 16)
16162306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	for (i = 2; i < 16; i += 2) {
16462306a36Sopenharmony_ci		if (buf[i] != 2 || buf[i + 1] != 0x82)
16562306a36Sopenharmony_ci			return INTEL_PT_BAD_PACKET;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	packet->type = INTEL_PT_PSB;
16962306a36Sopenharmony_ci	return 16;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic int intel_pt_get_psbend(struct intel_pt_pkt *packet)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	packet->type = INTEL_PT_PSBEND;
17562306a36Sopenharmony_ci	return 2;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic int intel_pt_get_tma(const unsigned char *buf, size_t len,
17962306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	if (len < 7)
18262306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	packet->type = INTEL_PT_TMA;
18562306a36Sopenharmony_ci	packet->payload = buf[2] | (buf[3] << 8);
18662306a36Sopenharmony_ci	packet->count = buf[5] | ((buf[6] & BIT(0)) << 8);
18762306a36Sopenharmony_ci	return 7;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int intel_pt_get_pad(struct intel_pt_pkt *packet)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	packet->type = INTEL_PT_PAD;
19362306a36Sopenharmony_ci	return 1;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic int intel_pt_get_mnt(const unsigned char *buf, size_t len,
19762306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	if (len < 11)
20062306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
20162306a36Sopenharmony_ci	packet->type = INTEL_PT_MNT;
20262306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 3, 8);
20362306a36Sopenharmony_ci	return 11;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic int intel_pt_get_3byte(const unsigned char *buf, size_t len,
20762306a36Sopenharmony_ci			      struct intel_pt_pkt *packet)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	if (len < 3)
21062306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	switch (buf[2]) {
21362306a36Sopenharmony_ci	case 0x88: /* MNT */
21462306a36Sopenharmony_ci		return intel_pt_get_mnt(buf, len, packet);
21562306a36Sopenharmony_ci	default:
21662306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic int intel_pt_get_ptwrite(const unsigned char *buf, size_t len,
22162306a36Sopenharmony_ci				struct intel_pt_pkt *packet)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	packet->count = (buf[1] >> 5) & 0x3;
22462306a36Sopenharmony_ci	packet->type = buf[1] & BIT(7) ? INTEL_PT_PTWRITE_IP :
22562306a36Sopenharmony_ci					 INTEL_PT_PTWRITE;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	switch (packet->count) {
22862306a36Sopenharmony_ci	case 0:
22962306a36Sopenharmony_ci		if (len < 6)
23062306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
23162306a36Sopenharmony_ci		packet->payload = le32_to_cpu(*(uint32_t *)(buf + 2));
23262306a36Sopenharmony_ci		return 6;
23362306a36Sopenharmony_ci	case 1:
23462306a36Sopenharmony_ci		if (len < 10)
23562306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
23662306a36Sopenharmony_ci		packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2));
23762306a36Sopenharmony_ci		return 10;
23862306a36Sopenharmony_ci	default:
23962306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic int intel_pt_get_exstop(struct intel_pt_pkt *packet)
24462306a36Sopenharmony_ci{
24562306a36Sopenharmony_ci	packet->type = INTEL_PT_EXSTOP;
24662306a36Sopenharmony_ci	return 2;
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic int intel_pt_get_exstop_ip(struct intel_pt_pkt *packet)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	packet->type = INTEL_PT_EXSTOP_IP;
25262306a36Sopenharmony_ci	return 2;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic int intel_pt_get_mwait(const unsigned char *buf, size_t len,
25662306a36Sopenharmony_ci			      struct intel_pt_pkt *packet)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	if (len < 10)
25962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
26062306a36Sopenharmony_ci	packet->type = INTEL_PT_MWAIT;
26162306a36Sopenharmony_ci	packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2));
26262306a36Sopenharmony_ci	return 10;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int intel_pt_get_pwre(const unsigned char *buf, size_t len,
26662306a36Sopenharmony_ci			     struct intel_pt_pkt *packet)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	if (len < 4)
26962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
27062306a36Sopenharmony_ci	packet->type = INTEL_PT_PWRE;
27162306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 2, 2);
27262306a36Sopenharmony_ci	return 4;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
27662306a36Sopenharmony_ci			     struct intel_pt_pkt *packet)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	if (len < 7)
27962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
28062306a36Sopenharmony_ci	packet->type = INTEL_PT_PWRX;
28162306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 2, 5);
28262306a36Sopenharmony_ci	return 7;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic int intel_pt_get_bbp(const unsigned char *buf, size_t len,
28662306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	if (len < 3)
28962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
29062306a36Sopenharmony_ci	packet->type = INTEL_PT_BBP;
29162306a36Sopenharmony_ci	packet->count = buf[2] >> 7;
29262306a36Sopenharmony_ci	packet->payload = buf[2] & 0x1f;
29362306a36Sopenharmony_ci	return 3;
29462306a36Sopenharmony_ci}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistatic int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
29762306a36Sopenharmony_ci			      struct intel_pt_pkt *packet)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	if (len < 5)
30062306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
30162306a36Sopenharmony_ci	packet->type = INTEL_PT_BIP;
30262306a36Sopenharmony_ci	packet->count = buf[0] >> 3;
30362306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 1, 4);
30462306a36Sopenharmony_ci	return 5;
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
30862306a36Sopenharmony_ci			      struct intel_pt_pkt *packet)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	if (len < 9)
31162306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
31262306a36Sopenharmony_ci	packet->type = INTEL_PT_BIP;
31362306a36Sopenharmony_ci	packet->count = buf[0] >> 3;
31462306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 1, 8);
31562306a36Sopenharmony_ci	return 9;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	if (len < 2)
32162306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
32262306a36Sopenharmony_ci	packet->type = INTEL_PT_BEP;
32362306a36Sopenharmony_ci	return 2;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	if (len < 2)
32962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
33062306a36Sopenharmony_ci	packet->type = INTEL_PT_BEP_IP;
33162306a36Sopenharmony_ci	return 2;
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic int intel_pt_get_cfe(const unsigned char *buf, size_t len,
33562306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	if (len < 4)
33862306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
33962306a36Sopenharmony_ci	packet->type = buf[2] & 0x80 ? INTEL_PT_CFE_IP : INTEL_PT_CFE;
34062306a36Sopenharmony_ci	packet->count = buf[2] & 0x1f;
34162306a36Sopenharmony_ci	packet->payload = buf[3];
34262306a36Sopenharmony_ci	return 4;
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic int intel_pt_get_evd(const unsigned char *buf, size_t len,
34662306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	if (len < 11)
34962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
35062306a36Sopenharmony_ci	packet->type = INTEL_PT_EVD;
35162306a36Sopenharmony_ci	packet->count = buf[2] & 0x3f;
35262306a36Sopenharmony_ci	packet->payload = buf[3];
35362306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 3, 8);
35462306a36Sopenharmony_ci	return 11;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic int intel_pt_get_ext(const unsigned char *buf, size_t len,
35862306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
35962306a36Sopenharmony_ci{
36062306a36Sopenharmony_ci	if (len < 2)
36162306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	if ((buf[1] & 0x1f) == 0x12)
36462306a36Sopenharmony_ci		return intel_pt_get_ptwrite(buf, len, packet);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	switch (buf[1]) {
36762306a36Sopenharmony_ci	case 0xa3: /* Long TNT */
36862306a36Sopenharmony_ci		return intel_pt_get_long_tnt(buf, len, packet);
36962306a36Sopenharmony_ci	case 0x43: /* PIP */
37062306a36Sopenharmony_ci		return intel_pt_get_pip(buf, len, packet);
37162306a36Sopenharmony_ci	case 0x83: /* TraceStop */
37262306a36Sopenharmony_ci		return intel_pt_get_tracestop(packet);
37362306a36Sopenharmony_ci	case 0x03: /* CBR */
37462306a36Sopenharmony_ci		return intel_pt_get_cbr(buf, len, packet);
37562306a36Sopenharmony_ci	case 0xc8: /* VMCS */
37662306a36Sopenharmony_ci		return intel_pt_get_vmcs(buf, len, packet);
37762306a36Sopenharmony_ci	case 0xf3: /* OVF */
37862306a36Sopenharmony_ci		return intel_pt_get_ovf(packet);
37962306a36Sopenharmony_ci	case 0x82: /* PSB */
38062306a36Sopenharmony_ci		return intel_pt_get_psb(buf, len, packet);
38162306a36Sopenharmony_ci	case 0x23: /* PSBEND */
38262306a36Sopenharmony_ci		return intel_pt_get_psbend(packet);
38362306a36Sopenharmony_ci	case 0x73: /* TMA */
38462306a36Sopenharmony_ci		return intel_pt_get_tma(buf, len, packet);
38562306a36Sopenharmony_ci	case 0xC3: /* 3-byte header */
38662306a36Sopenharmony_ci		return intel_pt_get_3byte(buf, len, packet);
38762306a36Sopenharmony_ci	case 0x62: /* EXSTOP no IP */
38862306a36Sopenharmony_ci		return intel_pt_get_exstop(packet);
38962306a36Sopenharmony_ci	case 0xE2: /* EXSTOP with IP */
39062306a36Sopenharmony_ci		return intel_pt_get_exstop_ip(packet);
39162306a36Sopenharmony_ci	case 0xC2: /* MWAIT */
39262306a36Sopenharmony_ci		return intel_pt_get_mwait(buf, len, packet);
39362306a36Sopenharmony_ci	case 0x22: /* PWRE */
39462306a36Sopenharmony_ci		return intel_pt_get_pwre(buf, len, packet);
39562306a36Sopenharmony_ci	case 0xA2: /* PWRX */
39662306a36Sopenharmony_ci		return intel_pt_get_pwrx(buf, len, packet);
39762306a36Sopenharmony_ci	case 0x63: /* BBP */
39862306a36Sopenharmony_ci		return intel_pt_get_bbp(buf, len, packet);
39962306a36Sopenharmony_ci	case 0x33: /* BEP no IP */
40062306a36Sopenharmony_ci		return intel_pt_get_bep(len, packet);
40162306a36Sopenharmony_ci	case 0xb3: /* BEP with IP */
40262306a36Sopenharmony_ci		return intel_pt_get_bep_ip(len, packet);
40362306a36Sopenharmony_ci	case 0x13: /* CFE */
40462306a36Sopenharmony_ci		return intel_pt_get_cfe(buf, len, packet);
40562306a36Sopenharmony_ci	case 0x53: /* EVD */
40662306a36Sopenharmony_ci		return intel_pt_get_evd(buf, len, packet);
40762306a36Sopenharmony_ci	default:
40862306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistatic int intel_pt_get_short_tnt(unsigned int byte,
41362306a36Sopenharmony_ci				  struct intel_pt_pkt *packet)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	int count;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	for (count = 6; count; count--) {
41862306a36Sopenharmony_ci		if (byte & BIT(7))
41962306a36Sopenharmony_ci			break;
42062306a36Sopenharmony_ci		byte <<= 1;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	packet->type = INTEL_PT_TNT;
42462306a36Sopenharmony_ci	packet->count = count;
42562306a36Sopenharmony_ci	packet->payload = (uint64_t)byte << 57;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	return 1;
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf,
43162306a36Sopenharmony_ci			    size_t len, struct intel_pt_pkt *packet)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	unsigned int offs = 1, shift;
43462306a36Sopenharmony_ci	uint64_t payload = byte >> 3;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	byte >>= 2;
43762306a36Sopenharmony_ci	len -= 1;
43862306a36Sopenharmony_ci	for (shift = 5; byte & 1; shift += 7) {
43962306a36Sopenharmony_ci		if (offs > 9)
44062306a36Sopenharmony_ci			return INTEL_PT_BAD_PACKET;
44162306a36Sopenharmony_ci		if (len < offs)
44262306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
44362306a36Sopenharmony_ci		byte = buf[offs++];
44462306a36Sopenharmony_ci		payload |= ((uint64_t)byte >> 1) << shift;
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	packet->type = INTEL_PT_CYC;
44862306a36Sopenharmony_ci	packet->payload = payload;
44962306a36Sopenharmony_ci	return offs;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
45362306a36Sopenharmony_ci			   const unsigned char *buf, size_t len,
45462306a36Sopenharmony_ci			   struct intel_pt_pkt *packet)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	int ip_len;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	packet->count = byte >> 5;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	switch (packet->count) {
46162306a36Sopenharmony_ci	case 0:
46262306a36Sopenharmony_ci		ip_len = 0;
46362306a36Sopenharmony_ci		break;
46462306a36Sopenharmony_ci	case 1:
46562306a36Sopenharmony_ci		if (len < 3)
46662306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
46762306a36Sopenharmony_ci		ip_len = 2;
46862306a36Sopenharmony_ci		packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
46962306a36Sopenharmony_ci		break;
47062306a36Sopenharmony_ci	case 2:
47162306a36Sopenharmony_ci		if (len < 5)
47262306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
47362306a36Sopenharmony_ci		ip_len = 4;
47462306a36Sopenharmony_ci		packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
47562306a36Sopenharmony_ci		break;
47662306a36Sopenharmony_ci	case 3:
47762306a36Sopenharmony_ci	case 4:
47862306a36Sopenharmony_ci		if (len < 7)
47962306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
48062306a36Sopenharmony_ci		ip_len = 6;
48162306a36Sopenharmony_ci		memcpy_le64(&packet->payload, buf + 1, 6);
48262306a36Sopenharmony_ci		break;
48362306a36Sopenharmony_ci	case 6:
48462306a36Sopenharmony_ci		if (len < 9)
48562306a36Sopenharmony_ci			return INTEL_PT_NEED_MORE_BYTES;
48662306a36Sopenharmony_ci		ip_len = 8;
48762306a36Sopenharmony_ci		packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
48862306a36Sopenharmony_ci		break;
48962306a36Sopenharmony_ci	default:
49062306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
49162306a36Sopenharmony_ci	}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	packet->type = type;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	return ip_len + 1;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic int intel_pt_get_mode(const unsigned char *buf, size_t len,
49962306a36Sopenharmony_ci			     struct intel_pt_pkt *packet)
50062306a36Sopenharmony_ci{
50162306a36Sopenharmony_ci	if (len < 2)
50262306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	switch (buf[1] >> 5) {
50562306a36Sopenharmony_ci	case 0:
50662306a36Sopenharmony_ci		packet->type = INTEL_PT_MODE_EXEC;
50762306a36Sopenharmony_ci		packet->count = buf[1];
50862306a36Sopenharmony_ci		switch (buf[1] & 3) {
50962306a36Sopenharmony_ci		case 0:
51062306a36Sopenharmony_ci			packet->payload = 16;
51162306a36Sopenharmony_ci			break;
51262306a36Sopenharmony_ci		case 1:
51362306a36Sopenharmony_ci			packet->payload = 64;
51462306a36Sopenharmony_ci			break;
51562306a36Sopenharmony_ci		case 2:
51662306a36Sopenharmony_ci			packet->payload = 32;
51762306a36Sopenharmony_ci			break;
51862306a36Sopenharmony_ci		default:
51962306a36Sopenharmony_ci			return INTEL_PT_BAD_PACKET;
52062306a36Sopenharmony_ci		}
52162306a36Sopenharmony_ci		break;
52262306a36Sopenharmony_ci	case 1:
52362306a36Sopenharmony_ci		packet->type = INTEL_PT_MODE_TSX;
52462306a36Sopenharmony_ci		if ((buf[1] & 3) == 3)
52562306a36Sopenharmony_ci			return INTEL_PT_BAD_PACKET;
52662306a36Sopenharmony_ci		packet->payload = buf[1] & 3;
52762306a36Sopenharmony_ci		break;
52862306a36Sopenharmony_ci	default:
52962306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	return 2;
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_cistatic int intel_pt_get_tsc(const unsigned char *buf, size_t len,
53662306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	if (len < 8)
53962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
54062306a36Sopenharmony_ci	packet->type = INTEL_PT_TSC;
54162306a36Sopenharmony_ci	memcpy_le64(&packet->payload, buf + 1, 7);
54262306a36Sopenharmony_ci	return 8;
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistatic int intel_pt_get_mtc(const unsigned char *buf, size_t len,
54662306a36Sopenharmony_ci			    struct intel_pt_pkt *packet)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	if (len < 2)
54962306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
55062306a36Sopenharmony_ci	packet->type = INTEL_PT_MTC;
55162306a36Sopenharmony_ci	packet->payload = buf[1];
55262306a36Sopenharmony_ci	return 2;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_cistatic int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
55662306a36Sopenharmony_ci				  struct intel_pt_pkt *packet,
55762306a36Sopenharmony_ci				  enum intel_pt_pkt_ctx ctx)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	unsigned int byte;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	memset(packet, 0, sizeof(struct intel_pt_pkt));
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	if (!len)
56462306a36Sopenharmony_ci		return INTEL_PT_NEED_MORE_BYTES;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	byte = buf[0];
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	switch (ctx) {
56962306a36Sopenharmony_ci	case INTEL_PT_NO_CTX:
57062306a36Sopenharmony_ci		break;
57162306a36Sopenharmony_ci	case INTEL_PT_BLK_4_CTX:
57262306a36Sopenharmony_ci		if ((byte & 0x7) == 4)
57362306a36Sopenharmony_ci			return intel_pt_get_bip_4(buf, len, packet);
57462306a36Sopenharmony_ci		break;
57562306a36Sopenharmony_ci	case INTEL_PT_BLK_8_CTX:
57662306a36Sopenharmony_ci		if ((byte & 0x7) == 4)
57762306a36Sopenharmony_ci			return intel_pt_get_bip_8(buf, len, packet);
57862306a36Sopenharmony_ci		break;
57962306a36Sopenharmony_ci	default:
58062306a36Sopenharmony_ci		break;
58162306a36Sopenharmony_ci	}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	if (!(byte & BIT(0))) {
58462306a36Sopenharmony_ci		if (byte == 0)
58562306a36Sopenharmony_ci			return intel_pt_get_pad(packet);
58662306a36Sopenharmony_ci		if (byte == 2)
58762306a36Sopenharmony_ci			return intel_pt_get_ext(buf, len, packet);
58862306a36Sopenharmony_ci		return intel_pt_get_short_tnt(byte, packet);
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if ((byte & 2))
59262306a36Sopenharmony_ci		return intel_pt_get_cyc(byte, buf, len, packet);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	switch (byte & 0x1f) {
59562306a36Sopenharmony_ci	case 0x0D:
59662306a36Sopenharmony_ci		return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
59762306a36Sopenharmony_ci	case 0x11:
59862306a36Sopenharmony_ci		return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
59962306a36Sopenharmony_ci				       packet);
60062306a36Sopenharmony_ci	case 0x01:
60162306a36Sopenharmony_ci		return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
60262306a36Sopenharmony_ci				       packet);
60362306a36Sopenharmony_ci	case 0x1D:
60462306a36Sopenharmony_ci		return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
60562306a36Sopenharmony_ci	case 0x19:
60662306a36Sopenharmony_ci		switch (byte) {
60762306a36Sopenharmony_ci		case 0x99:
60862306a36Sopenharmony_ci			return intel_pt_get_mode(buf, len, packet);
60962306a36Sopenharmony_ci		case 0x19:
61062306a36Sopenharmony_ci			return intel_pt_get_tsc(buf, len, packet);
61162306a36Sopenharmony_ci		case 0x59:
61262306a36Sopenharmony_ci			return intel_pt_get_mtc(buf, len, packet);
61362306a36Sopenharmony_ci		default:
61462306a36Sopenharmony_ci			return INTEL_PT_BAD_PACKET;
61562306a36Sopenharmony_ci		}
61662306a36Sopenharmony_ci	default:
61762306a36Sopenharmony_ci		return INTEL_PT_BAD_PACKET;
61862306a36Sopenharmony_ci	}
61962306a36Sopenharmony_ci}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_civoid intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
62262306a36Sopenharmony_ci			  enum intel_pt_pkt_ctx *ctx)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	switch (packet->type) {
62562306a36Sopenharmony_ci	case INTEL_PT_BAD:
62662306a36Sopenharmony_ci	case INTEL_PT_PAD:
62762306a36Sopenharmony_ci	case INTEL_PT_TSC:
62862306a36Sopenharmony_ci	case INTEL_PT_TMA:
62962306a36Sopenharmony_ci	case INTEL_PT_MTC:
63062306a36Sopenharmony_ci	case INTEL_PT_FUP:
63162306a36Sopenharmony_ci	case INTEL_PT_CYC:
63262306a36Sopenharmony_ci	case INTEL_PT_CBR:
63362306a36Sopenharmony_ci	case INTEL_PT_MNT:
63462306a36Sopenharmony_ci	case INTEL_PT_EXSTOP:
63562306a36Sopenharmony_ci	case INTEL_PT_EXSTOP_IP:
63662306a36Sopenharmony_ci	case INTEL_PT_PWRE:
63762306a36Sopenharmony_ci	case INTEL_PT_PWRX:
63862306a36Sopenharmony_ci	case INTEL_PT_BIP:
63962306a36Sopenharmony_ci		break;
64062306a36Sopenharmony_ci	case INTEL_PT_TNT:
64162306a36Sopenharmony_ci	case INTEL_PT_TIP:
64262306a36Sopenharmony_ci	case INTEL_PT_TIP_PGD:
64362306a36Sopenharmony_ci	case INTEL_PT_TIP_PGE:
64462306a36Sopenharmony_ci	case INTEL_PT_MODE_EXEC:
64562306a36Sopenharmony_ci	case INTEL_PT_MODE_TSX:
64662306a36Sopenharmony_ci	case INTEL_PT_PIP:
64762306a36Sopenharmony_ci	case INTEL_PT_OVF:
64862306a36Sopenharmony_ci	case INTEL_PT_VMCS:
64962306a36Sopenharmony_ci	case INTEL_PT_TRACESTOP:
65062306a36Sopenharmony_ci	case INTEL_PT_PSB:
65162306a36Sopenharmony_ci	case INTEL_PT_PSBEND:
65262306a36Sopenharmony_ci	case INTEL_PT_PTWRITE:
65362306a36Sopenharmony_ci	case INTEL_PT_PTWRITE_IP:
65462306a36Sopenharmony_ci	case INTEL_PT_MWAIT:
65562306a36Sopenharmony_ci	case INTEL_PT_BEP:
65662306a36Sopenharmony_ci	case INTEL_PT_BEP_IP:
65762306a36Sopenharmony_ci	case INTEL_PT_CFE:
65862306a36Sopenharmony_ci	case INTEL_PT_CFE_IP:
65962306a36Sopenharmony_ci	case INTEL_PT_EVD:
66062306a36Sopenharmony_ci		*ctx = INTEL_PT_NO_CTX;
66162306a36Sopenharmony_ci		break;
66262306a36Sopenharmony_ci	case INTEL_PT_BBP:
66362306a36Sopenharmony_ci		if (packet->count)
66462306a36Sopenharmony_ci			*ctx = INTEL_PT_BLK_4_CTX;
66562306a36Sopenharmony_ci		else
66662306a36Sopenharmony_ci			*ctx = INTEL_PT_BLK_8_CTX;
66762306a36Sopenharmony_ci		break;
66862306a36Sopenharmony_ci	default:
66962306a36Sopenharmony_ci		break;
67062306a36Sopenharmony_ci	}
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ciint intel_pt_get_packet(const unsigned char *buf, size_t len,
67462306a36Sopenharmony_ci			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
67562306a36Sopenharmony_ci{
67662306a36Sopenharmony_ci	int ret;
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
67962306a36Sopenharmony_ci	if (ret > 0) {
68062306a36Sopenharmony_ci		while (ret < 8 && len > (size_t)ret && !buf[ret])
68162306a36Sopenharmony_ci			ret += 1;
68262306a36Sopenharmony_ci		intel_pt_upd_pkt_ctx(packet, ctx);
68362306a36Sopenharmony_ci	}
68462306a36Sopenharmony_ci	return ret;
68562306a36Sopenharmony_ci}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ciint intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
68862306a36Sopenharmony_ci		      size_t buf_len)
68962306a36Sopenharmony_ci{
69062306a36Sopenharmony_ci	int ret, i, nr;
69162306a36Sopenharmony_ci	unsigned long long payload = packet->payload;
69262306a36Sopenharmony_ci	const char *name = intel_pt_pkt_name(packet->type);
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	switch (packet->type) {
69562306a36Sopenharmony_ci	case INTEL_PT_BAD:
69662306a36Sopenharmony_ci	case INTEL_PT_PAD:
69762306a36Sopenharmony_ci	case INTEL_PT_PSB:
69862306a36Sopenharmony_ci	case INTEL_PT_PSBEND:
69962306a36Sopenharmony_ci	case INTEL_PT_TRACESTOP:
70062306a36Sopenharmony_ci	case INTEL_PT_OVF:
70162306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s", name);
70262306a36Sopenharmony_ci	case INTEL_PT_TNT: {
70362306a36Sopenharmony_ci		size_t blen = buf_len;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci		ret = snprintf(buf, blen, "%s ", name);
70662306a36Sopenharmony_ci		if (ret < 0)
70762306a36Sopenharmony_ci			return ret;
70862306a36Sopenharmony_ci		buf += ret;
70962306a36Sopenharmony_ci		blen -= ret;
71062306a36Sopenharmony_ci		for (i = 0; i < packet->count; i++) {
71162306a36Sopenharmony_ci			if (payload & BIT63)
71262306a36Sopenharmony_ci				ret = snprintf(buf, blen, "T");
71362306a36Sopenharmony_ci			else
71462306a36Sopenharmony_ci				ret = snprintf(buf, blen, "N");
71562306a36Sopenharmony_ci			if (ret < 0)
71662306a36Sopenharmony_ci				return ret;
71762306a36Sopenharmony_ci			buf += ret;
71862306a36Sopenharmony_ci			blen -= ret;
71962306a36Sopenharmony_ci			payload <<= 1;
72062306a36Sopenharmony_ci		}
72162306a36Sopenharmony_ci		ret = snprintf(buf, blen, " (%d)", packet->count);
72262306a36Sopenharmony_ci		if (ret < 0)
72362306a36Sopenharmony_ci			return ret;
72462306a36Sopenharmony_ci		blen -= ret;
72562306a36Sopenharmony_ci		return buf_len - blen;
72662306a36Sopenharmony_ci	}
72762306a36Sopenharmony_ci	case INTEL_PT_TIP_PGD:
72862306a36Sopenharmony_ci	case INTEL_PT_TIP_PGE:
72962306a36Sopenharmony_ci	case INTEL_PT_TIP:
73062306a36Sopenharmony_ci	case INTEL_PT_FUP:
73162306a36Sopenharmony_ci		if (!(packet->count))
73262306a36Sopenharmony_ci			return snprintf(buf, buf_len, "%s no ip", name);
73362306a36Sopenharmony_ci		fallthrough;
73462306a36Sopenharmony_ci	case INTEL_PT_CYC:
73562306a36Sopenharmony_ci	case INTEL_PT_VMCS:
73662306a36Sopenharmony_ci	case INTEL_PT_MTC:
73762306a36Sopenharmony_ci	case INTEL_PT_MNT:
73862306a36Sopenharmony_ci	case INTEL_PT_CBR:
73962306a36Sopenharmony_ci	case INTEL_PT_TSC:
74062306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
74162306a36Sopenharmony_ci	case INTEL_PT_TMA:
74262306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name,
74362306a36Sopenharmony_ci				(unsigned)payload, packet->count);
74462306a36Sopenharmony_ci	case INTEL_PT_MODE_EXEC:
74562306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s IF:%d %lld",
74662306a36Sopenharmony_ci				name, !!(packet->count & 4), payload);
74762306a36Sopenharmony_ci	case INTEL_PT_MODE_TSX:
74862306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
74962306a36Sopenharmony_ci				name, (unsigned)(payload >> 1) & 1,
75062306a36Sopenharmony_ci				(unsigned)payload & 1);
75162306a36Sopenharmony_ci	case INTEL_PT_PIP:
75262306a36Sopenharmony_ci		nr = packet->payload & INTEL_PT_VMX_NR_FLAG ? 1 : 0;
75362306a36Sopenharmony_ci		payload &= ~INTEL_PT_VMX_NR_FLAG;
75462306a36Sopenharmony_ci		ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
75562306a36Sopenharmony_ci			       name, payload >> 1, nr);
75662306a36Sopenharmony_ci		return ret;
75762306a36Sopenharmony_ci	case INTEL_PT_PTWRITE:
75862306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
75962306a36Sopenharmony_ci	case INTEL_PT_PTWRITE_IP:
76062306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
76162306a36Sopenharmony_ci	case INTEL_PT_BEP:
76262306a36Sopenharmony_ci	case INTEL_PT_EXSTOP:
76362306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s IP:0", name);
76462306a36Sopenharmony_ci	case INTEL_PT_BEP_IP:
76562306a36Sopenharmony_ci	case INTEL_PT_EXSTOP_IP:
76662306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s IP:1", name);
76762306a36Sopenharmony_ci	case INTEL_PT_MWAIT:
76862306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx Hints 0x%x Extensions 0x%x",
76962306a36Sopenharmony_ci				name, payload, (unsigned int)(payload & 0xff),
77062306a36Sopenharmony_ci				(unsigned int)((payload >> 32) & 0x3));
77162306a36Sopenharmony_ci	case INTEL_PT_PWRE:
77262306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx HW:%u CState:%u Sub-CState:%u",
77362306a36Sopenharmony_ci				name, payload, !!(payload & 0x80),
77462306a36Sopenharmony_ci				(unsigned int)((payload >> 12) & 0xf),
77562306a36Sopenharmony_ci				(unsigned int)((payload >> 8) & 0xf));
77662306a36Sopenharmony_ci	case INTEL_PT_PWRX:
77762306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s 0x%llx Last CState:%u Deepest CState:%u Wake Reason 0x%x",
77862306a36Sopenharmony_ci				name, payload,
77962306a36Sopenharmony_ci				(unsigned int)((payload >> 4) & 0xf),
78062306a36Sopenharmony_ci				(unsigned int)(payload & 0xf),
78162306a36Sopenharmony_ci				(unsigned int)((payload >> 8) & 0xf));
78262306a36Sopenharmony_ci	case INTEL_PT_BBP:
78362306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
78462306a36Sopenharmony_ci				name, packet->count ? "4" : "8", payload);
78562306a36Sopenharmony_ci	case INTEL_PT_BIP:
78662306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
78762306a36Sopenharmony_ci				name, packet->count, payload);
78862306a36Sopenharmony_ci	case INTEL_PT_CFE:
78962306a36Sopenharmony_ci	case INTEL_PT_CFE_IP:
79062306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s IP:%d Type 0x%02x Vector 0x%llx",
79162306a36Sopenharmony_ci				name, packet->type == INTEL_PT_CFE_IP, packet->count, payload);
79262306a36Sopenharmony_ci	case INTEL_PT_EVD:
79362306a36Sopenharmony_ci		return snprintf(buf, buf_len, "%s Type 0x%02x Payload 0x%llx",
79462306a36Sopenharmony_ci				name, packet->count, payload);
79562306a36Sopenharmony_ci	default:
79662306a36Sopenharmony_ci		break;
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci	return snprintf(buf, buf_len, "%s 0x%llx (%d)",
79962306a36Sopenharmony_ci			name, payload, packet->count);
80062306a36Sopenharmony_ci}
801