linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT
@ 2019-06-10  7:27 Adrian Hunter
  2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Hi

PEBS via PT is a new feature that encodes PEBS events into the Intel PT trace.
This patch series is preparation.  Alex has posted his kernel support:

    https://lkml.org/lkml/2019/5/2/323

This patch set adds the packet definitions and a new packet decoder test,
followed by patches that enable synthesizing PEBS samples.

 
Adrian Hunter (11):
      perf intel-pt: Add new packets for PEBS via PT
      perf intel-pt: Add Intel PT packet decoder test
      perf intel-pt: Add decoder support for PEBS via PT
      perf intel-pt: Prepare to synthesize PEBS samples
      perf intel-pt: Factor out common sample preparation for re-use
      perf intel-pt: Synthesize PEBS sample basic information
      perf intel-pt: Add gp registers to synthesized PEBS sample
      perf intel-pt: Add xmm registers to synthesized PEBS sample
      perf intel-pt: Add lbr information to synthesized PEBS sample
      perf intel-pt: Add memory information to synthesized PEBS sample
      perf intel-pt: Add callchain to synthesized PEBS sample

 tools/perf/arch/x86/include/arch-tests.h           |   1 +
 tools/perf/arch/x86/tests/Build                    |   2 +-
 tools/perf/arch/x86/tests/arch-tests.c             |   4 +
 .../arch/x86/tests/intel-pt-pkt-decoder-test.c     | 304 +++++++++++++++++++++
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 114 +++++++-
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  | 137 ++++++++++
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 +++++++++-
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 +-
 tools/perf/util/intel-pt.c                         | 296 +++++++++++++++++++-
 9 files changed, 1002 insertions(+), 17 deletions(-)
 create mode 100644 tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c


Regards
Adrian


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-12  0:09   ` Arnaldo Carvalho de Melo
  2019-06-22  6:35   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 02/11] perf intel-pt: Add Intel PT packet decoder test Adrian Hunter
                   ` (9 subsequent siblings)
  10 siblings, 2 replies; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
into multiple BIP packets that come between BBP and BEP. The BEP packet
might be associated with a FUP packet. That is indicated by using a
separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
the _IP suffix.

Refer to the Intel SDM for more information about PEBS via PT.

Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
packets only occur in the context of a block (i.e. between BBP and BEP),
that context must be recorded and passed to the packet decoder.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 .../util/intel-pt-decoder/intel-pt-decoder.c  |  38 ++++-
 .../intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 +++++++++++++++++-
 .../intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 ++-
 tools/perf/util/intel-pt.c                    |   3 +-
 4 files changed, 193 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 9eb778f9c911..44218f9cf16a 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -140,6 +140,7 @@ struct intel_pt_decoder {
 	int mtc_shift;
 	struct intel_pt_stack stack;
 	enum intel_pt_pkt_state pkt_state;
+	enum intel_pt_pkt_ctx pkt_ctx;
 	struct intel_pt_pkt packet;
 	struct intel_pt_pkt tnt;
 	int pkt_step;
@@ -558,7 +559,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
 	memcpy(buf + len, decoder->buf, n);
 	len += n;
 
-	ret = intel_pt_get_packet(buf, len, &decoder->packet);
+	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
 	if (ret < (int)old_len) {
 		decoder->next_buf = decoder->buf;
 		decoder->next_len = decoder->len;
@@ -593,6 +594,7 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
 {
 	struct intel_pt_pkt_info pkt_info;
 	const unsigned char *buf = decoder->buf;
+	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
 	size_t len = decoder->len;
 	int ret;
 
@@ -611,7 +613,8 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
 			if (!len)
 				return INTEL_PT_NEED_MORE_BYTES;
 
-			ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
+			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
+						  &pkt_ctx);
 			if (!ret)
 				return INTEL_PT_NEED_MORE_BYTES;
 			if (ret < 0)
@@ -686,6 +689,10 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
 	case INTEL_PT_MNT:
 	case INTEL_PT_PTWRITE:
 	case INTEL_PT_PTWRITE_IP:
+	case INTEL_PT_BBP:
+	case INTEL_PT_BIP:
+	case INTEL_PT_BEP:
+	case INTEL_PT_BEP_IP:
 		return 0;
 
 	case INTEL_PT_MTC:
@@ -878,7 +885,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
 		}
 
 		ret = intel_pt_get_packet(decoder->buf, decoder->len,
-					  &decoder->packet);
+					  &decoder->packet, &decoder->pkt_ctx);
 		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
 		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
 			ret = intel_pt_get_split_packet(decoder);
@@ -1624,6 +1631,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			decoder->have_tma = false;
 			intel_pt_log("ERROR: Unexpected packet\n");
 			err = -EAGAIN;
@@ -1717,6 +1728,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			intel_pt_log("ERROR: Missing TIP after FUP\n");
 			decoder->pkt_state = INTEL_PT_STATE_ERR3;
 			decoder->pkt_step = 0;
@@ -2038,6 +2053,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
 			decoder->state.pwrx_payload = decoder->packet.payload;
 			return 0;
 
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
+			break;
+
 		default:
 			return intel_pt_bug(decoder);
 		}
@@ -2076,6 +2097,10 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			intel_pt_log("ERROR: Unexpected packet\n");
 			err = -ENOENT;
 			goto out;
@@ -2282,6 +2307,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 		default:
 			break;
 		}
@@ -2632,11 +2661,12 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
 static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
 			      size_t *rem)
 {
+	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
 	struct intel_pt_pkt packet;
 	int ret;
 
 	while (len) {
-		ret = intel_pt_get_packet(buf, len, &packet);
+		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
 		if (ret <= 0)
 			return false;
 		if (packet.type == INTEL_PT_TSC) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index d426761a549d..2b2793b339c0 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -71,6 +71,10 @@ static const char * const packet_name[] = {
 	[INTEL_PT_MWAIT]	= "MWAIT",
 	[INTEL_PT_PWRE]		= "PWRE",
 	[INTEL_PT_PWRX]		= "PWRX",
+	[INTEL_PT_BBP]		= "BBP",
+	[INTEL_PT_BIP]		= "BIP",
+	[INTEL_PT_BEP]		= "BEP",
+	[INTEL_PT_BEP_IP]	= "BEP",
 };
 
 const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
@@ -289,6 +293,55 @@ static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
 	return 7;
 }
 
+static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
+			    struct intel_pt_pkt *packet)
+{
+	if (len < 3)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BBP;
+	packet->count = buf[2] >> 7;
+	packet->payload = buf[2] & 0x1f;
+	return 3;
+}
+
+static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
+			      struct intel_pt_pkt *packet)
+{
+	if (len < 5)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BIP;
+	packet->count = buf[0] >> 3;
+	memcpy_le64(&packet->payload, buf + 1, 4);
+	return 5;
+}
+
+static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
+			      struct intel_pt_pkt *packet)
+{
+	if (len < 9)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BIP;
+	packet->count = buf[0] >> 3;
+	memcpy_le64(&packet->payload, buf + 1, 8);
+	return 9;
+}
+
+static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
+{
+	if (len < 2)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BEP;
+	return 2;
+}
+
+static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
+{
+	if (len < 2)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BEP_IP;
+	return 2;
+}
+
 static int intel_pt_get_ext(const unsigned char *buf, size_t len,
 			    struct intel_pt_pkt *packet)
 {
@@ -329,6 +382,12 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
 		return intel_pt_get_pwre(buf, len, packet);
 	case 0xA2: /* PWRX */
 		return intel_pt_get_pwrx(buf, len, packet);
+	case 0x63: /* BBP */
+		return intel_pt_get_bbp(buf, len, packet);
+	case 0x33: /* BEP no IP */
+		return intel_pt_get_bep(len, packet);
+	case 0xb3: /* BEP with IP */
+		return intel_pt_get_bep_ip(len, packet);
 	default:
 		return INTEL_PT_BAD_PACKET;
 	}
@@ -477,7 +536,8 @@ static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
 }
 
 static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
-				  struct intel_pt_pkt *packet)
+				  struct intel_pt_pkt *packet,
+				  enum intel_pt_pkt_ctx ctx)
 {
 	unsigned int byte;
 
@@ -487,6 +547,22 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 		return INTEL_PT_NEED_MORE_BYTES;
 
 	byte = buf[0];
+
+	switch (ctx) {
+	case INTEL_PT_NO_CTX:
+		break;
+	case INTEL_PT_BLK_4_CTX:
+		if ((byte & 0x7) == 4)
+			return intel_pt_get_bip_4(buf, len, packet);
+		break;
+	case INTEL_PT_BLK_8_CTX:
+		if ((byte & 0x7) == 4)
+			return intel_pt_get_bip_8(buf, len, packet);
+		break;
+	default:
+		break;
+	};
+
 	if (!(byte & BIT(0))) {
 		if (byte == 0)
 			return intel_pt_get_pad(packet);
@@ -525,15 +601,65 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 	}
 }
 
+void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
+			  enum intel_pt_pkt_ctx *ctx)
+{
+	switch (packet->type) {
+	case INTEL_PT_BAD:
+	case INTEL_PT_PAD:
+	case INTEL_PT_TSC:
+	case INTEL_PT_TMA:
+	case INTEL_PT_MTC:
+	case INTEL_PT_FUP:
+	case INTEL_PT_CYC:
+	case INTEL_PT_CBR:
+	case INTEL_PT_MNT:
+	case INTEL_PT_EXSTOP:
+	case INTEL_PT_EXSTOP_IP:
+	case INTEL_PT_PWRE:
+	case INTEL_PT_PWRX:
+	case INTEL_PT_BIP:
+		break;
+	case INTEL_PT_TNT:
+	case INTEL_PT_TIP:
+	case INTEL_PT_TIP_PGD:
+	case INTEL_PT_TIP_PGE:
+	case INTEL_PT_MODE_EXEC:
+	case INTEL_PT_MODE_TSX:
+	case INTEL_PT_PIP:
+	case INTEL_PT_OVF:
+	case INTEL_PT_VMCS:
+	case INTEL_PT_TRACESTOP:
+	case INTEL_PT_PSB:
+	case INTEL_PT_PSBEND:
+	case INTEL_PT_PTWRITE:
+	case INTEL_PT_PTWRITE_IP:
+	case INTEL_PT_MWAIT:
+	case INTEL_PT_BEP:
+	case INTEL_PT_BEP_IP:
+		*ctx = INTEL_PT_NO_CTX;
+		break;
+	case INTEL_PT_BBP:
+		if (packet->count)
+			*ctx = INTEL_PT_BLK_4_CTX;
+		else
+			*ctx = INTEL_PT_BLK_8_CTX;
+		break;
+	default:
+		break;
+	}
+}
+
 int intel_pt_get_packet(const unsigned char *buf, size_t len,
-			struct intel_pt_pkt *packet)
+			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
 {
 	int ret;
 
-	ret = intel_pt_do_get_packet(buf, len, packet);
+	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
 	if (ret > 0) {
 		while (ret < 8 && len > (size_t)ret && !buf[ret])
 			ret += 1;
+		intel_pt_upd_pkt_ctx(packet, ctx);
 	}
 	return ret;
 }
@@ -611,8 +737,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
 	case INTEL_PT_PTWRITE_IP:
 		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
+	case INTEL_PT_BEP:
 	case INTEL_PT_EXSTOP:
 		return snprintf(buf, buf_len, "%s IP:0", name);
+	case INTEL_PT_BEP_IP:
 	case INTEL_PT_EXSTOP_IP:
 		return snprintf(buf, buf_len, "%s IP:1", name);
 	case INTEL_PT_MWAIT:
@@ -630,6 +758,12 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 				(unsigned int)((payload >> 4) & 0xf),
 				(unsigned int)(payload & 0xf),
 				(unsigned int)((payload >> 8) & 0xf));
+	case INTEL_PT_BBP:
+		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
+				name, packet->count ? "4" : "8", payload);
+	case INTEL_PT_BIP:
+		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
+				name, packet->count, payload);
 	default:
 		break;
 	}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
index 73ddc3a88d07..682b35282abc 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
@@ -59,6 +59,10 @@ enum intel_pt_pkt_type {
 	INTEL_PT_MWAIT,
 	INTEL_PT_PWRE,
 	INTEL_PT_PWRX,
+	INTEL_PT_BBP,
+	INTEL_PT_BIP,
+	INTEL_PT_BEP,
+	INTEL_PT_BEP_IP,
 };
 
 struct intel_pt_pkt {
@@ -67,10 +71,25 @@ struct intel_pt_pkt {
 	uint64_t		payload;
 };
 
+/*
+ * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
+ * packets only occur in the context of a block (i.e. between BBP and BEP), that
+ * context must be recorded and passed to the packet decoder.
+ */
+enum intel_pt_pkt_ctx {
+	INTEL_PT_NO_CTX,	/* BIP packets are invalid */
+	INTEL_PT_BLK_4_CTX,	/* 4-byte BIP packets */
+	INTEL_PT_BLK_8_CTX,	/* 8-byte BIP packets */
+};
+
 const char *intel_pt_pkt_name(enum intel_pt_pkt_type);
 
 int intel_pt_get_packet(const unsigned char *buf, size_t len,
-			struct intel_pt_pkt *packet);
+			struct intel_pt_pkt *packet,
+			enum intel_pt_pkt_ctx *ctx);
+
+void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
+			  enum intel_pt_pkt_ctx *ctx);
 
 int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len);
 
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3cff8fe2eaa0..f43d3ac2db8b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -174,13 +174,14 @@ static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
 	int ret, pkt_len, i;
 	char desc[INTEL_PT_PKT_DESC_MAX];
 	const char *color = PERF_COLOR_BLUE;
+	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
 
 	color_fprintf(stdout, color,
 		      ". ... Intel Processor Trace data: size %zu bytes\n",
 		      len);
 
 	while (len) {
-		ret = intel_pt_get_packet(buf, len, &packet);
+		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
 		if (ret > 0)
 			pkt_len = ret;
 		else
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 02/11] perf intel-pt: Add Intel PT packet decoder test
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
  2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:36   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 03/11] perf intel-pt: Add decoder support for PEBS via PT Adrian Hunter
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add Intel PT packet decoder test. This test feeds byte sequences to the
Intel PT packet decoder and checks the results. Changes to the packet
context are also checked.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/arch/x86/include/arch-tests.h      |   1 +
 tools/perf/arch/x86/tests/Build               |   2 +-
 tools/perf/arch/x86/tests/arch-tests.c        |   4 +
 .../x86/tests/intel-pt-pkt-decoder-test.c     | 304 ++++++++++++++++++
 4 files changed, 310 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c

diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index 613709cfbbd0..c41c5affe4be 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -9,6 +9,7 @@ struct test;
 int test__rdpmc(struct test *test __maybe_unused, int subtest);
 int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
 int test__insn_x86(struct test *test __maybe_unused, int subtest);
+int test__intel_pt_pkt_decoder(struct test *test, int subtest);
 int test__bp_modify(struct test *test, int subtest);
 
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index 3d83d0c6982d..2997c506550c 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -4,5 +4,5 @@ perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 perf-y += arch-tests.o
 perf-y += rdpmc.o
 perf-y += perf-time-to-tsc.o
-perf-$(CONFIG_AUXTRACE) += insn-x86.o
+perf-$(CONFIG_AUXTRACE) += insn-x86.o intel-pt-pkt-decoder-test.o
 perf-$(CONFIG_X86_64) += bp-modify.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
index d47d3f8e3c8e..6763135aec17 100644
--- a/tools/perf/arch/x86/tests/arch-tests.c
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -23,6 +23,10 @@ struct test arch_tests[] = {
 		.desc = "x86 instruction decoder - new instructions",
 		.func = test__insn_x86,
 	},
