diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2016-07-20 12:00:06 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-08-12 20:39:48 +0300 |
commit | e1717e0485af4f47fc4da1e979ac817f9ad61b0f (patch) | |
tree | dc4efbd88c04f49bff42d9aef9cccceb962268ad /tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | |
parent | 95f3be798472f63b495ca4712af005ea5ac7aa47 (diff) | |
download | linux-e1717e0485af4f47fc4da1e979ac817f9ad61b0f.tar.xz |
perf intel-pt: Fix ip compression
The June 2015 Intel SDM introduced IP Compression types 4 and 6. Refer
to section 36.4.2.2 Target IP (TIP) Packet - IP Compression.
Existing Intel PT packet decoder did not support type 4, and got type 6
wrong. Because type 3 and type 4 have the same number of bytes, the
packet 'count' has been changed from being the number of ip bytes to
being the type code. That allows the Intel PT decoder to correctly
decide whether to sign-extend or use the last ip. However that also
meant the code had to be adjusted in a number of places.
Currently hardware is not using the new compression types, so this fix
has no effect on existing hardware.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1469005206-3049-1-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c')
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | 24 |
1 files changed, 17 insertions, 7 deletions
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 b1257c816310..4f7b32020487 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 @@ -292,36 +292,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, const unsigned char *buf, size_t len, struct intel_pt_pkt *packet) { - switch (byte >> 5) { + int ip_len; + + packet->count = byte >> 5; + + switch (packet->count) { case 0: - packet->count = 0; + ip_len = 0; break; case 1: if (len < 3) return INTEL_PT_NEED_MORE_BYTES; - packet->count = 2; + ip_len = 2; packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); break; case 2: if (len < 5) return INTEL_PT_NEED_MORE_BYTES; - packet->count = 4; + ip_len = 4; packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); break; case 3: - case 6: + case 4: if (len < 7) return INTEL_PT_NEED_MORE_BYTES; - packet->count = 6; + ip_len = 6; memcpy_le64(&packet->payload, buf + 1, 6); break; + case 6: + if (len < 9) + return INTEL_PT_NEED_MORE_BYTES; + ip_len = 8; + packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); + break; default: return INTEL_PT_BAD_PACKET; } packet->type = type; - return packet->count + 1; + return ip_len + 1; } static int intel_pt_get_mode(const unsigned char *buf, size_t len, |