+	{
+		.desc = "Intel PT packet decoder",
+		.func = test__intel_pt_pkt_decoder,
+	},
 #endif
 #if defined(__x86_64__)
 	{
diff --git a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
new file mode 100644
index 000000000000..901bf1f449c4
--- /dev/null
+++ b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <string.h>
+
+#include "intel-pt-decoder/intel-pt-pkt-decoder.h"
+
+#include "debug.h"
+#include "tests/tests.h"
+#include "arch-tests.h"
+
+/**
+ * struct test_data - Test data.
+ * @len: number of bytes to decode
+ * @bytes: bytes to decode
+ * @ctx: packet context to decode
+ * @packet: expected packet
+ * @new_ctx: expected new packet context
+ * @ctx_unchanged: the packet context must not change
+ */
+struct test_data {
+	int len;
+	u8 bytes[INTEL_PT_PKT_MAX_SZ];
+	enum intel_pt_pkt_ctx ctx;
+	struct intel_pt_pkt packet;
+	enum intel_pt_pkt_ctx new_ctx;
+	int ctx_unchanged;
+} data[] = {
+	/* Padding Packet */
+	{1, {0}, 0, {INTEL_PT_PAD, 0, 0}, 0, 1 },
+	/* Short Taken/Not Taken Packet */
+	{1, {4}, 0, {INTEL_PT_TNT, 1, 0}, 0, 0 },
+	{1, {6}, 0, {INTEL_PT_TNT, 1, 0x20ULL << 58}, 0, 0 },
+	{1, {0x80}, 0, {INTEL_PT_TNT, 6, 0}, 0, 0 },
+	{1, {0xfe}, 0, {INTEL_PT_TNT, 6, 0x3fULL << 58}, 0, 0 },
+	/* Long Taken/Not Taken Packet */
+	{8, {0x02, 0xa3, 2}, 0, {INTEL_PT_TNT, 1, 0xa302ULL << 47}, 0, 0 },
+	{8, {0x02, 0xa3, 3}, 0, {INTEL_PT_TNT, 1, 0x1a302ULL << 47}, 0, 0 },
+	{8, {0x02, 0xa3, 0, 0, 0, 0, 0, 0x80}, 0, {INTEL_PT_TNT, 47, 0xa302ULL << 1}, 0, 0 },
+	{8, {0x02, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_TNT, 47, 0xffffffffffffa302ULL << 1}, 0, 0 },
+	/* Target IP Packet */
+	{1, {0x0d}, 0, {INTEL_PT_TIP, 0, 0}, 0, 0 },
+	{3, {0x2d, 1, 2}, 0, {INTEL_PT_TIP, 1, 0x201}, 0, 0 },
+	{5, {0x4d, 1, 2, 3, 4}, 0, {INTEL_PT_TIP, 2, 0x4030201}, 0, 0 },
+	{7, {0x6d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 3, 0x60504030201}, 0, 0 },
+	{7, {0x8d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 4, 0x60504030201}, 0, 0 },
+	{9, {0xcd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP, 6, 0x807060504030201}, 0, 0 },
+	/* Packet Generation Enable */
+	{1, {0x11}, 0, {INTEL_PT_TIP_PGE, 0, 0}, 0, 0 },
+	{3, {0x31, 1, 2}, 0, {INTEL_PT_TIP_PGE, 1, 0x201}, 0, 0 },
+	{5, {0x51, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGE, 2, 0x4030201}, 0, 0 },
+	{7, {0x71, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 3, 0x60504030201}, 0, 0 },
+	{7, {0x91, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 4, 0x60504030201}, 0, 0 },
+	{9, {0xd1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGE, 6, 0x807060504030201}, 0, 0 },
+	/* Packet Generation Disable */
+	{1, {0x01}, 0, {INTEL_PT_TIP_PGD, 0, 0}, 0, 0 },
+	{3, {0x21, 1, 2}, 0, {INTEL_PT_TIP_PGD, 1, 0x201}, 0, 0 },
+	{5, {0x41, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGD, 2, 0x4030201}, 0, 0 },
+	{7, {0x61, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 3, 0x60504030201}, 0, 0 },
+	{7, {0x81, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 4, 0x60504030201}, 0, 0 },
+	{9, {0xc1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGD, 6, 0x807060504030201}, 0, 0 },
+	/* Flow Update Packet */
+	{1, {0x1d}, 0, {INTEL_PT_FUP, 0, 0}, 0, 0 },
+	{3, {0x3d, 1, 2}, 0, {INTEL_PT_FUP, 1, 0x201}, 0, 0 },
+	{5, {0x5d, 1, 2, 3, 4}, 0, {INTEL_PT_FUP, 2, 0x4030201}, 0, 0 },
+	{7, {0x7d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 3, 0x60504030201}, 0, 0 },
+	{7, {0x9d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 4, 0x60504030201}, 0, 0 },
+	{9, {0xdd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_FUP, 6, 0x807060504030201}, 0, 0 },
+	/* Paging Information Packet */
+	{8, {0x02, 0x43, 2, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0x60504030201}, 0, 0 },
+	{8, {0x02, 0x43, 3, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0x60504030201 | (1ULL << 63)}, 0, 0 },
+	/* Mode Exec Packet */
+	{2, {0x99, 0x00}, 0, {INTEL_PT_MODE_EXEC, 0, 16}, 0, 0 },
+	{2, {0x99, 0x01}, 0, {INTEL_PT_MODE_EXEC, 0, 64}, 0, 0 },
+	{2, {0x99, 0x02}, 0, {INTEL_PT_MODE_EXEC, 0, 32}, 0, 0 },
+	/* Mode TSX Packet */
+	{2, {0x99, 0x20}, 0, {INTEL_PT_MODE_TSX, 0, 0}, 0, 0 },
+	{2, {0x99, 0x21}, 0, {INTEL_PT_MODE_TSX, 0, 1}, 0, 0 },
+	{2, {0x99, 0x22}, 0, {INTEL_PT_MODE_TSX, 0, 2}, 0, 0 },
+	/* Trace Stop Packet */
+	{2, {0x02, 0x83}, 0, {INTEL_PT_TRACESTOP, 0, 0}, 0, 0 },
+	/* Core:Bus Ratio Packet */
+	{4, {0x02, 0x03, 0x12, 0}, 0, {INTEL_PT_CBR, 0, 0x12}, 0, 1 },
+	/* Timestamp Counter Packet */
+	{8, {0x19, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_TSC, 0, 0x7060504030201}, 0, 1 },
+	/* Mini Time Counter Packet */
+	{2, {0x59, 0x12}, 0, {INTEL_PT_MTC, 0, 0x12}, 0, 1 },
+	/* TSC / MTC Alignment Packet */
+	{7, {0x02, 0x73}, 0, {INTEL_PT_TMA, 0, 0}, 0, 1 },
+	{7, {0x02, 0x73, 1, 2}, 0, {INTEL_PT_TMA, 0, 0x201}, 0, 1 },
+	{7, {0x02, 0x73, 0, 0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0}, 0, 1 },
+	{7, {0x02, 0x73, 0x80, 0xc0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0xc080}, 0, 1 },
+	/* Cycle Count Packet */
+	{1, {0x03}, 0, {INTEL_PT_CYC, 0, 0}, 0, 1 },
+	{1, {0x0b}, 0, {INTEL_PT_CYC, 0, 1}, 0, 1 },
+	{1, {0xfb}, 0, {INTEL_PT_CYC, 0, 0x1f}, 0, 1 },
+	{2, {0x07, 2}, 0, {INTEL_PT_CYC, 0, 0x20}, 0, 1 },
+	{2, {0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xfff}, 0, 1 },
+	{3, {0x07, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x1000}, 0, 1 },
+	{3, {0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7ffff}, 0, 1 },
+	{4, {0x07, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x80000}, 0, 1 },
+	{4, {0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3ffffff}, 0, 1 },
+	{5, {0x07, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x4000000}, 0, 1 },
+	{5, {0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1ffffffff}, 0, 1 },
+	{6, {0x07, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x200000000}, 0, 1 },
+	{6, {0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xffffffffff}, 0, 1 },
+	{7, {0x07, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x10000000000}, 0, 1 },
+	{7, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7fffffffffff}, 0, 1 },
+	{8, {0x07, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x800000000000}, 0, 1 },
+	{8, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3fffffffffffff}, 0, 1 },
+	{9, {0x07, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x40000000000000}, 0, 1 },
+	{9, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1fffffffffffffff}, 0, 1 },
+	{10, {0x07, 1, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x2000000000000000}, 0, 1 },
+	{10, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe}, 0, {INTEL_PT_CYC, 0, 0xffffffffffffffff}, 0, 1 },
+	/* Virtual-Machine Control Structure Packet */
+	{7, {0x02, 0xc8, 1, 2, 3, 4, 5}, 0, {INTEL_PT_VMCS, 5, 0x504030201}, 0, 0 },
+	/* Overflow Packet */
+	{2, {0x02, 0xf3}, 0, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	{2, {0x02, 0xf3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	{2, {0x02, 0xf3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	/* Packet Stream Boundary*/
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, 0, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_4_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_8_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	/* PSB End Packet */
+	{2, {0x02, 0x23}, 0, {INTEL_PT_PSBEND, 0, 0}, 0, 0 },
+	/* Maintenance Packet */
+	{11, {0x02, 0xc3, 0x88, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_MNT, 0, 0x7060504030201}, 0, 1 },
+	/* Write Data to PT Packet */
+	{6, {0x02, 0x12, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE, 0, 0x4030201}, 0, 0 },
+	{10, {0x02, 0x32, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE, 1, 0x807060504030201}, 0, 0 },
+	{6, {0x02, 0x92, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE_IP, 0, 0x4030201}, 0, 0 },
+	{10, {0x02, 0xb2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE_IP, 1, 0x807060504030201}, 0, 0 },
+	/* Execution Stop Packet */
+	{2, {0x02, 0x62}, 0, {INTEL_PT_EXSTOP, 0, 0}, 0, 1 },
+	{2, {0x02, 0xe2}, 0, {INTEL_PT_EXSTOP_IP, 0, 0}, 0, 1 },
+	/* Monitor Wait Packet */
+	{10, {0x02, 0xc2}, 0, {INTEL_PT_MWAIT, 0, 0}, 0, 0 },
+	{10, {0x02, 0xc2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x807060504030201}, 0, 0 },
+	{10, {0x02, 0xc2, 0xff, 2, 3, 4, 7, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x8070607040302ff}, 0, 0 },
+	/* Power Entry Packet */
+	{4, {0x02, 0x22}, 0, {INTEL_PT_PWRE, 0, 0}, 0, 1 },
+	{4, {0x02, 0x22, 1, 2}, 0, {INTEL_PT_PWRE, 0, 0x0201}, 0, 1 },
+	{4, {0x02, 0x22, 0x80, 0x34}, 0, {INTEL_PT_PWRE, 0, 0x3480}, 0, 1 },
+	{4, {0x02, 0x22, 0x00, 0x56}, 0, {INTEL_PT_PWRE, 0, 0x5600}, 0, 1 },
+	/* Power Exit Packet */
+	{7, {0x02, 0xa2}, 0, {INTEL_PT_PWRX, 0, 0}, 0, 1 },
+	{7, {0x02, 0xa2, 1, 2, 3, 4, 5}, 0, {INTEL_PT_PWRX, 0, 0x504030201}, 0, 1 },
+	{7, {0x02, 0xa2, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_PWRX, 0, 0xffffffffff}, 0, 1 },
+	/* Block Begin Packet */
+	{3, {0x02, 0x63, 0x00}, 0, {INTEL_PT_BBP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{3, {0x02, 0x63, 0x80}, 0, {INTEL_PT_BBP, 1, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{3, {0x02, 0x63, 0x1f}, 0, {INTEL_PT_BBP, 0, 0x1f}, INTEL_PT_BLK_8_CTX, 0 },
+	{3, {0x02, 0x63, 0x9f}, 0, {INTEL_PT_BBP, 1, 0x1f}, INTEL_PT_BLK_4_CTX, 0 },
+	/* 4-byte Block Item Packet */
+	{5, {0x04}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0xfc}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0x04, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0xfc, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 },
+	/* 8-byte Block Item Packet */
+	{9, {0x04}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0xfc}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0x04, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0xfc, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 },
+	/* Block End Packet */
+	{2, {0x02, 0x33}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 },
+	{2, {0x02, 0xb3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 },
+	{2, {0x02, 0x33}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 },
+	{2, {0x02, 0xb3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 },
+	/* Terminator */
+	{0, {0}, 0, {0, 0, 0}, 0, 0 },
+};
+
+static int dump_packet(struct intel_pt_pkt *packet, u8 *bytes, int len)
+{
+	char desc[INTEL_PT_PKT_DESC_MAX];
+	int ret, i;
+
+	for (i = 0; i < len; i++)
+		pr_debug(" %02x", bytes[i]);
+	for (; i < INTEL_PT_PKT_MAX_SZ; i++)
+		pr_debug("   ");
+	pr_debug("   ");
+	ret = intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX);
+	if (ret < 0) {
+		pr_debug("intel_pt_pkt_desc failed!\n");
+		return TEST_FAIL;
+	}
+	pr_debug("%s\n", desc);
+
+	return TEST_OK;
+}
+
+static void decoding_failed(struct test_data *d)
+{
+	pr_debug("Decoding failed!\n");
+	pr_debug("Decoding:  ");
+	dump_packet(&d->packet, d->bytes, d->len);
+}
+
+static int fail(struct test_data *d, struct intel_pt_pkt *packet, int len,
+		enum intel_pt_pkt_ctx new_ctx)
+{
+	decoding_failed(d);
+
+	if (len != d->len)
+		pr_debug("Expected length: %d   Decoded length %d\n",
+			 d->len, len);
+
+	if (packet->type != d->packet.type)
+		pr_debug("Expected type: %d   Decoded type %d\n",
+			 d->packet.type, packet->type);
+
+	if (packet->count != d->packet.count)
+		pr_debug("Expected count: %d   Decoded count %d\n",
+			 d->packet.count, packet->count);
+
+	if (packet->payload != d->packet.payload)
+		pr_debug("Expected payload: 0x%llx   Decoded payload 0x%llx\n",
+			 (unsigned long long)d->packet.payload,
+			 (unsigned long long)packet->payload);
+
+	if (new_ctx != d->new_ctx)
+		pr_debug("Expected packet context: %d   Decoded packet context %d\n",
+			 d->new_ctx, new_ctx);
+
+	return TEST_FAIL;
+}
+
+static int test_ctx_unchanged(struct test_data *d, struct intel_pt_pkt *packet,
+			      enum intel_pt_pkt_ctx ctx)
+{
+	enum intel_pt_pkt_ctx old_ctx = ctx;
+
+	intel_pt_upd_pkt_ctx(packet, &ctx);
+
+	if (ctx != old_ctx) {
+		decoding_failed(d);
+		pr_debug("Packet context changed!\n");
+		return TEST_FAIL;
+	}
+
+	return TEST_OK;
+}
+
+static int test_one(struct test_data *d)
+{
+	struct intel_pt_pkt packet;
+	enum intel_pt_pkt_ctx ctx = d->ctx;
+	int ret;
+
+	memset(&packet, 0xff, sizeof(packet));
+
+	/* Decode a packet */
+	ret = intel_pt_get_packet(d->bytes, d->len, &packet, &ctx);
+	if (ret < 0 || ret > INTEL_PT_PKT_MAX_SZ) {
+		decoding_failed(d);
+		pr_debug("intel_pt_get_packet returned %d\n", ret);
+		return TEST_FAIL;
+	}
+
+	/* Some packets must always leave the packet context unchanged */
+	if (d->ctx_unchanged) {
+		int err;
+
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_NO_CTX);
+		if (err)
+			return err;
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_4_CTX);
+		if (err)
+			return err;
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_8_CTX);
+		if (err)
+			return err;
+	}
+
+	/* Compare to the expected values */
+	if (ret != d->len || packet.type != d->packet.type ||
+	    packet.count != d->packet.count ||
+	    packet.payload != d->packet.payload || ctx != d->new_ctx)
+		return fail(d, &packet, ret, ctx);
+
+	pr_debug("Decoded ok:");
+	ret = dump_packet(&d->packet, d->bytes, d->len);
+
+	return ret;
+}
+
+/*
+ * This test feeds byte sequences to the Intel PT packet decoder and checks the
+ * results. Changes to the packet context are also checked.
+ */
+int test__intel_pt_pkt_decoder(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+	struct test_data *d = data;
+	int ret;
+
+	for (d = data; d->len; d++) {
+		ret = test_one(d);
+		if (ret)
+			return ret;
+	}
+
+	return TEST_OK;
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 03/11] perf intel-pt: Add decoder support for PEBS via PT
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
  2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
  2019-06-10  7:27 ` [PATCH 02/11] perf intel-pt: Add Intel PT packet decoder test Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:37   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 04/11] perf intel-pt: Prepare to synthesize PEBS samples Adrian Hunter
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

PEBS data is encoded in Block Item Packets (BIP). Populate a new structure
intel_pt_blk_items with the values and, upon a Block End Packet (BEP),
report them as a new Intel PT sample type INTEL_PT_BLK_ITEMS.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 .../util/intel-pt-decoder/intel-pt-decoder.c  |  78 +++++++++-
 .../util/intel-pt-decoder/intel-pt-decoder.h  | 137 ++++++++++++++++++
 2 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 44218f9cf16a..3dcade00f7d0 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -141,6 +141,9 @@ struct intel_pt_decoder {
 	struct intel_pt_stack stack;
 	enum intel_pt_pkt_state pkt_state;
 	enum intel_pt_pkt_ctx pkt_ctx;
+	enum intel_pt_pkt_ctx prev_pkt_ctx;
+	enum intel_pt_blk_type blk_type;
+	int blk_type_pos;
 	struct intel_pt_pkt packet;
 	struct intel_pt_pkt tnt;
 	int pkt_step;
@@ -174,6 +177,7 @@ struct intel_pt_decoder {
 	bool set_fup_mwait;
 	bool set_fup_pwre;
 	bool set_fup_exstop;
+	bool set_fup_bep;
 	bool sample_cyc;
 	unsigned int fup_tx_flags;
 	unsigned int tx_flags;
@@ -559,6 +563,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
 	memcpy(buf + len, decoder->buf, n);
 	len += n;
 
+	decoder->prev_pkt_ctx = decoder->pkt_ctx;
 	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
 	if (ret < (int)old_len) {
 		decoder->next_buf = decoder->buf;
@@ -884,6 +889,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
 				return ret;
 		}
 
+		decoder->prev_pkt_ctx = decoder->pkt_ctx;
 		ret = intel_pt_get_packet(decoder->buf, decoder->len,
 					  &decoder->packet, &decoder->pkt_ctx);
 		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
@@ -1123,6 +1129,14 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
 		decoder->state.to_ip = 0;
 		ret = true;
 	}
+	if (decoder->set_fup_bep) {
+		decoder->set_fup_bep = false;
+		decoder->state.type |= INTEL_PT_BLK_ITEMS;
+		decoder->state.type &= ~INTEL_PT_BRANCH;
+		decoder->state.from_ip = decoder->ip;
+		decoder->state.to_ip = 0;
+		ret = true;
+	}
 	return ret;
 }
 
@@ -1600,6 +1614,46 @@ static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
 	intel_pt_log_to("Setting timestamp", decoder->timestamp);
 }
 
+static void intel_pt_bbp(struct intel_pt_decoder *decoder)
+{
+	if (decoder->prev_pkt_ctx == INTEL_PT_NO_CTX) {
+		memset(decoder->state.items.mask, 0, sizeof(decoder->state.items.mask));
+		decoder->state.items.is_32_bit = false;
+	}
+	decoder->blk_type = decoder->packet.payload;
+	decoder->blk_type_pos = intel_pt_blk_type_pos(decoder->blk_type);
+	if (decoder->blk_type == INTEL_PT_GP_REGS)
+		decoder->state.items.is_32_bit = decoder->packet.count;
+	if (decoder->blk_type_pos < 0) {
+		intel_pt_log("WARNING: Unknown block type %u\n",
+			     decoder->blk_type);
+	} else if (decoder->state.items.mask[decoder->blk_type_pos]) {
+		intel_pt_log("WARNING: Duplicate block type %u\n",
+			     decoder->blk_type);
+	}
+}
+
+static void intel_pt_bip(struct intel_pt_decoder *decoder)
+{
+	uint32_t id = decoder->packet.count;
+	uint32_t bit = 1 << id;
+	int pos = decoder->blk_type_pos;
+
+	if (pos < 0 || id >= INTEL_PT_BLK_ITEM_ID_CNT) {
+		intel_pt_log("WARNING: Unknown block item %u type %d\n",
+			     id, decoder->blk_type);
+		return;
+	}
+
+	if (decoder->state.items.mask[pos] & bit) {
+		intel_pt_log("WARNING: Duplicate block item %u type %d\n",
+			     id, decoder->blk_type);
+	}
+
+	decoder->state.items.mask[pos] |= bit;
+	decoder->state.items.val[pos][id] = decoder->packet.payload;
+}
+
 /* Walk PSB+ packets when already in sync. */
 static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
 {
@@ -2054,10 +2108,31 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
 			return 0;
 
 		case INTEL_PT_BBP:
+			intel_pt_bbp(decoder);
+			break;
+
 		case INTEL_PT_BIP:
+			intel_pt_bip(decoder);
+			break;
+
 		case INTEL_PT_BEP:
+			decoder->state.type = INTEL_PT_BLK_ITEMS;
+			decoder->state.from_ip = decoder->ip;
+			decoder->state.to_ip = 0;
+			return 0;
+
 		case INTEL_PT_BEP_IP:
-			break;
+			err = intel_pt_get_next_packet(decoder);
+			if (err)
+				return err;
+			if (decoder->packet.type == INTEL_PT_FUP) {
+				decoder->set_fup_bep = true;
+				no_tip = true;
+			} else {
+				intel_pt_log_at("ERROR: Missing FUP after BEP",
+						decoder->pos);
+			}
+			goto next;
 
 		default:
 			return intel_pt_bug(decoder);
@@ -2326,6 +2401,7 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
 	decoder->set_fup_mwait = false;
 	decoder->set_fup_pwre = false;
 	decoder->set_fup_exstop = false;
+	decoder->set_fup_bep = false;
 
 	if (!decoder->branch_enable) {
 		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 6a61773dc44b..7757ccae5833 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -39,6 +39,7 @@ enum intel_pt_sample_type {
 	INTEL_PT_CBR_CHG	= 1 << 8,
 	INTEL_PT_TRACE_BEGIN	= 1 << 9,
 	INTEL_PT_TRACE_END	= 1 << 10,
+	INTEL_PT_BLK_ITEMS	= 1 << 11,
 };
 
 enum intel_pt_period_type {
@@ -70,6 +71,141 @@ enum intel_pt_param_flags {
 	INTEL_PT_FUP_WITH_NLIP	= 1 << 0,
 };
 
+enum intel_pt_blk_type {
+	INTEL_PT_GP_REGS	= 1,
+	INTEL_PT_PEBS_BASIC	= 4,
+	INTEL_PT_PEBS_MEM	= 5,
+	INTEL_PT_LBR_0		= 8,
+	INTEL_PT_LBR_1		= 9,
+	INTEL_PT_LBR_2		= 10,
+	INTEL_PT_XMM		= 16,
+	INTEL_PT_BLK_TYPE_MAX
+};
+
+/*
+ * The block type numbers are not sequential but here they are given sequential
+ * positions to avoid wasting space for array placement.
+ */
+enum intel_pt_blk_type_pos {
+	INTEL_PT_GP_REGS_POS,
+	INTEL_PT_PEBS_BASIC_POS,
+	INTEL_PT_PEBS_MEM_POS,
+	INTEL_PT_LBR_0_POS,
+	INTEL_PT_LBR_1_POS,
+	INTEL_PT_LBR_2_POS,
+	INTEL_PT_XMM_POS,
+	INTEL_PT_BLK_TYPE_CNT
+};
+
+/* Get the array position for a block type */
+static inline int intel_pt_blk_type_pos(enum intel_pt_blk_type blk_type)
+{
+#define BLK_TYPE(bt) [INTEL_PT_##bt] = INTEL_PT_##bt##_POS + 1
+	const int map[INTEL_PT_BLK_TYPE_MAX] = {
+		BLK_TYPE(GP_REGS),
+		BLK_TYPE(PEBS_BASIC),
+		BLK_TYPE(PEBS_MEM),
+		BLK_TYPE(LBR_0),
+		BLK_TYPE(LBR_1),
+		BLK_TYPE(LBR_2),
+		BLK_TYPE(XMM),
+	};
+#undef BLK_TYPE
+
+	return blk_type < INTEL_PT_BLK_TYPE_MAX ? map[blk_type] - 1 : -1;
+}
+
+#define INTEL_PT_BLK_ITEM_ID_CNT	32
+
+/*
+ * Use unions so that the block items can be accessed by name or by array index.
+ * There is an array of 32-bit masks for each block type, which indicate which
+ * values are present. Then arrays of 32 64-bit values for each block type.
+ */
+struct intel_pt_blk_items {
+	union {
+		uint32_t mask[INTEL_PT_BLK_TYPE_CNT];
+		struct {
+			uint32_t has_rflags:1;
+			uint32_t has_rip:1;
+			uint32_t has_rax:1;
+			uint32_t has_rcx:1;
+			uint32_t has_rdx:1;
+			uint32_t has_rbx:1;
+			uint32_t has_rsp:1;
+			uint32_t has_rbp:1;
+			uint32_t has_rsi:1;
+			uint32_t has_rdi:1;
+			uint32_t has_r8:1;
+			uint32_t has_r9:1;
+			uint32_t has_r10:1;
+			uint32_t has_r11:1;
+			uint32_t has_r12:1;
+			uint32_t has_r13:1;
+			uint32_t has_r14:1;
+			uint32_t has_r15:1;
+			uint32_t has_unused_0:14;
+			uint32_t has_ip:1;
+			uint32_t has_applicable_counters:1;
+			uint32_t has_timestamp:1;
+			uint32_t has_unused_1:29;
+			uint32_t has_mem_access_address:1;
+			uint32_t has_mem_aux_info:1;
+			uint32_t has_mem_access_latency:1;
+			uint32_t has_tsx_aux_info:1;
+			uint32_t has_unused_2:28;
+			uint32_t has_lbr_0;
+			uint32_t has_lbr_1;
+			uint32_t has_lbr_2;
+			uint32_t has_xmm;
+		};
+	};
+	union {
+		uint64_t val[INTEL_PT_BLK_TYPE_CNT][INTEL_PT_BLK_ITEM_ID_CNT];
+		struct {
+			struct {
+				uint64_t rflags;
+				uint64_t rip;
+				uint64_t rax;
+				uint64_t rcx;
+				uint64_t rdx;
+				uint64_t rbx;
+				uint64_t rsp;
+				uint64_t rbp;
+				uint64_t rsi;
+				uint64_t rdi;
+				uint64_t r8;
+				uint64_t r9;
+				uint64_t r10;
+				uint64_t r11;
+				uint64_t r12;
+				uint64_t r13;
+				uint64_t r14;
+				uint64_t r15;
+				uint64_t unused_0[INTEL_PT_BLK_ITEM_ID_CNT - 18];
+			};
+			struct {
+				uint64_t ip;
+				uint64_t applicable_counters;
+				uint64_t timestamp;
+				uint64_t unused_1[INTEL_PT_BLK_ITEM_ID_CNT - 3];
+			};
+			struct {
+				uint64_t mem_access_address;
+				uint64_t mem_aux_info;
+				uint64_t mem_access_latency;
+				uint64_t tsx_aux_info;
+				uint64_t unused_2[INTEL_PT_BLK_ITEM_ID_CNT - 4];
+			};
+			uint64_t lbr_0[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t lbr_1[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t lbr_2[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t xmm[INTEL_PT_BLK_ITEM_ID_CNT];
+		};
+	};
+	bool is_32_bit;
+};
+
 struct intel_pt_state {
 	enum intel_pt_sample_type type;
 	int err;
@@ -90,6 +226,7 @@ struct intel_pt_state {
 	enum intel_pt_insn_op insn_op;
 	int insn_len;
 	char insn[INTEL_PT_INSN_BUF_SZ];
+	struct intel_pt_blk_items items;
 };
 
 struct intel_pt_insn;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 04/11] perf intel-pt: Prepare to synthesize PEBS samples
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (2 preceding siblings ...)
  2019-06-10  7:27 ` [PATCH 03/11] perf intel-pt: Add decoder support for PEBS via PT Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:38   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 05/11] perf intel-pt: Factor out common sample preparation for re-use Adrian Hunter
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add infrastructure to prepare for synthesizing PEBS samples but leave the
actual synthesis to later patches.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index f43d3ac2db8b..389ec4612f86 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -104,6 +104,9 @@ struct intel_pt {
 	u64 pwrx_id;
 	u64 cbr_id;
 
+	bool sample_pebs;
+	struct perf_evsel *pebs_evsel;
+
 	u64 tsc_bit;
 	u64 mtc_bit;
 	u64 mtc_freq_bits;
@@ -1431,6 +1434,11 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
+static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq __maybe_unused)
+{
+	return 0;
+}
+
 static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,
 				pid_t pid, pid_t tid, u64 ip, u64 timestamp)
 {
@@ -1518,6 +1526,16 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
 		ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
 	}
 
+	/*
+	 * Do PEBS first to allow for the possibility that the PEBS timestamp
+	 * precedes the current timestamp.
+	 */
+	if (pt->sample_pebs && state->type & INTEL_PT_BLK_ITEMS) {
+		err = intel_pt_synth_pebs_sample(ptq);
+		if (err)
+			return err;
+	}
+
 	if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) {
 		if (state->type & INTEL_PT_CBR_CHG) {
 			err = intel_pt_synth_cbr_sample(ptq);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 05/11] perf intel-pt: Factor out common sample preparation for re-use
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (3 preceding siblings ...)
  2019-06-10  7:27 ` [PATCH 04/11] perf intel-pt: Prepare to synthesize PEBS samples Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:38   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 06/11] perf intel-pt: Synthesize PEBS sample basic information Adrian Hunter
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Factor out common sample preparation for re-use when synthesizing PEBS
samples.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 389ec4612f86..1f5520f964ab 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1078,28 +1078,37 @@ static inline bool intel_pt_skip_event(struct intel_pt *pt)
 	       pt->num_events++ < pt->synth_opts.initial_skip;
 }
 
+static void intel_pt_prep_a_sample(struct intel_pt_queue *ptq,
+				   union perf_event *event,
+				   struct perf_sample *sample)
+{
+	event->sample.header.type = PERF_RECORD_SAMPLE;
+	event->sample.header.size = sizeof(struct perf_event_header);
+
+	sample->pid = ptq->pid;
+	sample->tid = ptq->tid;
+	sample->cpu = ptq->cpu;
+	sample->insn_len = ptq->insn_len;
+	memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
+}
+
 static void intel_pt_prep_b_sample(struct intel_pt *pt,
 				   struct intel_pt_queue *ptq,
 				   union perf_event *event,
 				   struct perf_sample *sample)
 {
+	intel_pt_prep_a_sample(ptq, event, sample);
+
 	if (!pt->timeless_decoding)
 		sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
 
 	sample->ip = ptq->state->from_ip;
 	sample->cpumode = intel_pt_cpumode(pt, sample->ip);
-	sample->pid = ptq->pid;
-	sample->tid = ptq->tid;
 	sample->addr = ptq->state->to_ip;
 	sample->period = 1;
-	sample->cpu = ptq->cpu;
 	sample->flags = ptq->flags;
-	sample->insn_len = ptq->insn_len;
-	memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
-	event->sample.header.type = PERF_RECORD_SAMPLE;
 	event->sample.header.misc = sample->cpumode;
-	event->sample.header.size = sizeof(struct perf_event_header);
 }
 
 static int intel_pt_inject_event(union perf_event *event,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 06/11] perf intel-pt: Synthesize PEBS sample basic information
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (4 preceding siblings ...)
  2019-06-10  7:27 ` [PATCH 05/11] perf intel-pt: Factor out common sample preparation for re-use Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:39   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:27 ` [PATCH 07/11] perf intel-pt: Add gp registers to synthesized PEBS sample Adrian Hunter
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Synthesize a PEBS sample using basic information (ip, timestamp) only.
Other PEBS information will be added in later patches.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 52 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 1f5520f964ab..4517c02fa478 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1443,9 +1443,57 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
-static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq __maybe_unused)
+static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
-	return 0;
+	const struct intel_pt_blk_items *items = &ptq->state->items;
+	struct perf_sample sample = { .ip = 0, };
+	union perf_event *event = ptq->event_buf;
+	struct intel_pt *pt = ptq->pt;
+	struct perf_evsel *evsel = pt->pebs_evsel;
+	u64 sample_type = evsel->attr.sample_type;
+	u64 id = evsel->id[0];
+	u8 cpumode;
+
+	if (intel_pt_skip_event(pt))
+		return 0;
+
+	intel_pt_prep_a_sample(ptq, event, &sample);
+
+	sample.id = id;
+	sample.stream_id = id;
+
+	if (!evsel->attr.freq)
+		sample.period = evsel->attr.sample_period;
+
+	/* No support for non-zero CS base */
+	if (items->has_ip)
+		sample.ip = items->ip;
+	else if (items->has_rip)
+		sample.ip = items->rip;
+	else
+		sample.ip = ptq->state->from_ip;
+
+	/* No support for guest mode at this time */
+	cpumode = sample.ip < ptq->pt->kernel_start ?
+		  PERF_RECORD_MISC_USER :
+		  PERF_RECORD_MISC_KERNEL;
+
+	event->sample.header.misc = cpumode | PERF_RECORD_MISC_EXACT_IP;
+
+	sample.cpumode = cpumode;
+
+	if (sample_type & PERF_SAMPLE_TIME) {
+		u64 timestamp = 0;
+
+		if (items->has_timestamp)
+			timestamp = items->timestamp;
+		else if (!pt->timeless_decoding)
+			timestamp = ptq->timestamp;
+		if (timestamp)
+			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
+	}
+
+	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 
 static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 07/11] perf intel-pt: Add gp registers to synthesized PEBS sample
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (5 preceding siblings ...)
  2019-06-10  7:27 ` [PATCH 06/11] perf intel-pt: Synthesize PEBS sample basic information Adrian Hunter
@ 2019-06-10  7:27 ` Adrian Hunter
  2019-06-22  6:40   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:28 ` [PATCH 08/11] perf intel-pt: Add xmm " Adrian Hunter
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add general purpose register information from PEBS data in the Intel PT
trace to the synthesized PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 4517c02fa478..3a6d5af6a71b 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -43,6 +43,8 @@
 #include "intel-pt.h"
 #include "config.h"
 
+#include "../arch/x86/include/uapi/asm/perf_regs.h"
+
 #include "intel-pt-decoder/intel-pt-log.h"
 #include "intel-pt-decoder/intel-pt-decoder.h"
 #include "intel-pt-decoder/intel-pt-insn-decoder.h"
@@ -1443,6 +1445,60 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
+/*
+ * PEBS gp_regs array indexes plus 1 so that 0 means not present. Refer
+ * intel_pt_add_gp_regs().
+ */
+static const int pebs_gp_regs[] = {
+	[PERF_REG_X86_FLAGS]	= 1,
+	[PERF_REG_X86_IP]	= 2,
+	[PERF_REG_X86_AX]	= 3,
+	[PERF_REG_X86_CX]	= 4,
+	[PERF_REG_X86_DX]	= 5,
+	[PERF_REG_X86_BX]	= 6,
+	[PERF_REG_X86_SP]	= 7,
+	[PERF_REG_X86_BP]	= 8,
+	[PERF_REG_X86_SI]	= 9,
+	[PERF_REG_X86_DI]	= 10,
+	[PERF_REG_X86_R8]	= 11,
+	[PERF_REG_X86_R9]	= 12,
+	[PERF_REG_X86_R10]	= 13,
+	[PERF_REG_X86_R11]	= 14,
+	[PERF_REG_X86_R12]	= 15,
+	[PERF_REG_X86_R13]	= 16,
+	[PERF_REG_X86_R14]	= 17,
+	[PERF_REG_X86_R15]	= 18,
+};
+
+static u64 *intel_pt_add_gp_regs(struct regs_dump *intr_regs, u64 *pos,
+				 const struct intel_pt_blk_items *items,
+				 u64 regs_mask)
+{
+	const u64 *gp_regs = items->val[INTEL_PT_GP_REGS_POS];
+	u32 mask = items->mask[INTEL_PT_GP_REGS_POS];
+	u32 bit;
+	int i;
+
+	for (i = 0, bit = 1; i < PERF_REG_X86_64_MAX; i++, bit <<= 1) {
+		/* Get the PEBS gp_regs array index */
+		int n = pebs_gp_regs[i] - 1;
+
+		if (n < 0)
+			continue;
+		/*
+		 * Add only registers that were requested (i.e. 'regs_mask') and
+		 * that were provided (i.e. 'mask'), and update the resulting
+		 * mask (i.e. 'intr_regs->mask') accordingly.
+		 */
+		if (mask & 1 << n && regs_mask & bit) {
+			intr_regs->mask |= bit;
+			*pos++ = gp_regs[n];
+		}
+	}
+
+	return pos;
+}
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1493,6 +1549,19 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
 	}
 
+	if (sample_type & PERF_SAMPLE_REGS_INTR &&
+	    items->mask[INTEL_PT_GP_REGS_POS]) {
+		u64 regs[sizeof(sample.intr_regs.mask)];
+		u64 regs_mask = evsel->attr.sample_regs_intr;
+
+		sample.intr_regs.abi = items->is_32_bit ?
+				       PERF_SAMPLE_REGS_ABI_32 :
+				       PERF_SAMPLE_REGS_ABI_64;
+		sample.intr_regs.regs = regs;
+
+		intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 08/11] perf intel-pt: Add xmm registers to synthesized PEBS sample
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (6 preceding siblings ...)
  2019-06-10  7:27 ` [PATCH 07/11] perf intel-pt: Add gp registers to synthesized PEBS sample Adrian Hunter
@ 2019-06-10  7:28 ` Adrian Hunter
  2019-06-22  6:40   ` [tip:perf/core] perf intel-pt: Add XMM " tip-bot for Adrian Hunter
  2019-06-10  7:28 ` [PATCH 09/11] perf intel-pt: Add lbr information " Adrian Hunter
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add xmm register information from PEBS data in the Intel PT trace to the
synthesized PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 3a6d5af6a71b..0175a4ec248f 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1499,6 +1499,31 @@ static u64 *intel_pt_add_gp_regs(struct regs_dump *intr_regs, u64 *pos,
 	return pos;
 }
 
+#ifndef PERF_REG_X86_XMM0
+#define PERF_REG_X86_XMM0 32
+#endif
+
+static void intel_pt_add_xmm(struct regs_dump *intr_regs, u64 *pos,
+			     const struct intel_pt_blk_items *items,
+			     u64 regs_mask)
+{
+	u32 mask = items->has_xmm & (regs_mask >> PERF_REG_X86_XMM0);
+	const u64 *xmm = items->xmm;
+
+	/*
+	 * If there are any XMM registers, then there should be all of them.
+	 * Nevertheless, follow the logic to add only registers that were
+	 * requested (i.e. 'regs_mask') and that were provided (i.e. 'mask'),
+	 * and update the resulting mask (i.e. 'intr_regs->mask') accordingly.
+	 */
+	intr_regs->mask |= (u64)mask << PERF_REG_X86_XMM0;
+
+	for (; mask; mask >>= 1, xmm++) {
+		if (mask & 1)
+			*pos++ = *xmm;
+	}
+}
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1553,13 +1578,16 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 	    items->mask[INTEL_PT_GP_REGS_POS]) {
 		u64 regs[sizeof(sample.intr_regs.mask)];
 		u64 regs_mask = evsel->attr.sample_regs_intr;
+		u64 *pos;
 
 		sample.intr_regs.abi = items->is_32_bit ?
 				       PERF_SAMPLE_REGS_ABI_32 :
 				       PERF_SAMPLE_REGS_ABI_64;
 		sample.intr_regs.regs = regs;
 
-		intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+		pos = intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+
+		intel_pt_add_xmm(&sample.intr_regs, pos, items, regs_mask);
 	}
 
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 09/11] perf intel-pt: Add lbr information to synthesized PEBS sample
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (7 preceding siblings ...)
  2019-06-10  7:28 ` [PATCH 08/11] perf intel-pt: Add xmm " Adrian Hunter
@ 2019-06-10  7:28 ` Adrian Hunter
  2019-06-22  6:41   ` [tip:perf/core] perf intel-pt: Add LBR " tip-bot for Adrian Hunter
  2019-06-10  7:28 ` [PATCH 10/11] perf intel-pt: Add memory " Adrian Hunter
  2019-06-10  7:28 ` [PATCH 11/11] perf intel-pt: Add callchain " Adrian Hunter
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add lbr information from PEBS data in the Intel PT trace to the synthesized
PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 72 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 0175a4ec248f..a73d92189b45 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1524,6 +1524,58 @@ static void intel_pt_add_xmm(struct regs_dump *intr_regs, u64 *pos,
 	}
 }
 
+#define LBR_INFO_MISPRED	(1ULL << 63)
+#define LBR_INFO_IN_TX		(1ULL << 62)
+#define LBR_INFO_ABORT		(1ULL << 61)
+#define LBR_INFO_CYCLES		0xffff
+
+/* Refer kernel's intel_pmu_store_pebs_lbrs() */
+static u64 intel_pt_lbr_flags(u64 info)
+{
+	union {
+		struct branch_flags flags;
+		u64 result;
+	} u = {
+		.flags = {
+			.mispred	= !!(info & LBR_INFO_MISPRED),
+			.predicted	= !(info & LBR_INFO_MISPRED),
+			.in_tx		= !!(info & LBR_INFO_IN_TX),
+			.abort		= !!(info & LBR_INFO_ABORT),
+			.cycles		= info & LBR_INFO_CYCLES,
+		}
+	};
+
+	return u.result;
+}
+
+static void intel_pt_add_lbrs(struct branch_stack *br_stack,
+			      const struct intel_pt_blk_items *items)
+{
+	u64 *to;
+	int i;
+
+	br_stack->nr = 0;
+
+	to = &br_stack->entries[0].from;
+
+	for (i = INTEL_PT_LBR_0_POS; i <= INTEL_PT_LBR_2_POS; i++) {
+		u32 mask = items->mask[i];
+		const u64 *from = items->val[i];
+
+		for (; mask; mask >>= 3, from += 3) {
+			if ((mask & 7) == 7) {
+				*to++ = from[0];
+				*to++ = from[1];
+				*to++ = intel_pt_lbr_flags(from[2]);
+				br_stack->nr += 1;
+			}
+		}
+	}
+}
+
+/* INTEL_PT_LBR_0, INTEL_PT_LBR_1 and INTEL_PT_LBR_2 */
+#define LBRS_MAX (INTEL_PT_BLK_ITEM_ID_CNT * 3)
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1590,6 +1642,26 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 		intel_pt_add_xmm(&sample.intr_regs, pos, items, regs_mask);
 	}
 
+	if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
+		struct {
+			struct branch_stack br_stack;
+			struct branch_entry entries[LBRS_MAX];
+		} br;
+
+		if (items->mask[INTEL_PT_LBR_0_POS] ||
+		    items->mask[INTEL_PT_LBR_1_POS] ||
+		    items->mask[INTEL_PT_LBR_2_POS]) {
+			intel_pt_add_lbrs(&br.br_stack, items);
+			sample.branch_stack = &br.br_stack;
+		} else if (pt->synth_opts.last_branch) {
+			intel_pt_copy_last_branch_rb(ptq);
+			sample.branch_stack = ptq->last_branch;
+		} else {
+			br.br_stack.nr = 0;
+			sample.branch_stack = &br.br_stack;
+		}
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 10/11] perf intel-pt: Add memory information to synthesized PEBS sample
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (8 preceding siblings ...)
  2019-06-10  7:28 ` [PATCH 09/11] perf intel-pt: Add lbr information " Adrian Hunter
@ 2019-06-10  7:28 ` Adrian Hunter
  2019-06-22  6:42   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2019-06-10  7:28 ` [PATCH 11/11] perf intel-pt: Add callchain " Adrian Hunter
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Add memory information from PEBS data in the Intel PT trace to the
synthesized PEBS sample. This provides sample types PERF_SAMPLE_ADDR,
PERF_SAMPLE_WEIGHT, and PERF_SAMPLE_TRANSACTION, but not
PERF_SAMPLE_DATA_SRC.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index a73d92189b45..0b7beb98a028 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1662,6 +1662,33 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 		}
 	}
 
+	if (sample_type & PERF_SAMPLE_ADDR && items->has_mem_access_address)
+		sample.addr = items->mem_access_address;
+
+	if (sample_type & PERF_SAMPLE_WEIGHT) {
+		/*
+		 * Refer kernel's setup_pebs_adaptive_sample_data() and
+		 * intel_hsw_weight().
+		 */
+		if (items->has_mem_access_latency)
+			sample.weight = items->mem_access_latency;
+		if (!sample.weight && items->has_tsx_aux_info) {
+			/* Cycles last block */
+			sample.weight = (u32)items->tsx_aux_info;
+		}
+	}
+
+	if (sample_type & PERF_SAMPLE_TRANSACTION && items->has_tsx_aux_info) {
+		u64 ax = items->has_rax ? items->rax : 0;
+		/* Refer kernel's intel_hsw_transaction() */
+		u64 txn = (u8)(items->tsx_aux_info >> 32);
+
+		/* For RTM XABORTs also log the abort code from AX */
+		if (txn & PERF_TXN_TRANSACTION && ax & 1)
+			txn |= ((ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
+		sample.transaction = txn;
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH 11/11] perf intel-pt: Add callchain to synthesized PEBS sample
  2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
                   ` (9 preceding siblings ...)
  2019-06-10  7:28 ` [PATCH 10/11] perf intel-pt: Add memory " Adrian Hunter
@ 2019-06-10  7:28 ` Adrian Hunter
  2019-06-22  6:43   ` [tip:perf/core] " tip-bot for Adrian Hunter
  10 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-10  7:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

Like other synthesized events, if there is also an Intel PT branch trace,
then a call stack can also be synthesized.  Add that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 0b7beb98a028..ea03bdaf8009 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1626,6 +1626,14 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
 	}
 
+	if (sample_type & PERF_SAMPLE_CALLCHAIN &&
+	    pt->synth_opts.callchain) {
+		thread_stack__sample(ptq->thread, ptq->cpu, ptq->chain,
+				     pt->synth_opts.callchain_sz, sample.ip,
+				     pt->kernel_start);
+		sample.callchain = ptq->chain;
+	}
+
 	if (sample_type & PERF_SAMPLE_REGS_INTR &&
 	    items->mask[INTEL_PT_GP_REGS_POS]) {
 		u64 regs[sizeof(sample.intr_regs.mask)];
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
@ 2019-06-12  0:09   ` Arnaldo Carvalho de Melo
  2019-06-12  5:58     ` Adrian Hunter
  2019-06-22  6:35   ` [tip:perf/core] " tip-bot for Adrian Hunter
  1 sibling, 1 reply; 30+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-06-12  0:09 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: Jiri Olsa, linux-kernel

Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
> into multiple BIP packets that come between BBP and BEP. The BEP packet
> might be associated with a FUP packet. That is indicated by using a
> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
> the _IP suffix.
> 
> Refer to the Intel SDM for more information about PEBS via PT.

In these cases would be nice to provide an URL and page number, for
convenience.

- Arnaldo
 
> Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
> packets only occur in the context of a block (i.e. between BBP and BEP),
> that context must be recorded and passed to the packet decoder.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  .../util/intel-pt-decoder/intel-pt-decoder.c  |  38 ++++-
>  .../intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 +++++++++++++++++-
>  .../intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 ++-
>  tools/perf/util/intel-pt.c                    |   3 +-
>  4 files changed, 193 insertions(+), 9 deletions(-)
> 
> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> index 9eb778f9c911..44218f9cf16a 100644
> --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> @@ -140,6 +140,7 @@ struct intel_pt_decoder {
>  	int mtc_shift;
>  	struct intel_pt_stack stack;
>  	enum intel_pt_pkt_state pkt_state;
> +	enum intel_pt_pkt_ctx pkt_ctx;
>  	struct intel_pt_pkt packet;
>  	struct intel_pt_pkt tnt;
>  	int pkt_step;
> @@ -558,7 +559,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
>  	memcpy(buf + len, decoder->buf, n);
>  	len += n;
>  
> -	ret = intel_pt_get_packet(buf, len, &decoder->packet);
> +	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
>  	if (ret < (int)old_len) {
>  		decoder->next_buf = decoder->buf;
>  		decoder->next_len = decoder->len;
> @@ -593,6 +594,7 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
>  {
>  	struct intel_pt_pkt_info pkt_info;
>  	const unsigned char *buf = decoder->buf;
> +	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
>  	size_t len = decoder->len;
>  	int ret;
>  
> @@ -611,7 +613,8 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
>  			if (!len)
>  				return INTEL_PT_NEED_MORE_BYTES;
>  
> -			ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
> +			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
> +						  &pkt_ctx);
>  			if (!ret)
>  				return INTEL_PT_NEED_MORE_BYTES;
>  			if (ret < 0)
> @@ -686,6 +689,10 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
>  	case INTEL_PT_MNT:
>  	case INTEL_PT_PTWRITE:
>  	case INTEL_PT_PTWRITE_IP:
> +	case INTEL_PT_BBP:
> +	case INTEL_PT_BIP:
> +	case INTEL_PT_BEP:
> +	case INTEL_PT_BEP_IP:
>  		return 0;
>  
>  	case INTEL_PT_MTC:
> @@ -878,7 +885,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
>  		}
>  
>  		ret = intel_pt_get_packet(decoder->buf, decoder->len,
> -					  &decoder->packet);
> +					  &decoder->packet, &decoder->pkt_ctx);
>  		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
>  		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
>  			ret = intel_pt_get_split_packet(decoder);
> @@ -1624,6 +1631,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
>  		case INTEL_PT_MWAIT:
>  		case INTEL_PT_PWRE:
>  		case INTEL_PT_PWRX:
> +		case INTEL_PT_BBP:
> +		case INTEL_PT_BIP:
> +		case INTEL_PT_BEP:
> +		case INTEL_PT_BEP_IP:
>  			decoder->have_tma = false;
>  			intel_pt_log("ERROR: Unexpected packet\n");
>  			err = -EAGAIN;
> @@ -1717,6 +1728,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
>  		case INTEL_PT_MWAIT:
>  		case INTEL_PT_PWRE:
>  		case INTEL_PT_PWRX:
> +		case INTEL_PT_BBP:
> +		case INTEL_PT_BIP:
> +		case INTEL_PT_BEP:
> +		case INTEL_PT_BEP_IP:
>  			intel_pt_log("ERROR: Missing TIP after FUP\n");
>  			decoder->pkt_state = INTEL_PT_STATE_ERR3;
>  			decoder->pkt_step = 0;
> @@ -2038,6 +2053,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
>  			decoder->state.pwrx_payload = decoder->packet.payload;
>  			return 0;
>  
> +		case INTEL_PT_BBP:
> +		case INTEL_PT_BIP:
> +		case INTEL_PT_BEP:
> +		case INTEL_PT_BEP_IP:
> +			break;
> +
>  		default:
>  			return intel_pt_bug(decoder);
>  		}
> @@ -2076,6 +2097,10 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
>  		case INTEL_PT_MWAIT:
>  		case INTEL_PT_PWRE:
>  		case INTEL_PT_PWRX:
> +		case INTEL_PT_BBP:
> +		case INTEL_PT_BIP:
> +		case INTEL_PT_BEP:
> +		case INTEL_PT_BEP_IP:
>  			intel_pt_log("ERROR: Unexpected packet\n");
>  			err = -ENOENT;
>  			goto out;
> @@ -2282,6 +2307,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
>  		case INTEL_PT_MWAIT:
>  		case INTEL_PT_PWRE:
>  		case INTEL_PT_PWRX:
> +		case INTEL_PT_BBP:
> +		case INTEL_PT_BIP:
> +		case INTEL_PT_BEP:
> +		case INTEL_PT_BEP_IP:
>  		default:
>  			break;
>  		}
> @@ -2632,11 +2661,12 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
>  static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
>  			      size_t *rem)
>  {
> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
>  	struct intel_pt_pkt packet;
>  	int ret;
>  
>  	while (len) {
> -		ret = intel_pt_get_packet(buf, len, &packet);
> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
>  		if (ret <= 0)
>  			return false;
>  		if (packet.type == INTEL_PT_TSC) {
> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> index d426761a549d..2b2793b339c0 100644
> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> @@ -71,6 +71,10 @@ static const char * const packet_name[] = {
>  	[INTEL_PT_MWAIT]	= "MWAIT",
>  	[INTEL_PT_PWRE]		= "PWRE",
>  	[INTEL_PT_PWRX]		= "PWRX",
> +	[INTEL_PT_BBP]		= "BBP",
> +	[INTEL_PT_BIP]		= "BIP",
> +	[INTEL_PT_BEP]		= "BEP",
> +	[INTEL_PT_BEP_IP]	= "BEP",
>  };
>  
>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
> @@ -289,6 +293,55 @@ static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
>  	return 7;
>  }
>  
> +static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
> +			    struct intel_pt_pkt *packet)
> +{
> +	if (len < 3)
> +		return INTEL_PT_NEED_MORE_BYTES;
> +	packet->type = INTEL_PT_BBP;
> +	packet->count = buf[2] >> 7;
> +	packet->payload = buf[2] & 0x1f;
> +	return 3;
> +}
> +
> +static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
> +			      struct intel_pt_pkt *packet)
> +{
> +	if (len < 5)
> +		return INTEL_PT_NEED_MORE_BYTES;
> +	packet->type = INTEL_PT_BIP;
> +	packet->count = buf[0] >> 3;
> +	memcpy_le64(&packet->payload, buf + 1, 4);
> +	return 5;
> +}
> +
> +static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
> +			      struct intel_pt_pkt *packet)
> +{
> +	if (len < 9)
> +		return INTEL_PT_NEED_MORE_BYTES;
> +	packet->type = INTEL_PT_BIP;
> +	packet->count = buf[0] >> 3;
> +	memcpy_le64(&packet->payload, buf + 1, 8);
> +	return 9;
> +}
> +
> +static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
> +{
> +	if (len < 2)
> +		return INTEL_PT_NEED_MORE_BYTES;
> +	packet->type = INTEL_PT_BEP;
> +	return 2;
> +}
> +
> +static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
> +{
> +	if (len < 2)
> +		return INTEL_PT_NEED_MORE_BYTES;
> +	packet->type = INTEL_PT_BEP_IP;
> +	return 2;
> +}
> +
>  static int intel_pt_get_ext(const unsigned char *buf, size_t len,
>  			    struct intel_pt_pkt *packet)
>  {
> @@ -329,6 +382,12 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
>  		return intel_pt_get_pwre(buf, len, packet);
>  	case 0xA2: /* PWRX */
>  		return intel_pt_get_pwrx(buf, len, packet);
> +	case 0x63: /* BBP */
> +		return intel_pt_get_bbp(buf, len, packet);
> +	case 0x33: /* BEP no IP */
> +		return intel_pt_get_bep(len, packet);
> +	case 0xb3: /* BEP with IP */
> +		return intel_pt_get_bep_ip(len, packet);
>  	default:
>  		return INTEL_PT_BAD_PACKET;
>  	}
> @@ -477,7 +536,8 @@ static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
>  }
>  
>  static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
> -				  struct intel_pt_pkt *packet)
> +				  struct intel_pt_pkt *packet,
> +				  enum intel_pt_pkt_ctx ctx)
>  {
>  	unsigned int byte;
>  
> @@ -487,6 +547,22 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
>  		return INTEL_PT_NEED_MORE_BYTES;
>  
>  	byte = buf[0];
> +
> +	switch (ctx) {
> +	case INTEL_PT_NO_CTX:
> +		break;
> +	case INTEL_PT_BLK_4_CTX:
> +		if ((byte & 0x7) == 4)
> +			return intel_pt_get_bip_4(buf, len, packet);
> +		break;
> +	case INTEL_PT_BLK_8_CTX:
> +		if ((byte & 0x7) == 4)
> +			return intel_pt_get_bip_8(buf, len, packet);
> +		break;
> +	default:
> +		break;
> +	};
> +
>  	if (!(byte & BIT(0))) {
>  		if (byte == 0)
>  			return intel_pt_get_pad(packet);
> @@ -525,15 +601,65 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
>  	}
>  }
>  
> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
> +			  enum intel_pt_pkt_ctx *ctx)
> +{
> +	switch (packet->type) {
> +	case INTEL_PT_BAD:
> +	case INTEL_PT_PAD:
> +	case INTEL_PT_TSC:
> +	case INTEL_PT_TMA:
> +	case INTEL_PT_MTC:
> +	case INTEL_PT_FUP:
> +	case INTEL_PT_CYC:
> +	case INTEL_PT_CBR:
> +	case INTEL_PT_MNT:
> +	case INTEL_PT_EXSTOP:
> +	case INTEL_PT_EXSTOP_IP:
> +	case INTEL_PT_PWRE:
> +	case INTEL_PT_PWRX:
> +	case INTEL_PT_BIP:
> +		break;
> +	case INTEL_PT_TNT:
> +	case INTEL_PT_TIP:
> +	case INTEL_PT_TIP_PGD:
> +	case INTEL_PT_TIP_PGE:
> +	case INTEL_PT_MODE_EXEC:
> +	case INTEL_PT_MODE_TSX:
> +	case INTEL_PT_PIP:
> +	case INTEL_PT_OVF:
> +	case INTEL_PT_VMCS:
> +	case INTEL_PT_TRACESTOP:
> +	case INTEL_PT_PSB:
> +	case INTEL_PT_PSBEND:
> +	case INTEL_PT_PTWRITE:
> +	case INTEL_PT_PTWRITE_IP:
> +	case INTEL_PT_MWAIT:
> +	case INTEL_PT_BEP:
> +	case INTEL_PT_BEP_IP:
> +		*ctx = INTEL_PT_NO_CTX;
> +		break;
> +	case INTEL_PT_BBP:
> +		if (packet->count)
> +			*ctx = INTEL_PT_BLK_4_CTX;
> +		else
> +			*ctx = INTEL_PT_BLK_8_CTX;
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
> -			struct intel_pt_pkt *packet)
> +			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
>  {
>  	int ret;
>  
> -	ret = intel_pt_do_get_packet(buf, len, packet);
> +	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
>  	if (ret > 0) {
>  		while (ret < 8 && len > (size_t)ret && !buf[ret])
>  			ret += 1;
> +		intel_pt_upd_pkt_ctx(packet, ctx);
>  	}
>  	return ret;
>  }
> @@ -611,8 +737,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
>  		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
>  	case INTEL_PT_PTWRITE_IP:
>  		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
> +	case INTEL_PT_BEP:
>  	case INTEL_PT_EXSTOP:
>  		return snprintf(buf, buf_len, "%s IP:0", name);
> +	case INTEL_PT_BEP_IP:
>  	case INTEL_PT_EXSTOP_IP:
>  		return snprintf(buf, buf_len, "%s IP:1", name);
>  	case INTEL_PT_MWAIT:
> @@ -630,6 +758,12 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
>  				(unsigned int)((payload >> 4) & 0xf),
>  				(unsigned int)(payload & 0xf),
>  				(unsigned int)((payload >> 8) & 0xf));
> +	case INTEL_PT_BBP:
> +		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
> +				name, packet->count ? "4" : "8", payload);
> +	case INTEL_PT_BIP:
> +		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
> +				name, packet->count, payload);
>  	default:
>  		break;
>  	}
> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> index 73ddc3a88d07..682b35282abc 100644
> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> @@ -59,6 +59,10 @@ enum intel_pt_pkt_type {
>  	INTEL_PT_MWAIT,
>  	INTEL_PT_PWRE,
>  	INTEL_PT_PWRX,
> +	INTEL_PT_BBP,
> +	INTEL_PT_BIP,
> +	INTEL_PT_BEP,
> +	INTEL_PT_BEP_IP,
>  };
>  
>  struct intel_pt_pkt {
> @@ -67,10 +71,25 @@ struct intel_pt_pkt {
>  	uint64_t		payload;
>  };
>  
> +/*
> + * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
> + * packets only occur in the context of a block (i.e. between BBP and BEP), that
> + * context must be recorded and passed to the packet decoder.
> + */
> +enum intel_pt_pkt_ctx {
> +	INTEL_PT_NO_CTX,	/* BIP packets are invalid */
> +	INTEL_PT_BLK_4_CTX,	/* 4-byte BIP packets */
> +	INTEL_PT_BLK_8_CTX,	/* 8-byte BIP packets */
> +};
> +
>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type);
>  
>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
> -			struct intel_pt_pkt *packet);
> +			struct intel_pt_pkt *packet,
> +			enum intel_pt_pkt_ctx *ctx);
> +
> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
> +			  enum intel_pt_pkt_ctx *ctx);
>  
>  int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len);
>  
> diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
> index 3cff8fe2eaa0..f43d3ac2db8b 100644
> --- a/tools/perf/util/intel-pt.c
> +++ b/tools/perf/util/intel-pt.c
> @@ -174,13 +174,14 @@ static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
>  	int ret, pkt_len, i;
>  	char desc[INTEL_PT_PKT_DESC_MAX];
>  	const char *color = PERF_COLOR_BLUE;
> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
>  
>  	color_fprintf(stdout, color,
>  		      ". ... Intel Processor Trace data: size %zu bytes\n",
>  		      len);
>  
>  	while (len) {
> -		ret = intel_pt_get_packet(buf, len, &packet);
> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
>  		if (ret > 0)
>  			pkt_len = ret;
>  		else
> -- 
> 2.17.1

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12  0:09   ` Arnaldo Carvalho de Melo
@ 2019-06-12  5:58     ` Adrian Hunter
  2019-06-12 12:41       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-12  5:58 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

On 12/06/19 3:09 AM, Arnaldo Carvalho de Melo wrote:
> Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
>> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
>> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
>> into multiple BIP packets that come between BBP and BEP. The BEP packet
>> might be associated with a FUP packet. That is indicated by using a
>> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
>> the _IP suffix.
>>
>> Refer to the Intel SDM for more information about PEBS via PT.
> 
> In these cases would be nice to provide an URL and page number, for
> convenience.

Intel SDM:

	https://software.intel.com/en-us/articles/intel-sdm

May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace

> 
> - Arnaldo
>  
>> Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
>> packets only occur in the context of a block (i.e. between BBP and BEP),
>> that context must be recorded and passed to the packet decoder.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  .../util/intel-pt-decoder/intel-pt-decoder.c  |  38 ++++-
>>  .../intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 +++++++++++++++++-
>>  .../intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 ++-
>>  tools/perf/util/intel-pt.c                    |   3 +-
>>  4 files changed, 193 insertions(+), 9 deletions(-)
>>
>> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
>> index 9eb778f9c911..44218f9cf16a 100644
>> --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
>> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
>> @@ -140,6 +140,7 @@ struct intel_pt_decoder {
>>  	int mtc_shift;
>>  	struct intel_pt_stack stack;
>>  	enum intel_pt_pkt_state pkt_state;
>> +	enum intel_pt_pkt_ctx pkt_ctx;
>>  	struct intel_pt_pkt packet;
>>  	struct intel_pt_pkt tnt;
>>  	int pkt_step;
>> @@ -558,7 +559,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
>>  	memcpy(buf + len, decoder->buf, n);
>>  	len += n;
>>  
>> -	ret = intel_pt_get_packet(buf, len, &decoder->packet);
>> +	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
>>  	if (ret < (int)old_len) {
>>  		decoder->next_buf = decoder->buf;
>>  		decoder->next_len = decoder->len;
>> @@ -593,6 +594,7 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
>>  {
>>  	struct intel_pt_pkt_info pkt_info;
>>  	const unsigned char *buf = decoder->buf;
>> +	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
>>  	size_t len = decoder->len;
>>  	int ret;
>>  
>> @@ -611,7 +613,8 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
>>  			if (!len)
>>  				return INTEL_PT_NEED_MORE_BYTES;
>>  
>> -			ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
>> +			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
>> +						  &pkt_ctx);
>>  			if (!ret)
>>  				return INTEL_PT_NEED_MORE_BYTES;
>>  			if (ret < 0)
>> @@ -686,6 +689,10 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
>>  	case INTEL_PT_MNT:
>>  	case INTEL_PT_PTWRITE:
>>  	case INTEL_PT_PTWRITE_IP:
>> +	case INTEL_PT_BBP:
>> +	case INTEL_PT_BIP:
>> +	case INTEL_PT_BEP:
>> +	case INTEL_PT_BEP_IP:
>>  		return 0;
>>  
>>  	case INTEL_PT_MTC:
>> @@ -878,7 +885,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
>>  		}
>>  
>>  		ret = intel_pt_get_packet(decoder->buf, decoder->len,
>> -					  &decoder->packet);
>> +					  &decoder->packet, &decoder->pkt_ctx);
>>  		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
>>  		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
>>  			ret = intel_pt_get_split_packet(decoder);
>> @@ -1624,6 +1631,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
>>  		case INTEL_PT_MWAIT:
>>  		case INTEL_PT_PWRE:
>>  		case INTEL_PT_PWRX:
>> +		case INTEL_PT_BBP:
>> +		case INTEL_PT_BIP:
>> +		case INTEL_PT_BEP:
>> +		case INTEL_PT_BEP_IP:
>>  			decoder->have_tma = false;
>>  			intel_pt_log("ERROR: Unexpected packet\n");
>>  			err = -EAGAIN;
>> @@ -1717,6 +1728,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
>>  		case INTEL_PT_MWAIT:
>>  		case INTEL_PT_PWRE:
>>  		case INTEL_PT_PWRX:
>> +		case INTEL_PT_BBP:
>> +		case INTEL_PT_BIP:
>> +		case INTEL_PT_BEP:
>> +		case INTEL_PT_BEP_IP:
>>  			intel_pt_log("ERROR: Missing TIP after FUP\n");
>>  			decoder->pkt_state = INTEL_PT_STATE_ERR3;
>>  			decoder->pkt_step = 0;
>> @@ -2038,6 +2053,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
>>  			decoder->state.pwrx_payload = decoder->packet.payload;
>>  			return 0;
>>  
>> +		case INTEL_PT_BBP:
>> +		case INTEL_PT_BIP:
>> +		case INTEL_PT_BEP:
>> +		case INTEL_PT_BEP_IP:
>> +			break;
>> +
>>  		default:
>>  			return intel_pt_bug(decoder);
>>  		}
>> @@ -2076,6 +2097,10 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
>>  		case INTEL_PT_MWAIT:
>>  		case INTEL_PT_PWRE:
>>  		case INTEL_PT_PWRX:
>> +		case INTEL_PT_BBP:
>> +		case INTEL_PT_BIP:
>> +		case INTEL_PT_BEP:
>> +		case INTEL_PT_BEP_IP:
>>  			intel_pt_log("ERROR: Unexpected packet\n");
>>  			err = -ENOENT;
>>  			goto out;
>> @@ -2282,6 +2307,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
>>  		case INTEL_PT_MWAIT:
>>  		case INTEL_PT_PWRE:
>>  		case INTEL_PT_PWRX:
>> +		case INTEL_PT_BBP:
>> +		case INTEL_PT_BIP:
>> +		case INTEL_PT_BEP:
>> +		case INTEL_PT_BEP_IP:
>>  		default:
>>  			break;
>>  		}
>> @@ -2632,11 +2661,12 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
>>  static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
>>  			      size_t *rem)
>>  {
>> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
>>  	struct intel_pt_pkt packet;
>>  	int ret;
>>  
>>  	while (len) {
>> -		ret = intel_pt_get_packet(buf, len, &packet);
>> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
>>  		if (ret <= 0)
>>  			return false;
>>  		if (packet.type == INTEL_PT_TSC) {
>> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
>> index d426761a549d..2b2793b339c0 100644
>> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
>> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
>> @@ -71,6 +71,10 @@ static const char * const packet_name[] = {
>>  	[INTEL_PT_MWAIT]	= "MWAIT",
>>  	[INTEL_PT_PWRE]		= "PWRE",
>>  	[INTEL_PT_PWRX]		= "PWRX",
>> +	[INTEL_PT_BBP]		= "BBP",
>> +	[INTEL_PT_BIP]		= "BIP",
>> +	[INTEL_PT_BEP]		= "BEP",
>> +	[INTEL_PT_BEP_IP]	= "BEP",
>>  };
>>  
>>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
>> @@ -289,6 +293,55 @@ static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
>>  	return 7;
>>  }
>>  
>> +static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
>> +			    struct intel_pt_pkt *packet)
>> +{
>> +	if (len < 3)
>> +		return INTEL_PT_NEED_MORE_BYTES;
>> +	packet->type = INTEL_PT_BBP;
>> +	packet->count = buf[2] >> 7;
>> +	packet->payload = buf[2] & 0x1f;
>> +	return 3;
>> +}
>> +
>> +static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
>> +			      struct intel_pt_pkt *packet)
>> +{
>> +	if (len < 5)
>> +		return INTEL_PT_NEED_MORE_BYTES;
>> +	packet->type = INTEL_PT_BIP;
>> +	packet->count = buf[0] >> 3;
>> +	memcpy_le64(&packet->payload, buf + 1, 4);
>> +	return 5;
>> +}
>> +
>> +static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
>> +			      struct intel_pt_pkt *packet)
>> +{
>> +	if (len < 9)
>> +		return INTEL_PT_NEED_MORE_BYTES;
>> +	packet->type = INTEL_PT_BIP;
>> +	packet->count = buf[0] >> 3;
>> +	memcpy_le64(&packet->payload, buf + 1, 8);
>> +	return 9;
>> +}
>> +
>> +static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
>> +{
>> +	if (len < 2)
>> +		return INTEL_PT_NEED_MORE_BYTES;
>> +	packet->type = INTEL_PT_BEP;
>> +	return 2;
>> +}
>> +
>> +static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
>> +{
>> +	if (len < 2)
>> +		return INTEL_PT_NEED_MORE_BYTES;
>> +	packet->type = INTEL_PT_BEP_IP;
>> +	return 2;
>> +}
>> +
>>  static int intel_pt_get_ext(const unsigned char *buf, size_t len,
>>  			    struct intel_pt_pkt *packet)
>>  {
>> @@ -329,6 +382,12 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
>>  		return intel_pt_get_pwre(buf, len, packet);
>>  	case 0xA2: /* PWRX */
>>  		return intel_pt_get_pwrx(buf, len, packet);
>> +	case 0x63: /* BBP */
>> +		return intel_pt_get_bbp(buf, len, packet);
>> +	case 0x33: /* BEP no IP */
>> +		return intel_pt_get_bep(len, packet);
>> +	case 0xb3: /* BEP with IP */
>> +		return intel_pt_get_bep_ip(len, packet);
>>  	default:
>>  		return INTEL_PT_BAD_PACKET;
>>  	}
>> @@ -477,7 +536,8 @@ static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
>>  }
>>  
>>  static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
>> -				  struct intel_pt_pkt *packet)
>> +				  struct intel_pt_pkt *packet,
>> +				  enum intel_pt_pkt_ctx ctx)
>>  {
>>  	unsigned int byte;
>>  
>> @@ -487,6 +547,22 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
>>  		return INTEL_PT_NEED_MORE_BYTES;
>>  
>>  	byte = buf[0];
>> +
>> +	switch (ctx) {
>> +	case INTEL_PT_NO_CTX:
>> +		break;
>> +	case INTEL_PT_BLK_4_CTX:
>> +		if ((byte & 0x7) == 4)
>> +			return intel_pt_get_bip_4(buf, len, packet);
>> +		break;
>> +	case INTEL_PT_BLK_8_CTX:
>> +		if ((byte & 0x7) == 4)
>> +			return intel_pt_get_bip_8(buf, len, packet);
>> +		break;
>> +	default:
>> +		break;
>> +	};
>> +
>>  	if (!(byte & BIT(0))) {
>>  		if (byte == 0)
>>  			return intel_pt_get_pad(packet);
>> @@ -525,15 +601,65 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
>>  	}
>>  }
>>  
>> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
>> +			  enum intel_pt_pkt_ctx *ctx)
>> +{
>> +	switch (packet->type) {
>> +	case INTEL_PT_BAD:
>> +	case INTEL_PT_PAD:
>> +	case INTEL_PT_TSC:
>> +	case INTEL_PT_TMA:
>> +	case INTEL_PT_MTC:
>> +	case INTEL_PT_FUP:
>> +	case INTEL_PT_CYC:
>> +	case INTEL_PT_CBR:
>> +	case INTEL_PT_MNT:
>> +	case INTEL_PT_EXSTOP:
>> +	case INTEL_PT_EXSTOP_IP:
>> +	case INTEL_PT_PWRE:
>> +	case INTEL_PT_PWRX:
>> +	case INTEL_PT_BIP:
>> +		break;
>> +	case INTEL_PT_TNT:
>> +	case INTEL_PT_TIP:
>> +	case INTEL_PT_TIP_PGD:
>> +	case INTEL_PT_TIP_PGE:
>> +	case INTEL_PT_MODE_EXEC:
>> +	case INTEL_PT_MODE_TSX:
>> +	case INTEL_PT_PIP:
>> +	case INTEL_PT_OVF:
>> +	case INTEL_PT_VMCS:
>> +	case INTEL_PT_TRACESTOP:
>> +	case INTEL_PT_PSB:
>> +	case INTEL_PT_PSBEND:
>> +	case INTEL_PT_PTWRITE:
>> +	case INTEL_PT_PTWRITE_IP:
>> +	case INTEL_PT_MWAIT:
>> +	case INTEL_PT_BEP:
>> +	case INTEL_PT_BEP_IP:
>> +		*ctx = INTEL_PT_NO_CTX;
>> +		break;
>> +	case INTEL_PT_BBP:
>> +		if (packet->count)
>> +			*ctx = INTEL_PT_BLK_4_CTX;
>> +		else
>> +			*ctx = INTEL_PT_BLK_8_CTX;
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +}
>> +
>>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
>> -			struct intel_pt_pkt *packet)
>> +			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
>>  {
>>  	int ret;
>>  
>> -	ret = intel_pt_do_get_packet(buf, len, packet);
>> +	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
>>  	if (ret > 0) {
>>  		while (ret < 8 && len > (size_t)ret && !buf[ret])
>>  			ret += 1;
>> +		intel_pt_upd_pkt_ctx(packet, ctx);
>>  	}
>>  	return ret;
>>  }
>> @@ -611,8 +737,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
>>  		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
>>  	case INTEL_PT_PTWRITE_IP:
>>  		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
>> +	case INTEL_PT_BEP:
>>  	case INTEL_PT_EXSTOP:
>>  		return snprintf(buf, buf_len, "%s IP:0", name);
>> +	case INTEL_PT_BEP_IP:
>>  	case INTEL_PT_EXSTOP_IP:
>>  		return snprintf(buf, buf_len, "%s IP:1", name);
>>  	case INTEL_PT_MWAIT:
>> @@ -630,6 +758,12 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
>>  				(unsigned int)((payload >> 4) & 0xf),
>>  				(unsigned int)(payload & 0xf),
>>  				(unsigned int)((payload >> 8) & 0xf));
>> +	case INTEL_PT_BBP:
>> +		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
>> +				name, packet->count ? "4" : "8", payload);
>> +	case INTEL_PT_BIP:
>> +		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
>> +				name, packet->count, payload);
>>  	default:
>>  		break;
>>  	}
>> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
>> index 73ddc3a88d07..682b35282abc 100644
>> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
>> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
>> @@ -59,6 +59,10 @@ enum intel_pt_pkt_type {
>>  	INTEL_PT_MWAIT,
>>  	INTEL_PT_PWRE,
>>  	INTEL_PT_PWRX,
>> +	INTEL_PT_BBP,
>> +	INTEL_PT_BIP,
>> +	INTEL_PT_BEP,
>> +	INTEL_PT_BEP_IP,
>>  };
>>  
>>  struct intel_pt_pkt {
>> @@ -67,10 +71,25 @@ struct intel_pt_pkt {
>>  	uint64_t		payload;
>>  };
>>  
>> +/*
>> + * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
>> + * packets only occur in the context of a block (i.e. between BBP and BEP), that
>> + * context must be recorded and passed to the packet decoder.
>> + */
>> +enum intel_pt_pkt_ctx {
>> +	INTEL_PT_NO_CTX,	/* BIP packets are invalid */
>> +	INTEL_PT_BLK_4_CTX,	/* 4-byte BIP packets */
>> +	INTEL_PT_BLK_8_CTX,	/* 8-byte BIP packets */
>> +};
>> +
>>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type);
>>  
>>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
>> -			struct intel_pt_pkt *packet);
>> +			struct intel_pt_pkt *packet,
>> +			enum intel_pt_pkt_ctx *ctx);
>> +
>> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
>> +			  enum intel_pt_pkt_ctx *ctx);
>>  
>>  int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len);
>>  
>> diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
>> index 3cff8fe2eaa0..f43d3ac2db8b 100644
>> --- a/tools/perf/util/intel-pt.c
>> +++ b/tools/perf/util/intel-pt.c
>> @@ -174,13 +174,14 @@ static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
>>  	int ret, pkt_len, i;
>>  	char desc[INTEL_PT_PKT_DESC_MAX];
>>  	const char *color = PERF_COLOR_BLUE;
>> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
>>  
>>  	color_fprintf(stdout, color,
>>  		      ". ... Intel Processor Trace data: size %zu bytes\n",
>>  		      len);
>>  
>>  	while (len) {
>> -		ret = intel_pt_get_packet(buf, len, &packet);
>> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
>>  		if (ret > 0)
>>  			pkt_len = ret;
>>  		else
>> -- 
>> 2.17.1
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12  5:58     ` Adrian Hunter
@ 2019-06-12 12:41       ` Arnaldo Carvalho de Melo
  2019-06-12 12:52         ` Adrian Hunter
  0 siblings, 1 reply; 30+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-06-12 12:41 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel

Em Wed, Jun 12, 2019 at 08:58:00AM +0300, Adrian Hunter escreveu:
> On 12/06/19 3:09 AM, Arnaldo Carvalho de Melo wrote:
> > Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
> >> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
> >> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
> >> into multiple BIP packets that come between BBP and BEP. The BEP packet
> >> might be associated with a FUP packet. That is indicated by using a
> >> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
> >> the _IP suffix.
> >>
> >> Refer to the Intel SDM for more information about PEBS via PT.
> > 
> > In these cases would be nice to provide an URL and page number, for
> > convenience.
> 
> Intel SDM:
> 
> 	https://software.intel.com/en-us/articles/intel-sdm
> 
> May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace

Thanks! I'll add to that cset.

What about the kernel bits?

- Arnaldo
 
> > 
> > - Arnaldo
> >  
> >> Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
> >> packets only occur in the context of a block (i.e. between BBP and BEP),
> >> that context must be recorded and passed to the packet decoder.
> >>
> >> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> >> ---
> >>  .../util/intel-pt-decoder/intel-pt-decoder.c  |  38 ++++-
> >>  .../intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 +++++++++++++++++-
> >>  .../intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 ++-
> >>  tools/perf/util/intel-pt.c                    |   3 +-
> >>  4 files changed, 193 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> >> index 9eb778f9c911..44218f9cf16a 100644
> >> --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> >> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
> >> @@ -140,6 +140,7 @@ struct intel_pt_decoder {
> >>  	int mtc_shift;
> >>  	struct intel_pt_stack stack;
> >>  	enum intel_pt_pkt_state pkt_state;
> >> +	enum intel_pt_pkt_ctx pkt_ctx;
> >>  	struct intel_pt_pkt packet;
> >>  	struct intel_pt_pkt tnt;
> >>  	int pkt_step;
> >> @@ -558,7 +559,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
> >>  	memcpy(buf + len, decoder->buf, n);
> >>  	len += n;
> >>  
> >> -	ret = intel_pt_get_packet(buf, len, &decoder->packet);
> >> +	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
> >>  	if (ret < (int)old_len) {
> >>  		decoder->next_buf = decoder->buf;
> >>  		decoder->next_len = decoder->len;
> >> @@ -593,6 +594,7 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
> >>  {
> >>  	struct intel_pt_pkt_info pkt_info;
> >>  	const unsigned char *buf = decoder->buf;
> >> +	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
> >>  	size_t len = decoder->len;
> >>  	int ret;
> >>  
> >> @@ -611,7 +613,8 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
> >>  			if (!len)
> >>  				return INTEL_PT_NEED_MORE_BYTES;
> >>  
> >> -			ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
> >> +			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
> >> +						  &pkt_ctx);
> >>  			if (!ret)
> >>  				return INTEL_PT_NEED_MORE_BYTES;
> >>  			if (ret < 0)
> >> @@ -686,6 +689,10 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
> >>  	case INTEL_PT_MNT:
> >>  	case INTEL_PT_PTWRITE:
> >>  	case INTEL_PT_PTWRITE_IP:
> >> +	case INTEL_PT_BBP:
> >> +	case INTEL_PT_BIP:
> >> +	case INTEL_PT_BEP:
> >> +	case INTEL_PT_BEP_IP:
> >>  		return 0;
> >>  
> >>  	case INTEL_PT_MTC:
> >> @@ -878,7 +885,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
> >>  		}
> >>  
> >>  		ret = intel_pt_get_packet(decoder->buf, decoder->len,
> >> -					  &decoder->packet);
> >> +					  &decoder->packet, &decoder->pkt_ctx);
> >>  		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
> >>  		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
> >>  			ret = intel_pt_get_split_packet(decoder);
> >> @@ -1624,6 +1631,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
> >>  		case INTEL_PT_MWAIT:
> >>  		case INTEL_PT_PWRE:
> >>  		case INTEL_PT_PWRX:
> >> +		case INTEL_PT_BBP:
> >> +		case INTEL_PT_BIP:
> >> +		case INTEL_PT_BEP:
> >> +		case INTEL_PT_BEP_IP:
> >>  			decoder->have_tma = false;
> >>  			intel_pt_log("ERROR: Unexpected packet\n");
> >>  			err = -EAGAIN;
> >> @@ -1717,6 +1728,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
> >>  		case INTEL_PT_MWAIT:
> >>  		case INTEL_PT_PWRE:
> >>  		case INTEL_PT_PWRX:
> >> +		case INTEL_PT_BBP:
> >> +		case INTEL_PT_BIP:
> >> +		case INTEL_PT_BEP:
> >> +		case INTEL_PT_BEP_IP:
> >>  			intel_pt_log("ERROR: Missing TIP after FUP\n");
> >>  			decoder->pkt_state = INTEL_PT_STATE_ERR3;
> >>  			decoder->pkt_step = 0;
> >> @@ -2038,6 +2053,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
> >>  			decoder->state.pwrx_payload = decoder->packet.payload;
> >>  			return 0;
> >>  
> >> +		case INTEL_PT_BBP:
> >> +		case INTEL_PT_BIP:
> >> +		case INTEL_PT_BEP:
> >> +		case INTEL_PT_BEP_IP:
> >> +			break;
> >> +
> >>  		default:
> >>  			return intel_pt_bug(decoder);
> >>  		}
> >> @@ -2076,6 +2097,10 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
> >>  		case INTEL_PT_MWAIT:
> >>  		case INTEL_PT_PWRE:
> >>  		case INTEL_PT_PWRX:
> >> +		case INTEL_PT_BBP:
> >> +		case INTEL_PT_BIP:
> >> +		case INTEL_PT_BEP:
> >> +		case INTEL_PT_BEP_IP:
> >>  			intel_pt_log("ERROR: Unexpected packet\n");
> >>  			err = -ENOENT;
> >>  			goto out;
> >> @@ -2282,6 +2307,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
> >>  		case INTEL_PT_MWAIT:
> >>  		case INTEL_PT_PWRE:
> >>  		case INTEL_PT_PWRX:
> >> +		case INTEL_PT_BBP:
> >> +		case INTEL_PT_BIP:
> >> +		case INTEL_PT_BEP:
> >> +		case INTEL_PT_BEP_IP:
> >>  		default:
> >>  			break;
> >>  		}
> >> @@ -2632,11 +2661,12 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
> >>  static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
> >>  			      size_t *rem)
> >>  {
> >> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
> >>  	struct intel_pt_pkt packet;
> >>  	int ret;
> >>  
> >>  	while (len) {
> >> -		ret = intel_pt_get_packet(buf, len, &packet);
> >> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
> >>  		if (ret <= 0)
> >>  			return false;
> >>  		if (packet.type == INTEL_PT_TSC) {
> >> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> >> index d426761a549d..2b2793b339c0 100644
> >> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> >> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
> >> @@ -71,6 +71,10 @@ static const char * const packet_name[] = {
> >>  	[INTEL_PT_MWAIT]	= "MWAIT",
> >>  	[INTEL_PT_PWRE]		= "PWRE",
> >>  	[INTEL_PT_PWRX]		= "PWRX",
> >> +	[INTEL_PT_BBP]		= "BBP",
> >> +	[INTEL_PT_BIP]		= "BIP",
> >> +	[INTEL_PT_BEP]		= "BEP",
> >> +	[INTEL_PT_BEP_IP]	= "BEP",
> >>  };
> >>  
> >>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
> >> @@ -289,6 +293,55 @@ static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
> >>  	return 7;
> >>  }
> >>  
> >> +static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
> >> +			    struct intel_pt_pkt *packet)
> >> +{
> >> +	if (len < 3)
> >> +		return INTEL_PT_NEED_MORE_BYTES;
> >> +	packet->type = INTEL_PT_BBP;
> >> +	packet->count = buf[2] >> 7;
> >> +	packet->payload = buf[2] & 0x1f;
> >> +	return 3;
> >> +}
> >> +
> >> +static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
> >> +			      struct intel_pt_pkt *packet)
> >> +{
> >> +	if (len < 5)
> >> +		return INTEL_PT_NEED_MORE_BYTES;
> >> +	packet->type = INTEL_PT_BIP;
> >> +	packet->count = buf[0] >> 3;
> >> +	memcpy_le64(&packet->payload, buf + 1, 4);
> >> +	return 5;
> >> +}
> >> +
> >> +static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
> >> +			      struct intel_pt_pkt *packet)
> >> +{
> >> +	if (len < 9)
> >> +		return INTEL_PT_NEED_MORE_BYTES;
> >> +	packet->type = INTEL_PT_BIP;
> >> +	packet->count = buf[0] >> 3;
> >> +	memcpy_le64(&packet->payload, buf + 1, 8);
> >> +	return 9;
> >> +}
> >> +
> >> +static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
> >> +{
> >> +	if (len < 2)
> >> +		return INTEL_PT_NEED_MORE_BYTES;
> >> +	packet->type = INTEL_PT_BEP;
> >> +	return 2;
> >> +}
> >> +
> >> +static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
> >> +{
> >> +	if (len < 2)
> >> +		return INTEL_PT_NEED_MORE_BYTES;
> >> +	packet->type = INTEL_PT_BEP_IP;
> >> +	return 2;
> >> +}
> >> +
> >>  static int intel_pt_get_ext(const unsigned char *buf, size_t len,
> >>  			    struct intel_pt_pkt *packet)
> >>  {
> >> @@ -329,6 +382,12 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
> >>  		return intel_pt_get_pwre(buf, len, packet);
> >>  	case 0xA2: /* PWRX */
> >>  		return intel_pt_get_pwrx(buf, len, packet);
> >> +	case 0x63: /* BBP */
> >> +		return intel_pt_get_bbp(buf, len, packet);
> >> +	case 0x33: /* BEP no IP */
> >> +		return intel_pt_get_bep(len, packet);
> >> +	case 0xb3: /* BEP with IP */
> >> +		return intel_pt_get_bep_ip(len, packet);
> >>  	default:
> >>  		return INTEL_PT_BAD_PACKET;
> >>  	}
> >> @@ -477,7 +536,8 @@ static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
> >>  }
> >>  
> >>  static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
> >> -				  struct intel_pt_pkt *packet)
> >> +				  struct intel_pt_pkt *packet,
> >> +				  enum intel_pt_pkt_ctx ctx)
> >>  {
> >>  	unsigned int byte;
> >>  
> >> @@ -487,6 +547,22 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
> >>  		return INTEL_PT_NEED_MORE_BYTES;
> >>  
> >>  	byte = buf[0];
> >> +
> >> +	switch (ctx) {
> >> +	case INTEL_PT_NO_CTX:
> >> +		break;
> >> +	case INTEL_PT_BLK_4_CTX:
> >> +		if ((byte & 0x7) == 4)
> >> +			return intel_pt_get_bip_4(buf, len, packet);
> >> +		break;
> >> +	case INTEL_PT_BLK_8_CTX:
> >> +		if ((byte & 0x7) == 4)
> >> +			return intel_pt_get_bip_8(buf, len, packet);
> >> +		break;
> >> +	default:
> >> +		break;
> >> +	};
> >> +
> >>  	if (!(byte & BIT(0))) {
> >>  		if (byte == 0)
> >>  			return intel_pt_get_pad(packet);
> >> @@ -525,15 +601,65 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
> >>  	}
> >>  }
> >>  
> >> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
> >> +			  enum intel_pt_pkt_ctx *ctx)
> >> +{
> >> +	switch (packet->type) {
> >> +	case INTEL_PT_BAD:
> >> +	case INTEL_PT_PAD:
> >> +	case INTEL_PT_TSC:
> >> +	case INTEL_PT_TMA:
> >> +	case INTEL_PT_MTC:
> >> +	case INTEL_PT_FUP:
> >> +	case INTEL_PT_CYC:
> >> +	case INTEL_PT_CBR:
> >> +	case INTEL_PT_MNT:
> >> +	case INTEL_PT_EXSTOP:
> >> +	case INTEL_PT_EXSTOP_IP:
> >> +	case INTEL_PT_PWRE:
> >> +	case INTEL_PT_PWRX:
> >> +	case INTEL_PT_BIP:
> >> +		break;
> >> +	case INTEL_PT_TNT:
> >> +	case INTEL_PT_TIP:
> >> +	case INTEL_PT_TIP_PGD:
> >> +	case INTEL_PT_TIP_PGE:
> >> +	case INTEL_PT_MODE_EXEC:
> >> +	case INTEL_PT_MODE_TSX:
> >> +	case INTEL_PT_PIP:
> >> +	case INTEL_PT_OVF:
> >> +	case INTEL_PT_VMCS:
> >> +	case INTEL_PT_TRACESTOP:
> >> +	case INTEL_PT_PSB:
> >> +	case INTEL_PT_PSBEND:
> >> +	case INTEL_PT_PTWRITE:
> >> +	case INTEL_PT_PTWRITE_IP:
> >> +	case INTEL_PT_MWAIT:
> >> +	case INTEL_PT_BEP:
> >> +	case INTEL_PT_BEP_IP:
> >> +		*ctx = INTEL_PT_NO_CTX;
> >> +		break;
> >> +	case INTEL_PT_BBP:
> >> +		if (packet->count)
> >> +			*ctx = INTEL_PT_BLK_4_CTX;
> >> +		else
> >> +			*ctx = INTEL_PT_BLK_8_CTX;
> >> +		break;
> >> +	default:
> >> +		break;
> >> +	}
> >> +}
> >> +
> >>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
> >> -			struct intel_pt_pkt *packet)
> >> +			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
> >>  {
> >>  	int ret;
> >>  
> >> -	ret = intel_pt_do_get_packet(buf, len, packet);
> >> +	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
> >>  	if (ret > 0) {
> >>  		while (ret < 8 && len > (size_t)ret && !buf[ret])
> >>  			ret += 1;
> >> +		intel_pt_upd_pkt_ctx(packet, ctx);
> >>  	}
> >>  	return ret;
> >>  }
> >> @@ -611,8 +737,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
> >>  		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
> >>  	case INTEL_PT_PTWRITE_IP:
> >>  		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
> >> +	case INTEL_PT_BEP:
> >>  	case INTEL_PT_EXSTOP:
> >>  		return snprintf(buf, buf_len, "%s IP:0", name);
> >> +	case INTEL_PT_BEP_IP:
> >>  	case INTEL_PT_EXSTOP_IP:
> >>  		return snprintf(buf, buf_len, "%s IP:1", name);
> >>  	case INTEL_PT_MWAIT:
> >> @@ -630,6 +758,12 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
> >>  				(unsigned int)((payload >> 4) & 0xf),
> >>  				(unsigned int)(payload & 0xf),
> >>  				(unsigned int)((payload >> 8) & 0xf));
> >> +	case INTEL_PT_BBP:
> >> +		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
> >> +				name, packet->count ? "4" : "8", payload);
> >> +	case INTEL_PT_BIP:
> >> +		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
> >> +				name, packet->count, payload);
> >>  	default:
> >>  		break;
> >>  	}
> >> diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> >> index 73ddc3a88d07..682b35282abc 100644
> >> --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> >> +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
> >> @@ -59,6 +59,10 @@ enum intel_pt_pkt_type {
> >>  	INTEL_PT_MWAIT,
> >>  	INTEL_PT_PWRE,
> >>  	INTEL_PT_PWRX,
> >> +	INTEL_PT_BBP,
> >> +	INTEL_PT_BIP,
> >> +	INTEL_PT_BEP,
> >> +	INTEL_PT_BEP_IP,
> >>  };
> >>  
> >>  struct intel_pt_pkt {
> >> @@ -67,10 +71,25 @@ struct intel_pt_pkt {
> >>  	uint64_t		payload;
> >>  };
> >>  
> >> +/*
> >> + * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
> >> + * packets only occur in the context of a block (i.e. between BBP and BEP), that
> >> + * context must be recorded and passed to the packet decoder.
> >> + */
> >> +enum intel_pt_pkt_ctx {
> >> +	INTEL_PT_NO_CTX,	/* BIP packets are invalid */
> >> +	INTEL_PT_BLK_4_CTX,	/* 4-byte BIP packets */
> >> +	INTEL_PT_BLK_8_CTX,	/* 8-byte BIP packets */
> >> +};
> >> +
> >>  const char *intel_pt_pkt_name(enum intel_pt_pkt_type);
> >>  
> >>  int intel_pt_get_packet(const unsigned char *buf, size_t len,
> >> -			struct intel_pt_pkt *packet);
> >> +			struct intel_pt_pkt *packet,
> >> +			enum intel_pt_pkt_ctx *ctx);
> >> +
> >> +void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
> >> +			  enum intel_pt_pkt_ctx *ctx);
> >>  
> >>  int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len);
> >>  
> >> diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
> >> index 3cff8fe2eaa0..f43d3ac2db8b 100644
> >> --- a/tools/perf/util/intel-pt.c
> >> +++ b/tools/perf/util/intel-pt.c
> >> @@ -174,13 +174,14 @@ static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
> >>  	int ret, pkt_len, i;
> >>  	char desc[INTEL_PT_PKT_DESC_MAX];
> >>  	const char *color = PERF_COLOR_BLUE;
> >> +	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
> >>  
> >>  	color_fprintf(stdout, color,
> >>  		      ". ... Intel Processor Trace data: size %zu bytes\n",
> >>  		      len);
> >>  
> >>  	while (len) {
> >> -		ret = intel_pt_get_packet(buf, len, &packet);
> >> +		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
> >>  		if (ret > 0)
> >>  			pkt_len = ret;
> >>  		else
> >> -- 
> >> 2.17.1
> > 

-- 

- Arnaldo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12 12:41       ` Arnaldo Carvalho de Melo
@ 2019-06-12 12:52         ` Adrian Hunter
  2019-06-12 13:28           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 30+ messages in thread
From: Adrian Hunter @ 2019-06-12 12:52 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Jiri Olsa, linux-kernel

On 12/06/19 3:41 PM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jun 12, 2019 at 08:58:00AM +0300, Adrian Hunter escreveu:
>> On 12/06/19 3:09 AM, Arnaldo Carvalho de Melo wrote:
>>> Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
>>>> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
>>>> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
>>>> into multiple BIP packets that come between BBP and BEP. The BEP packet
>>>> might be associated with a FUP packet. That is indicated by using a
>>>> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
>>>> the _IP suffix.
>>>>
>>>> Refer to the Intel SDM for more information about PEBS via PT.
>>>
>>> In these cases would be nice to provide an URL and page number, for
>>> convenience.
>>
>> Intel SDM:
>>
>> 	https://software.intel.com/en-us/articles/intel-sdm
>>
>> May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace
> 
> Thanks! I'll add to that cset.
> 
> What about the kernel bits?

Awaiting V2, here is a link to the patches:

	https://lore.kernel.org/lkml/20190502105022.15534-1-alexander.shishkin@linux.intel.com/

There is also still a few more tools changes dependent upon the kernel patches.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12 12:52         ` Adrian Hunter
@ 2019-06-12 13:28           ` Arnaldo Carvalho de Melo
  2019-06-13  8:13             ` Adrian Hunter
  2019-07-04 16:10             ` Alexander Shishkin
  0 siblings, 2 replies; 30+ messages in thread
From: Arnaldo Carvalho de Melo @ 2019-06-12 13:28 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Peter Zijlstra, Alexander Shishkin

Em Wed, Jun 12, 2019 at 03:52:11PM +0300, Adrian Hunter escreveu:
> On 12/06/19 3:41 PM, Arnaldo Carvalho de Melo wrote:
> > Em Wed, Jun 12, 2019 at 08:58:00AM +0300, Adrian Hunter escreveu:
> >> On 12/06/19 3:09 AM, Arnaldo Carvalho de Melo wrote:
> >>> Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
> >>>> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
> >>>> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
> >>>> into multiple BIP packets that come between BBP and BEP. The BEP packet
> >>>> might be associated with a FUP packet. That is indicated by using a
> >>>> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
> >>>> the _IP suffix.
> >>>>
> >>>> Refer to the Intel SDM for more information about PEBS via PT.
> >>>
> >>> In these cases would be nice to provide an URL and page number, for
> >>> convenience.
> >>
> >> Intel SDM:
> >>
> >> 	https://software.intel.com/en-us/articles/intel-sdm
> >>
> >> May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace
> > 
> > Thanks! I'll add to that cset.
> > 
> > What about the kernel bits?
> 
> Awaiting V2, here is a link to the patches:
> 
> 	https://lore.kernel.org/lkml/20190502105022.15534-1-alexander.shishkin@linux.intel.com/

yeah, I saw those and PeterZ's comments, that is why I asked about them
:-)
 
> There is also still a few more tools changes dependent upon the kernel patches.

But I think I can go ahead and push the decoder bits, when the kernel
patches get merged we'll be almost ready to make full use of what it
provides, right?

- Arnaldo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12 13:28           ` Arnaldo Carvalho de Melo
@ 2019-06-13  8:13             ` Adrian Hunter
  2019-07-04 16:10             ` Alexander Shishkin
  1 sibling, 0 replies; 30+ messages in thread
From: Adrian Hunter @ 2019-06-13  8:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, linux-kernel, Peter Zijlstra, Alexander Shishkin

On 12/06/19 4:28 PM, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jun 12, 2019 at 03:52:11PM +0300, Adrian Hunter escreveu:
>> On 12/06/19 3:41 PM, Arnaldo Carvalho de Melo wrote:
>>> Em Wed, Jun 12, 2019 at 08:58:00AM +0300, Adrian Hunter escreveu:
>>>> On 12/06/19 3:09 AM, Arnaldo Carvalho de Melo wrote:
>>>>> Em Mon, Jun 10, 2019 at 10:27:53AM +0300, Adrian Hunter escreveu:
>>>>>> Add 3 new packets to supports PEBS via PT, namely Block Begin Packet (BBP),
>>>>>> Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is encoded
>>>>>> into multiple BIP packets that come between BBP and BEP. The BEP packet
>>>>>> might be associated with a FUP packet. That is indicated by using a
>>>>>> separate packet type (INTEL_PT_BEP_IP) similar to other packets types with
>>>>>> the _IP suffix.
>>>>>>
>>>>>> Refer to the Intel SDM for more information about PEBS via PT.
>>>>>
>>>>> In these cases would be nice to provide an URL and page number, for
>>>>> convenience.
>>>>
>>>> Intel SDM:
>>>>
>>>> 	https://software.intel.com/en-us/articles/intel-sdm
>>>>
>>>> May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace
>>>
>>> Thanks! I'll add to that cset.
>>>
>>> What about the kernel bits?
>>
>> Awaiting V2, here is a link to the patches:
>>
>> 	https://lore.kernel.org/lkml/20190502105022.15534-1-alexander.shishkin@linux.intel.com/
> 
> yeah, I saw those and PeterZ's comments, that is why I asked about them
> :-)
>  
>> There is also still a few more tools changes dependent upon the kernel patches.
> 
> But I think I can go ahead and push the decoder bits, when the kernel
> patches get merged we'll be almost ready to make full use of what it
> provides, right?

Yes



^ permalink raw reply	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add new packets for PEBS via PT
  2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
  2019-06-12  0:09   ` Arnaldo Carvalho de Melo
@ 2019-06-22  6:35   ` tip-bot for Adrian Hunter
  1 sibling, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:35 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, adrian.hunter, tglx, acme, mingo, jolsa

Commit-ID:  edff7809c80f09398783d602c33a507309c23e24
Gitweb:     https://git.kernel.org/tip/edff7809c80f09398783d602c33a507309c23e24
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:53 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:17 -0300

perf intel-pt: Add new packets for PEBS via PT

Add 3 new packets to supports PEBS via PT, namely Block Begin Packet
(BBP), Block Item Packet (BIP) and Block End Packet (BEP). PEBS data is
encoded into multiple BIP packets that come between BBP and BEP. The BEP
packet might be associated with a FUP packet. That is indicated by using
a separate packet type (INTEL_PT_BEP_IP) similar to other packets types
with the _IP suffix.

Refer to the Intel SDM for more information about PEBS via PT:

  https://software.intel.com/en-us/articles/intel-sdm
  May 2019 version: Vol. 3B 18.5.5.2 PEBS output to Intel® Processor Trace

Decoding of BIP packets conflicts with single-byte TNT packets. Since
BIP packets only occur in the context of a block (i.e. between BBP and
BEP), that context must be recorded and passed to the packet decoder.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-2-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  |  38 +++++-
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.c   | 140 ++++++++++++++++++++-
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.h   |  21 +++-
 tools/perf/util/intel-pt.c                         |   3 +-
 4 files changed, 193 insertions(+), 9 deletions(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index f001f4ec4ddf..2f7791d4034f 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -133,6 +133,7 @@ struct intel_pt_decoder {
 	int mtc_shift;
 	struct intel_pt_stack stack;
 	enum intel_pt_pkt_state pkt_state;
+	enum intel_pt_pkt_ctx pkt_ctx;
 	struct intel_pt_pkt packet;
 	struct intel_pt_pkt tnt;
 	int pkt_step;
@@ -559,7 +560,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
 	memcpy(buf + len, decoder->buf, n);
 	len += n;
 
-	ret = intel_pt_get_packet(buf, len, &decoder->packet);
+	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
 	if (ret < (int)old_len) {
 		decoder->next_buf = decoder->buf;
 		decoder->next_len = decoder->len;
@@ -594,6 +595,7 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
 {
 	struct intel_pt_pkt_info pkt_info;
 	const unsigned char *buf = decoder->buf;
+	enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx;
 	size_t len = decoder->len;
 	int ret;
 
@@ -612,7 +614,8 @@ static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
 			if (!len)
 				return INTEL_PT_NEED_MORE_BYTES;
 
-			ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
+			ret = intel_pt_get_packet(buf, len, &pkt_info.packet,
+						  &pkt_ctx);
 			if (!ret)
 				return INTEL_PT_NEED_MORE_BYTES;
 			if (ret < 0)
@@ -687,6 +690,10 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
 	case INTEL_PT_MNT:
 	case INTEL_PT_PTWRITE:
 	case INTEL_PT_PTWRITE_IP:
+	case INTEL_PT_BBP:
+	case INTEL_PT_BIP:
+	case INTEL_PT_BEP:
+	case INTEL_PT_BEP_IP:
 		return 0;
 
 	case INTEL_PT_MTC:
@@ -879,7 +886,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
 		}
 
 		ret = intel_pt_get_packet(decoder->buf, decoder->len,
-					  &decoder->packet);
+					  &decoder->packet, &decoder->pkt_ctx);
 		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
 		    decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) {
 			ret = intel_pt_get_split_packet(decoder);
@@ -1633,6 +1640,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			decoder->have_tma = false;
 			intel_pt_log("ERROR: Unexpected packet\n");
 			err = -EAGAIN;
@@ -1726,6 +1737,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			intel_pt_log("ERROR: Missing TIP after FUP\n");
 			decoder->pkt_state = INTEL_PT_STATE_ERR3;
 			decoder->pkt_step = 0;
@@ -2047,6 +2062,12 @@ next:
 			decoder->state.pwrx_payload = decoder->packet.payload;
 			return 0;
 
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
+			break;
+
 		default:
 			return intel_pt_bug(decoder);
 		}
@@ -2085,6 +2106,10 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 			intel_pt_log("ERROR: Unexpected packet\n");
 			err = -ENOENT;
 			goto out;
@@ -2291,6 +2316,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
 		case INTEL_PT_MWAIT:
 		case INTEL_PT_PWRE:
 		case INTEL_PT_PWRX:
+		case INTEL_PT_BBP:
+		case INTEL_PT_BIP:
+		case INTEL_PT_BEP:
+		case INTEL_PT_BEP_IP:
 		default:
 			break;
 		}
@@ -2641,11 +2670,12 @@ static unsigned char *intel_pt_last_psb(unsigned char *buf, size_t len)
 static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc,
 			      size_t *rem)
 {
+	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
 	struct intel_pt_pkt packet;
 	int ret;
 
 	while (len) {
-		ret = intel_pt_get_packet(buf, len, &packet);
+		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
 		if (ret <= 0)
 			return false;
 		if (packet.type == INTEL_PT_TSC) {
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index 605fce537d80..0ccf10a0bf44 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -62,6 +62,10 @@ static const char * const packet_name[] = {
 	[INTEL_PT_MWAIT]	= "MWAIT",
 	[INTEL_PT_PWRE]		= "PWRE",
 	[INTEL_PT_PWRX]		= "PWRX",
+	[INTEL_PT_BBP]		= "BBP",
+	[INTEL_PT_BIP]		= "BIP",
+	[INTEL_PT_BEP]		= "BEP",
+	[INTEL_PT_BEP_IP]	= "BEP",
 };
 
 const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
@@ -280,6 +284,55 @@ static int intel_pt_get_pwrx(const unsigned char *buf, size_t len,
 	return 7;
 }
 
+static int intel_pt_get_bbp(const unsigned char *buf, size_t len,
+			    struct intel_pt_pkt *packet)
+{
+	if (len < 3)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BBP;
+	packet->count = buf[2] >> 7;
+	packet->payload = buf[2] & 0x1f;
+	return 3;
+}
+
+static int intel_pt_get_bip_4(const unsigned char *buf, size_t len,
+			      struct intel_pt_pkt *packet)
+{
+	if (len < 5)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BIP;
+	packet->count = buf[0] >> 3;
+	memcpy_le64(&packet->payload, buf + 1, 4);
+	return 5;
+}
+
+static int intel_pt_get_bip_8(const unsigned char *buf, size_t len,
+			      struct intel_pt_pkt *packet)
+{
+	if (len < 9)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BIP;
+	packet->count = buf[0] >> 3;
+	memcpy_le64(&packet->payload, buf + 1, 8);
+	return 9;
+}
+
+static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet)
+{
+	if (len < 2)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BEP;
+	return 2;
+}
+
+static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet)
+{
+	if (len < 2)
+		return INTEL_PT_NEED_MORE_BYTES;
+	packet->type = INTEL_PT_BEP_IP;
+	return 2;
+}
+
 static int intel_pt_get_ext(const unsigned char *buf, size_t len,
 			    struct intel_pt_pkt *packet)
 {
@@ -320,6 +373,12 @@ static int intel_pt_get_ext(const unsigned char *buf, size_t len,
 		return intel_pt_get_pwre(buf, len, packet);
 	case 0xA2: /* PWRX */
 		return intel_pt_get_pwrx(buf, len, packet);
+	case 0x63: /* BBP */
+		return intel_pt_get_bbp(buf, len, packet);
+	case 0x33: /* BEP no IP */
+		return intel_pt_get_bep(len, packet);
+	case 0xb3: /* BEP with IP */
+		return intel_pt_get_bep_ip(len, packet);
 	default:
 		return INTEL_PT_BAD_PACKET;
 	}
@@ -468,7 +527,8 @@ static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
 }
 
 static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
-				  struct intel_pt_pkt *packet)
+				  struct intel_pt_pkt *packet,
+				  enum intel_pt_pkt_ctx ctx)
 {
 	unsigned int byte;
 
@@ -478,6 +538,22 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 		return INTEL_PT_NEED_MORE_BYTES;
 
 	byte = buf[0];
+
+	switch (ctx) {
+	case INTEL_PT_NO_CTX:
+		break;
+	case INTEL_PT_BLK_4_CTX:
+		if ((byte & 0x7) == 4)
+			return intel_pt_get_bip_4(buf, len, packet);
+		break;
+	case INTEL_PT_BLK_8_CTX:
+		if ((byte & 0x7) == 4)
+			return intel_pt_get_bip_8(buf, len, packet);
+		break;
+	default:
+		break;
+	};
+
 	if (!(byte & BIT(0))) {
 		if (byte == 0)
 			return intel_pt_get_pad(packet);
@@ -516,15 +592,65 @@ static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 	}
 }
 
+void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
+			  enum intel_pt_pkt_ctx *ctx)
+{
+	switch (packet->type) {
+	case INTEL_PT_BAD:
+	case INTEL_PT_PAD:
+	case INTEL_PT_TSC:
+	case INTEL_PT_TMA:
+	case INTEL_PT_MTC:
+	case INTEL_PT_FUP:
+	case INTEL_PT_CYC:
+	case INTEL_PT_CBR:
+	case INTEL_PT_MNT:
+	case INTEL_PT_EXSTOP:
+	case INTEL_PT_EXSTOP_IP:
+	case INTEL_PT_PWRE:
+	case INTEL_PT_PWRX:
+	case INTEL_PT_BIP:
+		break;
+	case INTEL_PT_TNT:
+	case INTEL_PT_TIP:
+	case INTEL_PT_TIP_PGD:
+	case INTEL_PT_TIP_PGE:
+	case INTEL_PT_MODE_EXEC:
+	case INTEL_PT_MODE_TSX:
+	case INTEL_PT_PIP:
+	case INTEL_PT_OVF:
+	case INTEL_PT_VMCS:
+	case INTEL_PT_TRACESTOP:
+	case INTEL_PT_PSB:
+	case INTEL_PT_PSBEND:
+	case INTEL_PT_PTWRITE:
+	case INTEL_PT_PTWRITE_IP:
+	case INTEL_PT_MWAIT:
+	case INTEL_PT_BEP:
+	case INTEL_PT_BEP_IP:
+		*ctx = INTEL_PT_NO_CTX;
+		break;
+	case INTEL_PT_BBP:
+		if (packet->count)
+			*ctx = INTEL_PT_BLK_4_CTX;
+		else
+			*ctx = INTEL_PT_BLK_8_CTX;
+		break;
+	default:
+		break;
+	}
+}
+
 int intel_pt_get_packet(const unsigned char *buf, size_t len,
-			struct intel_pt_pkt *packet)
+			struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx)
 {
 	int ret;
 
-	ret = intel_pt_do_get_packet(buf, len, packet);
+	ret = intel_pt_do_get_packet(buf, len, packet, *ctx);
 	if (ret > 0) {
 		while (ret < 8 && len > (size_t)ret && !buf[ret])
 			ret += 1;
+		intel_pt_upd_pkt_ctx(packet, ctx);
 	}
 	return ret;
 }
@@ -602,8 +728,10 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 		return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload);
 	case INTEL_PT_PTWRITE_IP:
 		return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload);
+	case INTEL_PT_BEP:
 	case INTEL_PT_EXSTOP:
 		return snprintf(buf, buf_len, "%s IP:0", name);
+	case INTEL_PT_BEP_IP:
 	case INTEL_PT_EXSTOP_IP:
 		return snprintf(buf, buf_len, "%s IP:1", name);
 	case INTEL_PT_MWAIT:
@@ -621,6 +749,12 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 				(unsigned int)((payload >> 4) & 0xf),
 				(unsigned int)(payload & 0xf),
 				(unsigned int)((payload >> 8) & 0xf));
+	case INTEL_PT_BBP:
+		return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx",
+				name, packet->count ? "4" : "8", payload);
+	case INTEL_PT_BIP:
+		return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx",
+				name, packet->count, payload);
 	default:
 		break;
 	}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
index a7aefaa08588..17ca9b56d72f 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.h
@@ -50,6 +50,10 @@ enum intel_pt_pkt_type {
 	INTEL_PT_MWAIT,
 	INTEL_PT_PWRE,
 	INTEL_PT_PWRX,
+	INTEL_PT_BBP,
+	INTEL_PT_BIP,
+	INTEL_PT_BEP,
+	INTEL_PT_BEP_IP,
 };
 
 struct intel_pt_pkt {
@@ -58,10 +62,25 @@ struct intel_pt_pkt {
 	uint64_t		payload;
 };
 
+/*
+ * Decoding of BIP packets conflicts with single-byte TNT packets. Since BIP
+ * packets only occur in the context of a block (i.e. between BBP and BEP), that
+ * context must be recorded and passed to the packet decoder.
+ */
+enum intel_pt_pkt_ctx {
+	INTEL_PT_NO_CTX,	/* BIP packets are invalid */
+	INTEL_PT_BLK_4_CTX,	/* 4-byte BIP packets */
+	INTEL_PT_BLK_8_CTX,	/* 8-byte BIP packets */
+};
+
 const char *intel_pt_pkt_name(enum intel_pt_pkt_type);
 
 int intel_pt_get_packet(const unsigned char *buf, size_t len,
-			struct intel_pt_pkt *packet);
+			struct intel_pt_pkt *packet,
+			enum intel_pt_pkt_ctx *ctx);
+
+void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet,
+			  enum intel_pt_pkt_ctx *ctx);
 
 int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, size_t len);
 
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 8ed51f4e9e30..893cef494a43 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -177,13 +177,14 @@ static void intel_pt_dump(struct intel_pt *pt __maybe_unused,
 	int ret, pkt_len, i;
 	char desc[INTEL_PT_PKT_DESC_MAX];
 	const char *color = PERF_COLOR_BLUE;
+	enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX;
 
 	color_fprintf(stdout, color,
 		      ". ... Intel Processor Trace data: size %zu bytes\n",
 		      len);
 
 	while (len) {
-		ret = intel_pt_get_packet(buf, len, &packet);
+		ret = intel_pt_get_packet(buf, len, &packet, &ctx);
 		if (ret > 0)
 			pkt_len = ret;
 		else

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add Intel PT packet decoder test
  2019-06-10  7:27 ` [PATCH 02/11] perf intel-pt: Add Intel PT packet decoder test Adrian Hunter
@ 2019-06-22  6:36   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:36 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, tglx, jolsa, acme, mingo, hpa, linux-kernel

Commit-ID:  a0db77bf880b8badd2f9ce4da708c69b0b865853
Gitweb:     https://git.kernel.org/tip/a0db77bf880b8badd2f9ce4da708c69b0b865853
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:54 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:17 -0300

perf intel-pt: Add Intel PT packet decoder test

Add Intel PT packet decoder test. This test feeds byte sequences to the
Intel PT packet decoder and checks the results. Changes to the packet
context are also checked.

Committer testing:

  # perf test "Intel PT"
  65: Intel PT packet decoder                               : Ok
  # perf test -v "Intel PT"
  65: Intel PT packet decoder                               :
  --- start ---
  test child forked, pid 6360
  Decoded ok: 00                                                PAD
  Decoded ok: 04                                                TNT N (1)
  Decoded ok: 06                                                TNT T (1)
  Decoded ok: 80                                                TNT NNNNNN (6)
  Decoded ok: fe                                                TNT TTTTTT (6)
  Decoded ok: 02 a3 02 00 00 00 00 00                           TNT N (1)
  Decoded ok: 02 a3 03 00 00 00 00 00                           TNT T (1)
  Decoded ok: 02 a3 00 00 00 00 00 80                           TNT NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN (47)
  Decoded ok: 02 a3 ff ff ff ff ff ff                           TNT TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT (47)
  Decoded ok: 0d                                                TIP no ip
  Decoded ok: 2d 01 02                                          TIP 0x201
  Decoded ok: 4d 01 02 03 04                                    TIP 0x4030201
  Decoded ok: 6d 01 02 03 04 05 06                              TIP 0x60504030201
  Decoded ok: 8d 01 02 03 04 05 06                              TIP 0x60504030201
  Decoded ok: cd 01 02 03 04 05 06 07 08                        TIP 0x807060504030201
  Decoded ok: 11                                                TIP.PGE no ip
  Decoded ok: 31 01 02                                          TIP.PGE 0x201
  Decoded ok: 51 01 02 03 04                                    TIP.PGE 0x4030201
  Decoded ok: 71 01 02 03 04 05 06                              TIP.PGE 0x60504030201
  Decoded ok: 91 01 02 03 04 05 06                              TIP.PGE 0x60504030201
  Decoded ok: d1 01 02 03 04 05 06 07 08                        TIP.PGE 0x807060504030201
  Decoded ok: 01                                                TIP.PGD no ip
  Decoded ok: 21 01 02                                          TIP.PGD 0x201
  Decoded ok: 41 01 02 03 04                                    TIP.PGD 0x4030201
  Decoded ok: 61 01 02 03 04 05 06                              TIP.PGD 0x60504030201
  Decoded ok: 81 01 02 03 04 05 06                              TIP.PGD 0x60504030201
  Decoded ok: c1 01 02 03 04 05 06 07 08                        TIP.PGD 0x807060504030201
  Decoded ok: 1d                                                FUP no ip
  Decoded ok: 3d 01 02                                          FUP 0x201
  Decoded ok: 5d 01 02 03 04                                    FUP 0x4030201
  Decoded ok: 7d 01 02 03 04 05 06                              FUP 0x60504030201
  Decoded ok: 9d 01 02 03 04 05 06                              FUP 0x60504030201
  Decoded ok: dd 01 02 03 04 05 06 07 08                        FUP 0x807060504030201
  Decoded ok: 02 43 02 04 06 08 0a 0c                           PIP 0x60504030201 (NR=0)
  Decoded ok: 02 43 03 04 06 08 0a 0c                           PIP 0x60504030201 (NR=1)
  Decoded ok: 99 00                                             MODE.Exec 16
  Decoded ok: 99 01                                             MODE.Exec 64
  Decoded ok: 99 02                                             MODE.Exec 32
  Decoded ok: 99 20                                             MODE.TSX TXAbort:0 InTX:0
  Decoded ok: 99 21                                             MODE.TSX TXAbort:0 InTX:1
  Decoded ok: 99 22                                             MODE.TSX TXAbort:1 InTX:0
  Decoded ok: 02 83                                             TraceSTOP
  Decoded ok: 02 03 12 00                                       CBR 0x12
  Decoded ok: 19 01 02 03 04 05 06 07                           TSC 0x7060504030201
  Decoded ok: 59 12                                             MTC 0x12
  Decoded ok: 02 73 00 00 00 00 00                              TMA CTC 0x0 FC 0x0
  Decoded ok: 02 73 01 02 00 00 00                              TMA CTC 0x201 FC 0x0
  Decoded ok: 02 73 00 00 00 ff 01                              TMA CTC 0x0 FC 0x1ff
  Decoded ok: 02 73 80 c0 00 ff 01                              TMA CTC 0xc080 FC 0x1ff
  Decoded ok: 03                                                CYC 0x0
  Decoded ok: 0b                                                CYC 0x1
  Decoded ok: fb                                                CYC 0x1f
  Decoded ok: 07 02                                             CYC 0x20
  Decoded ok: ff fe                                             CYC 0xfff
  Decoded ok: 07 01 02                                          CYC 0x1000
  Decoded ok: ff ff fe                                          CYC 0x7ffff
  Decoded ok: 07 01 01 02                                       CYC 0x80000
  Decoded ok: ff ff ff fe                                       CYC 0x3ffffff
  Decoded ok: 07 01 01 01 02                                    CYC 0x4000000
  Decoded ok: ff ff ff ff fe                                    CYC 0x1ffffffff
  Decoded ok: 07 01 01 01 01 02                                 CYC 0x200000000
  Decoded ok: ff ff ff ff ff fe                                 CYC 0xffffffffff
  Decoded ok: 07 01 01 01 01 01 02                              CYC 0x10000000000
  Decoded ok: ff ff ff ff ff ff fe                              CYC 0x7fffffffffff
  Decoded ok: 07 01 01 01 01 01 01 02                           CYC 0x800000000000
  Decoded ok: ff ff ff ff ff ff ff fe                           CYC 0x3fffffffffffff
  Decoded ok: 07 01 01 01 01 01 01 01 02                        CYC 0x40000000000000
  Decoded ok: ff ff ff ff ff ff ff ff fe                        CYC 0x1fffffffffffffff
  Decoded ok: 07 01 01 01 01 01 01 01 01 02                     CYC 0x2000000000000000
  Decoded ok: ff ff ff ff ff ff ff ff ff 0e                     CYC 0xffffffffffffffff
  Decoded ok: 02 c8 01 02 03 04 05                              VMCS 0x504030201
  Decoded ok: 02 f3                                             OVF
  Decoded ok: 02 f3                                             OVF
  Decoded ok: 02 f3                                             OVF
  Decoded ok: 02 82 02 82 02 82 02 82 02 82 02 82 02 82 02 82   PSB
  Decoded ok: 02 82 02 82 02 82 02 82 02 82 02 82 02 82 02 82   PSB
  Decoded ok: 02 82 02 82 02 82 02 82 02 82 02 82 02 82 02 82   PSB
  Decoded ok: 02 23                                             PSBEND
  Decoded ok: 02 c3 88 01 02 03 04 05 06 07 00                  MNT 0x7060504030201
  Decoded ok: 02 12 01 02 03 04                                 PTWRITE 0x4030201 IP:0
  Decoded ok: 02 32 01 02 03 04 05 06 07 08                     PTWRITE 0x807060504030201 IP:0
  Decoded ok: 02 92 01 02 03 04                                 PTWRITE 0x4030201 IP:1
  Decoded ok: 02 b2 01 02 03 04 05 06 07 08                     PTWRITE 0x807060504030201 IP:1
  Decoded ok: 02 62                                             EXSTOP IP:0
  Decoded ok: 02 e2                                             EXSTOP IP:1
  Decoded ok: 02 c2 00 00 00 00 00 00 00 00                     MWAIT 0x0 Hints 0x0 Extensions 0x0
  Decoded ok: 02 c2 01 02 03 04 05 06 07 08                     MWAIT 0x807060504030201 Hints 0x1 Extensions 0x1
  Decoded ok: 02 c2 ff 02 03 04 07 06 07 08                     MWAIT 0x8070607040302ff Hints 0xff Extensions 0x3
  Decoded ok: 02 22 00 00                                       PWRE 0x0 HW:0 CState:0 Sub-CState:0
  Decoded ok: 02 22 01 02                                       PWRE 0x201 HW:0 CState:0 Sub-CState:2
  Decoded ok: 02 22 80 34                                       PWRE 0x3480 HW:1 CState:3 Sub-CState:4
  Decoded ok: 02 22 00 56                                       PWRE 0x5600 HW:0 CState:5 Sub-CState:6
  Decoded ok: 02 a2 00 00 00 00 00                              PWRX 0x0 Last CState:0 Deepest CState:0 Wake Reason 0x0
  Decoded ok: 02 a2 01 02 03 04 05                              PWRX 0x504030201 Last CState:0 Deepest CState:1 Wake Reason 0x2
  Decoded ok: 02 a2 ff ff ff ff ff                              PWRX 0xffffffffff Last CState:15 Deepest CState:15 Wake Reason 0xf
  Decoded ok: 02 63 00                                          BBP SZ 8-byte Type 0x0
  Decoded ok: 02 63 80                                          BBP SZ 4-byte Type 0x0
  Decoded ok: 02 63 1f                                          BBP SZ 8-byte Type 0x1f
  Decoded ok: 02 63 9f                                          BBP SZ 4-byte Type 0x1f
  Decoded ok: 04 00 00 00 00                                    BIP ID 0x00 Value 0x0
  Decoded ok: fc 00 00 00 00                                    BIP ID 0x1f Value 0x0
  Decoded ok: 04 01 02 03 04                                    BIP ID 0x00 Value 0x4030201
  Decoded ok: fc 01 02 03 04                                    BIP ID 0x1f Value 0x4030201
  Decoded ok: 04 00 00 00 00 00 00 00 00                        BIP ID 0x00 Value 0x0
  Decoded ok: fc 00 00 00 00 00 00 00 00                        BIP ID 0x1f Value 0x0
  Decoded ok: 04 01 02 03 04 05 06 07 08                        BIP ID 0x00 Value 0x807060504030201
  Decoded ok: fc 01 02 03 04 05 06 07 08                        BIP ID 0x1f Value 0x807060504030201
  Decoded ok: 02 33                                             BEP IP:0
  Decoded ok: 02 b3                                             BEP IP:1
  Decoded ok: 02 33                                             BEP IP:0
  Decoded ok: 02 b3                                             BEP IP:1
  test child finished with 0
  ---- end ----
  Intel PT packet decoder: Ok
  #

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-3-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/x86/include/arch-tests.h           |   1 +
 tools/perf/arch/x86/tests/Build                    |   2 +-
 tools/perf/arch/x86/tests/arch-tests.c             |   4 +
 .../arch/x86/tests/intel-pt-pkt-decoder-test.c     | 304 +++++++++++++++++++++
 4 files changed, 310 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h
index 613709cfbbd0..c41c5affe4be 100644
--- a/tools/perf/arch/x86/include/arch-tests.h
+++ b/tools/perf/arch/x86/include/arch-tests.h
@@ -9,6 +9,7 @@ struct test;
 int test__rdpmc(struct test *test __maybe_unused, int subtest);
 int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
 int test__insn_x86(struct test *test __maybe_unused, int subtest);
+int test__intel_pt_pkt_decoder(struct test *test, int subtest);
 int test__bp_modify(struct test *test, int subtest);
 
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
index 3d83d0c6982d..2997c506550c 100644
--- a/tools/perf/arch/x86/tests/Build
+++ b/tools/perf/arch/x86/tests/Build
@@ -4,5 +4,5 @@ perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 perf-y += arch-tests.o
 perf-y += rdpmc.o
 perf-y += perf-time-to-tsc.o
-perf-$(CONFIG_AUXTRACE) += insn-x86.o
+perf-$(CONFIG_AUXTRACE) += insn-x86.o intel-pt-pkt-decoder-test.o
 perf-$(CONFIG_X86_64) += bp-modify.o
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c
index d47d3f8e3c8e..6763135aec17 100644
--- a/tools/perf/arch/x86/tests/arch-tests.c
+++ b/tools/perf/arch/x86/tests/arch-tests.c
@@ -23,6 +23,10 @@ struct test arch_tests[] = {
 		.desc = "x86 instruction decoder - new instructions",
 		.func = test__insn_x86,
 	},
+	{
+		.desc = "Intel PT packet decoder",
+		.func = test__intel_pt_pkt_decoder,
+	},
 #endif
 #if defined(__x86_64__)
 	{
diff --git a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
new file mode 100644
index 000000000000..901bf1f449c4
--- /dev/null
+++ b/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <string.h>
+
+#include "intel-pt-decoder/intel-pt-pkt-decoder.h"
+
+#include "debug.h"
+#include "tests/tests.h"
+#include "arch-tests.h"
+
+/**
+ * struct test_data - Test data.
+ * @len: number of bytes to decode
+ * @bytes: bytes to decode
+ * @ctx: packet context to decode
+ * @packet: expected packet
+ * @new_ctx: expected new packet context
+ * @ctx_unchanged: the packet context must not change
+ */
+struct test_data {
+	int len;
+	u8 bytes[INTEL_PT_PKT_MAX_SZ];
+	enum intel_pt_pkt_ctx ctx;
+	struct intel_pt_pkt packet;
+	enum intel_pt_pkt_ctx new_ctx;
+	int ctx_unchanged;
+} data[] = {
+	/* Padding Packet */
+	{1, {0}, 0, {INTEL_PT_PAD, 0, 0}, 0, 1 },
+	/* Short Taken/Not Taken Packet */
+	{1, {4}, 0, {INTEL_PT_TNT, 1, 0}, 0, 0 },
+	{1, {6}, 0, {INTEL_PT_TNT, 1, 0x20ULL << 58}, 0, 0 },
+	{1, {0x80}, 0, {INTEL_PT_TNT, 6, 0}, 0, 0 },
+	{1, {0xfe}, 0, {INTEL_PT_TNT, 6, 0x3fULL << 58}, 0, 0 },
+	/* Long Taken/Not Taken Packet */
+	{8, {0x02, 0xa3, 2}, 0, {INTEL_PT_TNT, 1, 0xa302ULL << 47}, 0, 0 },
+	{8, {0x02, 0xa3, 3}, 0, {INTEL_PT_TNT, 1, 0x1a302ULL << 47}, 0, 0 },
+	{8, {0x02, 0xa3, 0, 0, 0, 0, 0, 0x80}, 0, {INTEL_PT_TNT, 47, 0xa302ULL << 1}, 0, 0 },
+	{8, {0x02, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_TNT, 47, 0xffffffffffffa302ULL << 1}, 0, 0 },
+	/* Target IP Packet */
+	{1, {0x0d}, 0, {INTEL_PT_TIP, 0, 0}, 0, 0 },
+	{3, {0x2d, 1, 2}, 0, {INTEL_PT_TIP, 1, 0x201}, 0, 0 },
+	{5, {0x4d, 1, 2, 3, 4}, 0, {INTEL_PT_TIP, 2, 0x4030201}, 0, 0 },
+	{7, {0x6d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 3, 0x60504030201}, 0, 0 },
+	{7, {0x8d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP, 4, 0x60504030201}, 0, 0 },
+	{9, {0xcd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP, 6, 0x807060504030201}, 0, 0 },
+	/* Packet Generation Enable */
+	{1, {0x11}, 0, {INTEL_PT_TIP_PGE, 0, 0}, 0, 0 },
+	{3, {0x31, 1, 2}, 0, {INTEL_PT_TIP_PGE, 1, 0x201}, 0, 0 },
+	{5, {0x51, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGE, 2, 0x4030201}, 0, 0 },
+	{7, {0x71, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 3, 0x60504030201}, 0, 0 },
+	{7, {0x91, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGE, 4, 0x60504030201}, 0, 0 },
+	{9, {0xd1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGE, 6, 0x807060504030201}, 0, 0 },
+	/* Packet Generation Disable */
+	{1, {0x01}, 0, {INTEL_PT_TIP_PGD, 0, 0}, 0, 0 },
+	{3, {0x21, 1, 2}, 0, {INTEL_PT_TIP_PGD, 1, 0x201}, 0, 0 },
+	{5, {0x41, 1, 2, 3, 4}, 0, {INTEL_PT_TIP_PGD, 2, 0x4030201}, 0, 0 },
+	{7, {0x61, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 3, 0x60504030201}, 0, 0 },
+	{7, {0x81, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_TIP_PGD, 4, 0x60504030201}, 0, 0 },
+	{9, {0xc1, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_TIP_PGD, 6, 0x807060504030201}, 0, 0 },
+	/* Flow Update Packet */
+	{1, {0x1d}, 0, {INTEL_PT_FUP, 0, 0}, 0, 0 },
+	{3, {0x3d, 1, 2}, 0, {INTEL_PT_FUP, 1, 0x201}, 0, 0 },
+	{5, {0x5d, 1, 2, 3, 4}, 0, {INTEL_PT_FUP, 2, 0x4030201}, 0, 0 },
+	{7, {0x7d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 3, 0x60504030201}, 0, 0 },
+	{7, {0x9d, 1, 2, 3, 4, 5, 6}, 0, {INTEL_PT_FUP, 4, 0x60504030201}, 0, 0 },
+	{9, {0xdd, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_FUP, 6, 0x807060504030201}, 0, 0 },
+	/* Paging Information Packet */
+	{8, {0x02, 0x43, 2, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0x60504030201}, 0, 0 },
+	{8, {0x02, 0x43, 3, 4, 6, 8, 10, 12}, 0, {INTEL_PT_PIP, 0, 0x60504030201 | (1ULL << 63)}, 0, 0 },
+	/* Mode Exec Packet */
+	{2, {0x99, 0x00}, 0, {INTEL_PT_MODE_EXEC, 0, 16}, 0, 0 },
+	{2, {0x99, 0x01}, 0, {INTEL_PT_MODE_EXEC, 0, 64}, 0, 0 },
+	{2, {0x99, 0x02}, 0, {INTEL_PT_MODE_EXEC, 0, 32}, 0, 0 },
+	/* Mode TSX Packet */
+	{2, {0x99, 0x20}, 0, {INTEL_PT_MODE_TSX, 0, 0}, 0, 0 },
+	{2, {0x99, 0x21}, 0, {INTEL_PT_MODE_TSX, 0, 1}, 0, 0 },
+	{2, {0x99, 0x22}, 0, {INTEL_PT_MODE_TSX, 0, 2}, 0, 0 },
+	/* Trace Stop Packet */
+	{2, {0x02, 0x83}, 0, {INTEL_PT_TRACESTOP, 0, 0}, 0, 0 },
+	/* Core:Bus Ratio Packet */
+	{4, {0x02, 0x03, 0x12, 0}, 0, {INTEL_PT_CBR, 0, 0x12}, 0, 1 },
+	/* Timestamp Counter Packet */
+	{8, {0x19, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_TSC, 0, 0x7060504030201}, 0, 1 },
+	/* Mini Time Counter Packet */
+	{2, {0x59, 0x12}, 0, {INTEL_PT_MTC, 0, 0x12}, 0, 1 },
+	/* TSC / MTC Alignment Packet */
+	{7, {0x02, 0x73}, 0, {INTEL_PT_TMA, 0, 0}, 0, 1 },
+	{7, {0x02, 0x73, 1, 2}, 0, {INTEL_PT_TMA, 0, 0x201}, 0, 1 },
+	{7, {0x02, 0x73, 0, 0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0}, 0, 1 },
+	{7, {0x02, 0x73, 0x80, 0xc0, 0, 0xff, 1}, 0, {INTEL_PT_TMA, 0x1ff, 0xc080}, 0, 1 },
+	/* Cycle Count Packet */
+	{1, {0x03}, 0, {INTEL_PT_CYC, 0, 0}, 0, 1 },
+	{1, {0x0b}, 0, {INTEL_PT_CYC, 0, 1}, 0, 1 },
+	{1, {0xfb}, 0, {INTEL_PT_CYC, 0, 0x1f}, 0, 1 },
+	{2, {0x07, 2}, 0, {INTEL_PT_CYC, 0, 0x20}, 0, 1 },
+	{2, {0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xfff}, 0, 1 },
+	{3, {0x07, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x1000}, 0, 1 },
+	{3, {0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7ffff}, 0, 1 },
+	{4, {0x07, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x80000}, 0, 1 },
+	{4, {0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3ffffff}, 0, 1 },
+	{5, {0x07, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x4000000}, 0, 1 },
+	{5, {0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1ffffffff}, 0, 1 },
+	{6, {0x07, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x200000000}, 0, 1 },
+	{6, {0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0xffffffffff}, 0, 1 },
+	{7, {0x07, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x10000000000}, 0, 1 },
+	{7, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x7fffffffffff}, 0, 1 },
+	{8, {0x07, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x800000000000}, 0, 1 },
+	{8, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x3fffffffffffff}, 0, 1 },
+	{9, {0x07, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x40000000000000}, 0, 1 },
+	{9, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, 0, {INTEL_PT_CYC, 0, 0x1fffffffffffffff}, 0, 1 },
+	{10, {0x07, 1, 1, 1, 1, 1, 1, 1, 1, 2}, 0, {INTEL_PT_CYC, 0, 0x2000000000000000}, 0, 1 },
+	{10, {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe}, 0, {INTEL_PT_CYC, 0, 0xffffffffffffffff}, 0, 1 },
+	/* Virtual-Machine Control Structure Packet */
+	{7, {0x02, 0xc8, 1, 2, 3, 4, 5}, 0, {INTEL_PT_VMCS, 5, 0x504030201}, 0, 0 },
+	/* Overflow Packet */
+	{2, {0x02, 0xf3}, 0, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	{2, {0x02, 0xf3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	{2, {0x02, 0xf3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_OVF, 0, 0}, 0, 0 },
+	/* Packet Stream Boundary*/
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, 0, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_4_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	{16, {0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82}, INTEL_PT_BLK_8_CTX, {INTEL_PT_PSB, 0, 0}, 0, 0 },
+	/* PSB End Packet */
+	{2, {0x02, 0x23}, 0, {INTEL_PT_PSBEND, 0, 0}, 0, 0 },
+	/* Maintenance Packet */
+	{11, {0x02, 0xc3, 0x88, 1, 2, 3, 4, 5, 6, 7}, 0, {INTEL_PT_MNT, 0, 0x7060504030201}, 0, 1 },
+	/* Write Data to PT Packet */
+	{6, {0x02, 0x12, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE, 0, 0x4030201}, 0, 0 },
+	{10, {0x02, 0x32, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE, 1, 0x807060504030201}, 0, 0 },
+	{6, {0x02, 0x92, 1, 2, 3, 4}, 0, {INTEL_PT_PTWRITE_IP, 0, 0x4030201}, 0, 0 },
+	{10, {0x02, 0xb2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_PTWRITE_IP, 1, 0x807060504030201}, 0, 0 },
+	/* Execution Stop Packet */
+	{2, {0x02, 0x62}, 0, {INTEL_PT_EXSTOP, 0, 0}, 0, 1 },
+	{2, {0x02, 0xe2}, 0, {INTEL_PT_EXSTOP_IP, 0, 0}, 0, 1 },
+	/* Monitor Wait Packet */
+	{10, {0x02, 0xc2}, 0, {INTEL_PT_MWAIT, 0, 0}, 0, 0 },
+	{10, {0x02, 0xc2, 1, 2, 3, 4, 5, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x807060504030201}, 0, 0 },
+	{10, {0x02, 0xc2, 0xff, 2, 3, 4, 7, 6, 7, 8}, 0, {INTEL_PT_MWAIT, 0, 0x8070607040302ff}, 0, 0 },
+	/* Power Entry Packet */
+	{4, {0x02, 0x22}, 0, {INTEL_PT_PWRE, 0, 0}, 0, 1 },
+	{4, {0x02, 0x22, 1, 2}, 0, {INTEL_PT_PWRE, 0, 0x0201}, 0, 1 },
+	{4, {0x02, 0x22, 0x80, 0x34}, 0, {INTEL_PT_PWRE, 0, 0x3480}, 0, 1 },
+	{4, {0x02, 0x22, 0x00, 0x56}, 0, {INTEL_PT_PWRE, 0, 0x5600}, 0, 1 },
+	/* Power Exit Packet */
+	{7, {0x02, 0xa2}, 0, {INTEL_PT_PWRX, 0, 0}, 0, 1 },
+	{7, {0x02, 0xa2, 1, 2, 3, 4, 5}, 0, {INTEL_PT_PWRX, 0, 0x504030201}, 0, 1 },
+	{7, {0x02, 0xa2, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, {INTEL_PT_PWRX, 0, 0xffffffffff}, 0, 1 },
+	/* Block Begin Packet */
+	{3, {0x02, 0x63, 0x00}, 0, {INTEL_PT_BBP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{3, {0x02, 0x63, 0x80}, 0, {INTEL_PT_BBP, 1, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{3, {0x02, 0x63, 0x1f}, 0, {INTEL_PT_BBP, 0, 0x1f}, INTEL_PT_BLK_8_CTX, 0 },
+	{3, {0x02, 0x63, 0x9f}, 0, {INTEL_PT_BBP, 1, 0x1f}, INTEL_PT_BLK_4_CTX, 0 },
+	/* 4-byte Block Item Packet */
+	{5, {0x04}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0xfc}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0x04, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 },
+	{5, {0xfc, 1, 2, 3, 4}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BIP, 0x1f, 0x04030201}, INTEL_PT_BLK_4_CTX, 0 },
+	/* 8-byte Block Item Packet */
+	{9, {0x04}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0xfc}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0x04, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 },
+	{9, {0xfc, 1, 2, 3, 4, 5, 6, 7, 8}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BIP, 0x1f, 0x0807060504030201}, INTEL_PT_BLK_8_CTX, 0 },
+	/* Block End Packet */
+	{2, {0x02, 0x33}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 },
+	{2, {0x02, 0xb3}, INTEL_PT_BLK_4_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 },
+	{2, {0x02, 0x33}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP, 0, 0}, 0, 0 },
+	{2, {0x02, 0xb3}, INTEL_PT_BLK_8_CTX, {INTEL_PT_BEP_IP, 0, 0}, 0, 0 },
+	/* Terminator */
+	{0, {0}, 0, {0, 0, 0}, 0, 0 },
+};
+
+static int dump_packet(struct intel_pt_pkt *packet, u8 *bytes, int len)
+{
+	char desc[INTEL_PT_PKT_DESC_MAX];
+	int ret, i;
+
+	for (i = 0; i < len; i++)
+		pr_debug(" %02x", bytes[i]);
+	for (; i < INTEL_PT_PKT_MAX_SZ; i++)
+		pr_debug("   ");
+	pr_debug("   ");
+	ret = intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX);
+	if (ret < 0) {
+		pr_debug("intel_pt_pkt_desc failed!\n");
+		return TEST_FAIL;
+	}
+	pr_debug("%s\n", desc);
+
+	return TEST_OK;
+}
+
+static void decoding_failed(struct test_data *d)
+{
+	pr_debug("Decoding failed!\n");
+	pr_debug("Decoding:  ");
+	dump_packet(&d->packet, d->bytes, d->len);
+}
+
+static int fail(struct test_data *d, struct intel_pt_pkt *packet, int len,
+		enum intel_pt_pkt_ctx new_ctx)
+{
+	decoding_failed(d);
+
+	if (len != d->len)
+		pr_debug("Expected length: %d   Decoded length %d\n",
+			 d->len, len);
+
+	if (packet->type != d->packet.type)
+		pr_debug("Expected type: %d   Decoded type %d\n",
+			 d->packet.type, packet->type);
+
+	if (packet->count != d->packet.count)
+		pr_debug("Expected count: %d   Decoded count %d\n",
+			 d->packet.count, packet->count);
+
+	if (packet->payload != d->packet.payload)
+		pr_debug("Expected payload: 0x%llx   Decoded payload 0x%llx\n",
+			 (unsigned long long)d->packet.payload,
+			 (unsigned long long)packet->payload);
+
+	if (new_ctx != d->new_ctx)
+		pr_debug("Expected packet context: %d   Decoded packet context %d\n",
+			 d->new_ctx, new_ctx);
+
+	return TEST_FAIL;
+}
+
+static int test_ctx_unchanged(struct test_data *d, struct intel_pt_pkt *packet,
+			      enum intel_pt_pkt_ctx ctx)
+{
+	enum intel_pt_pkt_ctx old_ctx = ctx;
+
+	intel_pt_upd_pkt_ctx(packet, &ctx);
+
+	if (ctx != old_ctx) {
+		decoding_failed(d);
+		pr_debug("Packet context changed!\n");
+		return TEST_FAIL;
+	}
+
+	return TEST_OK;
+}
+
+static int test_one(struct test_data *d)
+{
+	struct intel_pt_pkt packet;
+	enum intel_pt_pkt_ctx ctx = d->ctx;
+	int ret;
+
+	memset(&packet, 0xff, sizeof(packet));
+
+	/* Decode a packet */
+	ret = intel_pt_get_packet(d->bytes, d->len, &packet, &ctx);
+	if (ret < 0 || ret > INTEL_PT_PKT_MAX_SZ) {
+		decoding_failed(d);
+		pr_debug("intel_pt_get_packet returned %d\n", ret);
+		return TEST_FAIL;
+	}
+
+	/* Some packets must always leave the packet context unchanged */
+	if (d->ctx_unchanged) {
+		int err;
+
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_NO_CTX);
+		if (err)
+			return err;
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_4_CTX);
+		if (err)
+			return err;
+		err = test_ctx_unchanged(d, &packet, INTEL_PT_BLK_8_CTX);
+		if (err)
+			return err;
+	}
+
+	/* Compare to the expected values */
+	if (ret != d->len || packet.type != d->packet.type ||
+	    packet.count != d->packet.count ||
+	    packet.payload != d->packet.payload || ctx != d->new_ctx)
+		return fail(d, &packet, ret, ctx);
+
+	pr_debug("Decoded ok:");
+	ret = dump_packet(&d->packet, d->bytes, d->len);
+
+	return ret;
+}
+
+/*
+ * This test feeds byte sequences to the Intel PT packet decoder and checks the
+ * results. Changes to the packet context are also checked.
+ */
+int test__intel_pt_pkt_decoder(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+	struct test_data *d = data;
+	int ret;
+
+	for (d = data; d->len; d++) {
+		ret = test_one(d);
+		if (ret)
+			return ret;
+	}
+
+	return TEST_OK;
+}

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add decoder support for PEBS via PT
  2019-06-10  7:27 ` [PATCH 03/11] perf intel-pt: Add decoder support for PEBS via PT Adrian Hunter
@ 2019-06-22  6:37   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, tglx, jolsa, acme, hpa, mingo, adrian.hunter

Commit-ID:  4c35595e1ea7585d09eb80096f47af237061e795
Gitweb:     https://git.kernel.org/tip/4c35595e1ea7585d09eb80096f47af237061e795
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:55 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:17 -0300

perf intel-pt: Add decoder support for PEBS via PT

PEBS data is encoded in Block Item Packets (BIP). Populate a new structure
intel_pt_blk_items with the values and, upon a Block End Packet (BEP),
report them as a new Intel PT sample type INTEL_PT_BLK_ITEMS.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-4-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  |  78 +++++++++++-
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  | 137 +++++++++++++++++++++
 2 files changed, 214 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 2f7791d4034f..f8b71bf2bb4c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -134,6 +134,9 @@ struct intel_pt_decoder {
 	struct intel_pt_stack stack;
 	enum intel_pt_pkt_state pkt_state;
 	enum intel_pt_pkt_ctx pkt_ctx;
+	enum intel_pt_pkt_ctx prev_pkt_ctx;
+	enum intel_pt_blk_type blk_type;
+	int blk_type_pos;
 	struct intel_pt_pkt packet;
 	struct intel_pt_pkt tnt;
 	int pkt_step;
@@ -167,6 +170,7 @@ struct intel_pt_decoder {
 	bool set_fup_mwait;
 	bool set_fup_pwre;
 	bool set_fup_exstop;
+	bool set_fup_bep;
 	bool sample_cyc;
 	unsigned int fup_tx_flags;
 	unsigned int tx_flags;
@@ -560,6 +564,7 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
 	memcpy(buf + len, decoder->buf, n);
 	len += n;
 
+	decoder->prev_pkt_ctx = decoder->pkt_ctx;
 	ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx);
 	if (ret < (int)old_len) {
 		decoder->next_buf = decoder->buf;
@@ -885,6 +890,7 @@ static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
 				return ret;
 		}
 
+		decoder->prev_pkt_ctx = decoder->pkt_ctx;
 		ret = intel_pt_get_packet(decoder->buf, decoder->len,
 					  &decoder->packet, &decoder->pkt_ctx);
 		if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 &&
@@ -1124,6 +1130,14 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
 		decoder->state.to_ip = 0;
 		ret = true;
 	}
+	if (decoder->set_fup_bep) {
+		decoder->set_fup_bep = false;
+		decoder->state.type |= INTEL_PT_BLK_ITEMS;
+		decoder->state.type &= ~INTEL_PT_BRANCH;
+		decoder->state.from_ip = decoder->ip;
+		decoder->state.to_ip = 0;
+		ret = true;
+	}
 	return ret;
 }
 
@@ -1609,6 +1623,46 @@ static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
 	intel_pt_log_to("Setting timestamp", decoder->timestamp);
 }
 
+static void intel_pt_bbp(struct intel_pt_decoder *decoder)
+{
+	if (decoder->prev_pkt_ctx == INTEL_PT_NO_CTX) {
+		memset(decoder->state.items.mask, 0, sizeof(decoder->state.items.mask));
+		decoder->state.items.is_32_bit = false;
+	}
+	decoder->blk_type = decoder->packet.payload;
+	decoder->blk_type_pos = intel_pt_blk_type_pos(decoder->blk_type);
+	if (decoder->blk_type == INTEL_PT_GP_REGS)
+		decoder->state.items.is_32_bit = decoder->packet.count;
+	if (decoder->blk_type_pos < 0) {
+		intel_pt_log("WARNING: Unknown block type %u\n",
+			     decoder->blk_type);
+	} else if (decoder->state.items.mask[decoder->blk_type_pos]) {
+		intel_pt_log("WARNING: Duplicate block type %u\n",
+			     decoder->blk_type);
+	}
+}
+
+static void intel_pt_bip(struct intel_pt_decoder *decoder)
+{
+	uint32_t id = decoder->packet.count;
+	uint32_t bit = 1 << id;
+	int pos = decoder->blk_type_pos;
+
+	if (pos < 0 || id >= INTEL_PT_BLK_ITEM_ID_CNT) {
+		intel_pt_log("WARNING: Unknown block item %u type %d\n",
+			     id, decoder->blk_type);
+		return;
+	}
+
+	if (decoder->state.items.mask[pos] & bit) {
+		intel_pt_log("WARNING: Duplicate block item %u type %d\n",
+			     id, decoder->blk_type);
+	}
+
+	decoder->state.items.mask[pos] |= bit;
+	decoder->state.items.val[pos][id] = decoder->packet.payload;
+}
+
 /* Walk PSB+ packets when already in sync. */
 static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
 {
@@ -2063,10 +2117,31 @@ next:
 			return 0;
 
 		case INTEL_PT_BBP:
+			intel_pt_bbp(decoder);
+			break;
+
 		case INTEL_PT_BIP:
+			intel_pt_bip(decoder);
+			break;
+
 		case INTEL_PT_BEP:
+			decoder->state.type = INTEL_PT_BLK_ITEMS;
+			decoder->state.from_ip = decoder->ip;
+			decoder->state.to_ip = 0;
+			return 0;
+
 		case INTEL_PT_BEP_IP:
-			break;
+			err = intel_pt_get_next_packet(decoder);
+			if (err)
+				return err;
+			if (decoder->packet.type == INTEL_PT_FUP) {
+				decoder->set_fup_bep = true;
+				no_tip = true;
+			} else {
+				intel_pt_log_at("ERROR: Missing FUP after BEP",
+						decoder->pos);
+			}
+			goto next;
 
 		default:
 			return intel_pt_bug(decoder);
@@ -2335,6 +2410,7 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
 	decoder->set_fup_mwait = false;
 	decoder->set_fup_pwre = false;
 	decoder->set_fup_exstop = false;
+	decoder->set_fup_bep = false;
 
 	if (!decoder->branch_enable) {
 		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 754efa8b501f..9957f2ccdca8 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -30,6 +30,7 @@ enum intel_pt_sample_type {
 	INTEL_PT_CBR_CHG	= 1 << 8,
 	INTEL_PT_TRACE_BEGIN	= 1 << 9,
 	INTEL_PT_TRACE_END	= 1 << 10,
+	INTEL_PT_BLK_ITEMS	= 1 << 11,
 };
 
 enum intel_pt_period_type {
@@ -61,6 +62,141 @@ enum intel_pt_param_flags {
 	INTEL_PT_FUP_WITH_NLIP	= 1 << 0,
 };
 
+enum intel_pt_blk_type {
+	INTEL_PT_GP_REGS	= 1,
+	INTEL_PT_PEBS_BASIC	= 4,
+	INTEL_PT_PEBS_MEM	= 5,
+	INTEL_PT_LBR_0		= 8,
+	INTEL_PT_LBR_1		= 9,
+	INTEL_PT_LBR_2		= 10,
+	INTEL_PT_XMM		= 16,
+	INTEL_PT_BLK_TYPE_MAX
+};
+
+/*
+ * The block type numbers are not sequential but here they are given sequential
+ * positions to avoid wasting space for array placement.
+ */
+enum intel_pt_blk_type_pos {
+	INTEL_PT_GP_REGS_POS,
+	INTEL_PT_PEBS_BASIC_POS,
+	INTEL_PT_PEBS_MEM_POS,
+	INTEL_PT_LBR_0_POS,
+	INTEL_PT_LBR_1_POS,
+	INTEL_PT_LBR_2_POS,
+	INTEL_PT_XMM_POS,
+	INTEL_PT_BLK_TYPE_CNT
+};
+
+/* Get the array position for a block type */
+static inline int intel_pt_blk_type_pos(enum intel_pt_blk_type blk_type)
+{
+#define BLK_TYPE(bt) [INTEL_PT_##bt] = INTEL_PT_##bt##_POS + 1
+	const int map[INTEL_PT_BLK_TYPE_MAX] = {
+		BLK_TYPE(GP_REGS),
+		BLK_TYPE(PEBS_BASIC),
+		BLK_TYPE(PEBS_MEM),
+		BLK_TYPE(LBR_0),
+		BLK_TYPE(LBR_1),
+		BLK_TYPE(LBR_2),
+		BLK_TYPE(XMM),
+	};
+#undef BLK_TYPE
+
+	return blk_type < INTEL_PT_BLK_TYPE_MAX ? map[blk_type] - 1 : -1;
+}
+
+#define INTEL_PT_BLK_ITEM_ID_CNT	32
+
+/*
+ * Use unions so that the block items can be accessed by name or by array index.
+ * There is an array of 32-bit masks for each block type, which indicate which
+ * values are present. Then arrays of 32 64-bit values for each block type.
+ */
+struct intel_pt_blk_items {
+	union {
+		uint32_t mask[INTEL_PT_BLK_TYPE_CNT];
+		struct {
+			uint32_t has_rflags:1;
+			uint32_t has_rip:1;
+			uint32_t has_rax:1;
+			uint32_t has_rcx:1;
+			uint32_t has_rdx:1;
+			uint32_t has_rbx:1;
+			uint32_t has_rsp:1;
+			uint32_t has_rbp:1;
+			uint32_t has_rsi:1;
+			uint32_t has_rdi:1;
+			uint32_t has_r8:1;
+			uint32_t has_r9:1;
+			uint32_t has_r10:1;
+			uint32_t has_r11:1;
+			uint32_t has_r12:1;
+			uint32_t has_r13:1;
+			uint32_t has_r14:1;
+			uint32_t has_r15:1;
+			uint32_t has_unused_0:14;
+			uint32_t has_ip:1;
+			uint32_t has_applicable_counters:1;
+			uint32_t has_timestamp:1;
+			uint32_t has_unused_1:29;
+			uint32_t has_mem_access_address:1;
+			uint32_t has_mem_aux_info:1;
+			uint32_t has_mem_access_latency:1;
+			uint32_t has_tsx_aux_info:1;
+			uint32_t has_unused_2:28;
+			uint32_t has_lbr_0;
+			uint32_t has_lbr_1;
+			uint32_t has_lbr_2;
+			uint32_t has_xmm;
+		};
+	};
+	union {
+		uint64_t val[INTEL_PT_BLK_TYPE_CNT][INTEL_PT_BLK_ITEM_ID_CNT];
+		struct {
+			struct {
+				uint64_t rflags;
+				uint64_t rip;
+				uint64_t rax;
+				uint64_t rcx;
+				uint64_t rdx;
+				uint64_t rbx;
+				uint64_t rsp;
+				uint64_t rbp;
+				uint64_t rsi;
+				uint64_t rdi;
+				uint64_t r8;
+				uint64_t r9;
+				uint64_t r10;
+				uint64_t r11;
+				uint64_t r12;
+				uint64_t r13;
+				uint64_t r14;
+				uint64_t r15;
+				uint64_t unused_0[INTEL_PT_BLK_ITEM_ID_CNT - 18];
+			};
+			struct {
+				uint64_t ip;
+				uint64_t applicable_counters;
+				uint64_t timestamp;
+				uint64_t unused_1[INTEL_PT_BLK_ITEM_ID_CNT - 3];
+			};
+			struct {
+				uint64_t mem_access_address;
+				uint64_t mem_aux_info;
+				uint64_t mem_access_latency;
+				uint64_t tsx_aux_info;
+				uint64_t unused_2[INTEL_PT_BLK_ITEM_ID_CNT - 4];
+			};
+			uint64_t lbr_0[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t lbr_1[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t lbr_2[INTEL_PT_BLK_ITEM_ID_CNT];
+			uint64_t xmm[INTEL_PT_BLK_ITEM_ID_CNT];
+		};
+	};
+	bool is_32_bit;
+};
+
 struct intel_pt_state {
 	enum intel_pt_sample_type type;
 	int err;
@@ -81,6 +217,7 @@ struct intel_pt_state {
 	enum intel_pt_insn_op insn_op;
 	int insn_len;
 	char insn[INTEL_PT_INSN_BUF_SZ];
+	struct intel_pt_blk_items items;
 };
 
 struct intel_pt_insn;

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Prepare to synthesize PEBS samples
  2019-06-10  7:27 ` [PATCH 04/11] perf intel-pt: Prepare to synthesize PEBS samples Adrian Hunter
@ 2019-06-22  6:38   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, acme, mingo, jolsa, adrian.hunter, hpa, linux-kernel

Commit-ID:  e62ca655eea7ad4956929f647c2d9fb36aeff90e
Gitweb:     https://git.kernel.org/tip/e62ca655eea7ad4956929f647c2d9fb36aeff90e
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:56 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:17 -0300

perf intel-pt: Prepare to synthesize PEBS samples

Add infrastructure to prepare for synthesizing PEBS samples but leave
the actual synthesis to later patches.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-5-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 893cef494a43..cc91c1413c22 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -101,6 +101,9 @@ struct intel_pt {
 	u64 pwrx_id;
 	u64 cbr_id;
 
+	bool sample_pebs;
+	struct perf_evsel *pebs_evsel;
+
 	u64 tsc_bit;
 	u64 mtc_bit;
 	u64 mtc_freq_bits;
@@ -1535,6 +1538,11 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
+static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq __maybe_unused)
+{
+	return 0;
+}
+
 static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,
 				pid_t pid, pid_t tid, u64 ip, u64 timestamp)
 {
@@ -1622,6 +1630,16 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
 		ptq->ipc_cyc_cnt = ptq->state->tot_cyc_cnt;
 	}
 
+	/*
+	 * Do PEBS first to allow for the possibility that the PEBS timestamp
+	 * precedes the current timestamp.
+	 */
+	if (pt->sample_pebs && state->type & INTEL_PT_BLK_ITEMS) {
+		err = intel_pt_synth_pebs_sample(ptq);
+		if (err)
+			return err;
+	}
+
 	if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) {
 		if (state->type & INTEL_PT_CBR_CHG) {
 			err = intel_pt_synth_cbr_sample(ptq);

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Factor out common sample preparation for re-use
  2019-06-10  7:27 ` [PATCH 05/11] perf intel-pt: Factor out common sample preparation for re-use Adrian Hunter
@ 2019-06-22  6:38   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, mingo, tglx, adrian.hunter, linux-kernel, acme, jolsa

Commit-ID:  0dfded34a2e3b517c149ee9c7d1e5173025017b7
Gitweb:     https://git.kernel.org/tip/0dfded34a2e3b517c149ee9c7d1e5173025017b7
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:57 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Factor out common sample preparation for re-use

Factor out common sample preparation for re-use when synthesizing PEBS
samples.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-6-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index cc91c1413c22..a2d90b2f1f11 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1182,28 +1182,37 @@ static inline bool intel_pt_skip_event(struct intel_pt *pt)
 	       pt->num_events++ < pt->synth_opts.initial_skip;
 }
 
+static void intel_pt_prep_a_sample(struct intel_pt_queue *ptq,
+				   union perf_event *event,
+				   struct perf_sample *sample)
+{
+	event->sample.header.type = PERF_RECORD_SAMPLE;
+	event->sample.header.size = sizeof(struct perf_event_header);
+
+	sample->pid = ptq->pid;
+	sample->tid = ptq->tid;
+	sample->cpu = ptq->cpu;
+	sample->insn_len = ptq->insn_len;
+	memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
+}
+
 static void intel_pt_prep_b_sample(struct intel_pt *pt,
 				   struct intel_pt_queue *ptq,
 				   union perf_event *event,
 				   struct perf_sample *sample)
 {
+	intel_pt_prep_a_sample(ptq, event, sample);
+
 	if (!pt->timeless_decoding)
 		sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc);
 
 	sample->ip = ptq->state->from_ip;
 	sample->cpumode = intel_pt_cpumode(pt, sample->ip);
-	sample->pid = ptq->pid;
-	sample->tid = ptq->tid;
 	sample->addr = ptq->state->to_ip;
 	sample->period = 1;
-	sample->cpu = ptq->cpu;
 	sample->flags = ptq->flags;
-	sample->insn_len = ptq->insn_len;
-	memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ);
 
-	event->sample.header.type = PERF_RECORD_SAMPLE;
 	event->sample.header.misc = sample->cpumode;
-	event->sample.header.size = sizeof(struct perf_event_header);
 }
 
 static int intel_pt_inject_event(union perf_event *event,

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Synthesize PEBS sample basic information
  2019-06-10  7:27 ` [PATCH 06/11] perf intel-pt: Synthesize PEBS sample basic information Adrian Hunter
@ 2019-06-22  6:39   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, acme, hpa, mingo, linux-kernel, tglx, adrian.hunter

Commit-ID:  9d0bc53e35b82e429ab698d112f7af4336578735
Gitweb:     https://git.kernel.org/tip/9d0bc53e35b82e429ab698d112f7af4336578735
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:58 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Synthesize PEBS sample basic information

Synthesize a PEBS sample using basic information (ip, timestamp) only.
Other PEBS information will be added in later patches.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-7-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index a2d90b2f1f11..979519b00a74 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1547,9 +1547,57 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
-static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq __maybe_unused)
+static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
-	return 0;
+	const struct intel_pt_blk_items *items = &ptq->state->items;
+	struct perf_sample sample = { .ip = 0, };
+	union perf_event *event = ptq->event_buf;
+	struct intel_pt *pt = ptq->pt;
+	struct perf_evsel *evsel = pt->pebs_evsel;
+	u64 sample_type = evsel->attr.sample_type;
+	u64 id = evsel->id[0];
+	u8 cpumode;
+
+	if (intel_pt_skip_event(pt))
+		return 0;
+
+	intel_pt_prep_a_sample(ptq, event, &sample);
+
+	sample.id = id;
+	sample.stream_id = id;
+
+	if (!evsel->attr.freq)
+		sample.period = evsel->attr.sample_period;
+
+	/* No support for non-zero CS base */
+	if (items->has_ip)
+		sample.ip = items->ip;
+	else if (items->has_rip)
+		sample.ip = items->rip;
+	else
+		sample.ip = ptq->state->from_ip;
+
+	/* No support for guest mode at this time */
+	cpumode = sample.ip < ptq->pt->kernel_start ?
+		  PERF_RECORD_MISC_USER :
+		  PERF_RECORD_MISC_KERNEL;
+
+	event->sample.header.misc = cpumode | PERF_RECORD_MISC_EXACT_IP;
+
+	sample.cpumode = cpumode;
+
+	if (sample_type & PERF_SAMPLE_TIME) {
+		u64 timestamp = 0;
+
+		if (items->has_timestamp)
+			timestamp = items->timestamp;
+		else if (!pt->timeless_decoding)
+			timestamp = ptq->timestamp;
+		if (timestamp)
+			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
+	}
+
+	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 
 static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu,

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add gp registers to synthesized PEBS sample
  2019-06-10  7:27 ` [PATCH 07/11] perf intel-pt: Add gp registers to synthesized PEBS sample Adrian Hunter
@ 2019-06-22  6:40   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, hpa, adrian.hunter, jolsa, tglx, linux-kernel, mingo

Commit-ID:  9e9a618afc178e747cc449464ba54d9c932f7af2
Gitweb:     https://git.kernel.org/tip/9e9a618afc178e747cc449464ba54d9c932f7af2
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:27:59 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Add gp registers to synthesized PEBS sample

Add general purpose register information from PEBS data in the Intel PT
trace to the synthesized PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-8-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 979519b00a74..00c2c96bb805 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -35,6 +35,8 @@
 #include "config.h"
 #include "time-utils.h"
 
+#include "../arch/x86/include/uapi/asm/perf_regs.h"
+
 #include "intel-pt-decoder/intel-pt-log.h"
 #include "intel-pt-decoder/intel-pt-decoder.h"
 #include "intel-pt-decoder/intel-pt-insn-decoder.h"
@@ -1547,6 +1549,60 @@ static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq)
 					    pt->pwr_events_sample_type);
 }
 
+/*
+ * PEBS gp_regs array indexes plus 1 so that 0 means not present. Refer
+ * intel_pt_add_gp_regs().
+ */
+static const int pebs_gp_regs[] = {
+	[PERF_REG_X86_FLAGS]	= 1,
+	[PERF_REG_X86_IP]	= 2,
+	[PERF_REG_X86_AX]	= 3,
+	[PERF_REG_X86_CX]	= 4,
+	[PERF_REG_X86_DX]	= 5,
+	[PERF_REG_X86_BX]	= 6,
+	[PERF_REG_X86_SP]	= 7,
+	[PERF_REG_X86_BP]	= 8,
+	[PERF_REG_X86_SI]	= 9,
+	[PERF_REG_X86_DI]	= 10,
+	[PERF_REG_X86_R8]	= 11,
+	[PERF_REG_X86_R9]	= 12,
+	[PERF_REG_X86_R10]	= 13,
+	[PERF_REG_X86_R11]	= 14,
+	[PERF_REG_X86_R12]	= 15,
+	[PERF_REG_X86_R13]	= 16,
+	[PERF_REG_X86_R14]	= 17,
+	[PERF_REG_X86_R15]	= 18,
+};
+
+static u64 *intel_pt_add_gp_regs(struct regs_dump *intr_regs, u64 *pos,
+				 const struct intel_pt_blk_items *items,
+				 u64 regs_mask)
+{
+	const u64 *gp_regs = items->val[INTEL_PT_GP_REGS_POS];
+	u32 mask = items->mask[INTEL_PT_GP_REGS_POS];
+	u32 bit;
+	int i;
+
+	for (i = 0, bit = 1; i < PERF_REG_X86_64_MAX; i++, bit <<= 1) {
+		/* Get the PEBS gp_regs array index */
+		int n = pebs_gp_regs[i] - 1;
+
+		if (n < 0)
+			continue;
+		/*
+		 * Add only registers that were requested (i.e. 'regs_mask') and
+		 * that were provided (i.e. 'mask'), and update the resulting
+		 * mask (i.e. 'intr_regs->mask') accordingly.
+		 */
+		if (mask & 1 << n && regs_mask & bit) {
+			intr_regs->mask |= bit;
+			*pos++ = gp_regs[n];
+		}
+	}
+
+	return pos;
+}
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1597,6 +1653,19 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
 	}
 
+	if (sample_type & PERF_SAMPLE_REGS_INTR &&
+	    items->mask[INTEL_PT_GP_REGS_POS]) {
+		u64 regs[sizeof(sample.intr_regs.mask)];
+		u64 regs_mask = evsel->attr.sample_regs_intr;
+
+		sample.intr_regs.abi = items->is_32_bit ?
+				       PERF_SAMPLE_REGS_ABI_32 :
+				       PERF_SAMPLE_REGS_ABI_64;
+		sample.intr_regs.regs = regs;
+
+		intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add XMM registers to synthesized PEBS sample
  2019-06-10  7:28 ` [PATCH 08/11] perf intel-pt: Add xmm " Adrian Hunter
@ 2019-06-22  6:40   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:40 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, acme, mingo, hpa, linux-kernel, tglx, jolsa

Commit-ID:  143d34a6b387b96aba42c49cb76d18ad3e3863e5
Gitweb:     https://git.kernel.org/tip/143d34a6b387b96aba42c49cb76d18ad3e3863e5
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:28:00 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Add XMM registers to synthesized PEBS sample

Add XMM register information from PEBS data in the Intel PT trace to the
synthesized PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-9-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 00c2c96bb805..f83dd10bb7d0 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1603,6 +1603,31 @@ static u64 *intel_pt_add_gp_regs(struct regs_dump *intr_regs, u64 *pos,
 	return pos;
 }
 
+#ifndef PERF_REG_X86_XMM0
+#define PERF_REG_X86_XMM0 32
+#endif
+
+static void intel_pt_add_xmm(struct regs_dump *intr_regs, u64 *pos,
+			     const struct intel_pt_blk_items *items,
+			     u64 regs_mask)
+{
+	u32 mask = items->has_xmm & (regs_mask >> PERF_REG_X86_XMM0);
+	const u64 *xmm = items->xmm;
+
+	/*
+	 * If there are any XMM registers, then there should be all of them.
+	 * Nevertheless, follow the logic to add only registers that were
+	 * requested (i.e. 'regs_mask') and that were provided (i.e. 'mask'),
+	 * and update the resulting mask (i.e. 'intr_regs->mask') accordingly.
+	 */
+	intr_regs->mask |= (u64)mask << PERF_REG_X86_XMM0;
+
+	for (; mask; mask >>= 1, xmm++) {
+		if (mask & 1)
+			*pos++ = *xmm;
+	}
+}
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1657,13 +1682,16 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 	    items->mask[INTEL_PT_GP_REGS_POS]) {
 		u64 regs[sizeof(sample.intr_regs.mask)];
 		u64 regs_mask = evsel->attr.sample_regs_intr;
+		u64 *pos;
 
 		sample.intr_regs.abi = items->is_32_bit ?
 				       PERF_SAMPLE_REGS_ABI_32 :
 				       PERF_SAMPLE_REGS_ABI_64;
 		sample.intr_regs.regs = regs;
 
-		intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+		pos = intel_pt_add_gp_regs(&sample.intr_regs, regs, items, regs_mask);
+
+		intel_pt_add_xmm(&sample.intr_regs, pos, items, regs_mask);
 	}
 
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add LBR information to synthesized PEBS sample
  2019-06-10  7:28 ` [PATCH 09/11] perf intel-pt: Add lbr information " Adrian Hunter
@ 2019-06-22  6:41   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, linux-kernel, jolsa, acme, tglx, adrian.hunter, hpa

Commit-ID:  aa62afd7daac4b4cc95cd2454e3f43aa23f519c1
Gitweb:     https://git.kernel.org/tip/aa62afd7daac4b4cc95cd2454e3f43aa23f519c1
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:28:01 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Add LBR information to synthesized PEBS sample

Add LBR information from PEBS data in the Intel PT trace to the
synthesized PEBS sample.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-10-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index f83dd10bb7d0..db00c13dc36f 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1628,6 +1628,58 @@ static void intel_pt_add_xmm(struct regs_dump *intr_regs, u64 *pos,
 	}
 }
 
+#define LBR_INFO_MISPRED	(1ULL << 63)
+#define LBR_INFO_IN_TX		(1ULL << 62)
+#define LBR_INFO_ABORT		(1ULL << 61)
+#define LBR_INFO_CYCLES		0xffff
+
+/* Refer kernel's intel_pmu_store_pebs_lbrs() */
+static u64 intel_pt_lbr_flags(u64 info)
+{
+	union {
+		struct branch_flags flags;
+		u64 result;
+	} u = {
+		.flags = {
+			.mispred	= !!(info & LBR_INFO_MISPRED),
+			.predicted	= !(info & LBR_INFO_MISPRED),
+			.in_tx		= !!(info & LBR_INFO_IN_TX),
+			.abort		= !!(info & LBR_INFO_ABORT),
+			.cycles		= info & LBR_INFO_CYCLES,
+		}
+	};
+
+	return u.result;
+}
+
+static void intel_pt_add_lbrs(struct branch_stack *br_stack,
+			      const struct intel_pt_blk_items *items)
+{
+	u64 *to;
+	int i;
+
+	br_stack->nr = 0;
+
+	to = &br_stack->entries[0].from;
+
+	for (i = INTEL_PT_LBR_0_POS; i <= INTEL_PT_LBR_2_POS; i++) {
+		u32 mask = items->mask[i];
+		const u64 *from = items->val[i];
+
+		for (; mask; mask >>= 3, from += 3) {
+			if ((mask & 7) == 7) {
+				*to++ = from[0];
+				*to++ = from[1];
+				*to++ = intel_pt_lbr_flags(from[2]);
+				br_stack->nr += 1;
+			}
+		}
+	}
+}
+
+/* INTEL_PT_LBR_0, INTEL_PT_LBR_1 and INTEL_PT_LBR_2 */
+#define LBRS_MAX (INTEL_PT_BLK_ITEM_ID_CNT * 3)
+
 static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 {
 	const struct intel_pt_blk_items *items = &ptq->state->items;
@@ -1694,6 +1746,26 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 		intel_pt_add_xmm(&sample.intr_regs, pos, items, regs_mask);
 	}
 
+	if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
+		struct {
+			struct branch_stack br_stack;
+			struct branch_entry entries[LBRS_MAX];
+		} br;
+
+		if (items->mask[INTEL_PT_LBR_0_POS] ||
+		    items->mask[INTEL_PT_LBR_1_POS] ||
+		    items->mask[INTEL_PT_LBR_2_POS]) {
+			intel_pt_add_lbrs(&br.br_stack, items);
+			sample.branch_stack = &br.br_stack;
+		} else if (pt->synth_opts.last_branch) {
+			intel_pt_copy_last_branch_rb(ptq);
+			sample.branch_stack = ptq->last_branch;
+		} else {
+			br.br_stack.nr = 0;
+			sample.branch_stack = &br.br_stack;
+		}
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add memory information to synthesized PEBS sample
  2019-06-10  7:28 ` [PATCH 10/11] perf intel-pt: Add memory " Adrian Hunter
@ 2019-06-22  6:42   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, jolsa, mingo, tglx, adrian.hunter, hpa

Commit-ID:  975846eddf907297aa036544545cd839c7c7dd31
Gitweb:     https://git.kernel.org/tip/975846eddf907297aa036544545cd839c7c7dd31
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:28:02 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Add memory information to synthesized PEBS sample

Add memory information from PEBS data in the Intel PT trace to the
synthesized PEBS sample. This provides sample types PERF_SAMPLE_ADDR,
PERF_SAMPLE_WEIGHT, and PERF_SAMPLE_TRANSACTION, but not
PERF_SAMPLE_DATA_SRC.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-11-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index db00c13dc36f..bf7647897e8a 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1766,6 +1766,33 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 		}
 	}
 
+	if (sample_type & PERF_SAMPLE_ADDR && items->has_mem_access_address)
+		sample.addr = items->mem_access_address;
+
+	if (sample_type & PERF_SAMPLE_WEIGHT) {
+		/*
+		 * Refer kernel's setup_pebs_adaptive_sample_data() and
+		 * intel_hsw_weight().
+		 */
+		if (items->has_mem_access_latency)
+			sample.weight = items->mem_access_latency;
+		if (!sample.weight && items->has_tsx_aux_info) {
+			/* Cycles last block */
+			sample.weight = (u32)items->tsx_aux_info;
+		}
+	}
+
+	if (sample_type & PERF_SAMPLE_TRANSACTION && items->has_tsx_aux_info) {
+		u64 ax = items->has_rax ? items->rax : 0;
+		/* Refer kernel's intel_hsw_transaction() */
+		u64 txn = (u8)(items->tsx_aux_info >> 32);
+
+		/* For RTM XABORTs also log the abort code from AX */
+		if (txn & PERF_TXN_TRANSACTION && ax & 1)
+			txn |= ((ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
+		sample.transaction = txn;
+	}
+
 	return intel_pt_deliver_synth_event(pt, ptq, event, &sample, sample_type);
 }
 

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [tip:perf/core] perf intel-pt: Add callchain to synthesized PEBS sample
  2019-06-10  7:28 ` [PATCH 11/11] perf intel-pt: Add callchain " Adrian Hunter
@ 2019-06-22  6:43   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Adrian Hunter @ 2019-06-22  6:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, adrian.hunter, tglx, acme, jolsa, mingo

Commit-ID:  e01f0ef509ea7e76929f24a074d241de52c6f82a
Gitweb:     https://git.kernel.org/tip/e01f0ef509ea7e76929f24a074d241de52c6f82a
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Mon, 10 Jun 2019 10:28:03 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 17 Jun 2019 15:57:18 -0300

perf intel-pt: Add callchain to synthesized PEBS sample

Like other synthesized events, if there is also an Intel PT branch
trace, then a call stack can also be synthesized.  Add that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/20190610072803.10456-12-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index bf7647897e8a..550db6e77968 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1730,6 +1730,14 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
 			sample.time = tsc_to_perf_time(timestamp, &pt->tc);
 	}
 
+	if (sample_type & PERF_SAMPLE_CALLCHAIN &&
+	    pt->synth_opts.callchain) {
+		thread_stack__sample(ptq->thread, ptq->cpu, ptq->chain,
+				     pt->synth_opts.callchain_sz, sample.ip,
+				     pt->kernel_start);
+		sample.callchain = ptq->chain;
+	}
+
 	if (sample_type & PERF_SAMPLE_REGS_INTR &&
 	    items->mask[INTEL_PT_GP_REGS_POS]) {
 		u64 regs[sizeof(sample.intr_regs.mask)];

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH 01/11] perf intel-pt: Add new packets for PEBS via PT
  2019-06-12 13:28           ` Arnaldo Carvalho de Melo
  2019-06-13  8:13             ` Adrian Hunter
@ 2019-07-04 16:10             ` Alexander Shishkin
  1 sibling, 0 replies; 30+ messages in thread
From: Alexander Shishkin @ 2019-07-04 16:10 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Adrian Hunter
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Peter Zijlstra, alexander.shishkin

Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> writes:

>> Awaiting V2, here is a link to the patches:
>> 
>> 	https://lore.kernel.org/lkml/20190502105022.15534-1-alexander.shishkin@linux.intel.com/
>
> yeah, I saw those and PeterZ's comments, that is why I asked about them
> :-)
>  
>> There is also still a few more tools changes dependent upon the kernel patches.
>
> But I think I can go ahead and push the decoder bits, when the kernel
> patches get merged we'll be almost ready to make full use of what it
> provides, right?

The kernel stuff and the rest of the tooling patches are here [1].

[1] https://marc.info/?l=linux-kernel&m=156225605132606

Regards,
--
Alex

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2019-07-04 16:10 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-10  7:27 [PATCH 00/11] perf intel-pt: Prepare for PEBS via PT Adrian Hunter
2019-06-10  7:27 ` [PATCH 01/11] perf intel-pt: Add new packets " Adrian Hunter
2019-06-12  0:09   ` Arnaldo Carvalho de Melo
2019-06-12  5:58     ` Adrian Hunter
2019-06-12 12:41       ` Arnaldo Carvalho de Melo
2019-06-12 12:52         ` Adrian Hunter
2019-06-12 13:28           ` Arnaldo Carvalho de Melo
2019-06-13  8:13             ` Adrian Hunter
2019-07-04 16:10             ` Alexander Shishkin
2019-06-22  6:35   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 02/11] perf intel-pt: Add Intel PT packet decoder test Adrian Hunter
2019-06-22  6:36   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 03/11] perf intel-pt: Add decoder support for PEBS via PT Adrian Hunter
2019-06-22  6:37   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 04/11] perf intel-pt: Prepare to synthesize PEBS samples Adrian Hunter
2019-06-22  6:38   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 05/11] perf intel-pt: Factor out common sample preparation for re-use Adrian Hunter
2019-06-22  6:38   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 06/11] perf intel-pt: Synthesize PEBS sample basic information Adrian Hunter
2019-06-22  6:39   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:27 ` [PATCH 07/11] perf intel-pt: Add gp registers to synthesized PEBS sample Adrian Hunter
2019-06-22  6:40   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:28 ` [PATCH 08/11] perf intel-pt: Add xmm " Adrian Hunter
2019-06-22  6:40   ` [tip:perf/core] perf intel-pt: Add XMM " tip-bot for Adrian Hunter
2019-06-10  7:28 ` [PATCH 09/11] perf intel-pt: Add lbr information " Adrian Hunter
2019-06-22  6:41   ` [tip:perf/core] perf intel-pt: Add LBR " tip-bot for Adrian Hunter
2019-06-10  7:28 ` [PATCH 10/11] perf intel-pt: Add memory " Adrian Hunter
2019-06-22  6:42   ` [tip:perf/core] " tip-bot for Adrian Hunter
2019-06-10  7:28 ` [PATCH 11/11] perf intel-pt: Add callchain " Adrian Hunter
2019-06-22  6:43   ` [tip:perf/core] " tip-bot for Adrian Hunter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).