linux/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
<<
>>
Prefs
   1/*
   2 * intel_pt_pkt_decoder.c: Intel Processor Trace support
   3 * Copyright (c) 2013-2014, Intel Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 */
  15
  16#include <stdio.h>
  17#include <string.h>
  18#include <endian.h>
  19#include <byteswap.h>
  20
  21#include "intel-pt-pkt-decoder.h"
  22
  23#define BIT(n)          (1 << (n))
  24
  25#define BIT63           ((uint64_t)1 << 63)
  26
  27#define NR_FLAG         BIT63
  28
  29#if __BYTE_ORDER == __BIG_ENDIAN
  30#define le16_to_cpu bswap_16
  31#define le32_to_cpu bswap_32
  32#define le64_to_cpu bswap_64
  33#define memcpy_le64(d, s, n) do { \
  34        memcpy((d), (s), (n));    \
  35        *(d) = le64_to_cpu(*(d)); \
  36} while (0)
  37#else
  38#define le16_to_cpu
  39#define le32_to_cpu
  40#define le64_to_cpu
  41#define memcpy_le64 memcpy
  42#endif
  43
  44static const char * const packet_name[] = {
  45        [INTEL_PT_BAD]          = "Bad Packet!",
  46        [INTEL_PT_PAD]          = "PAD",
  47        [INTEL_PT_TNT]          = "TNT",
  48        [INTEL_PT_TIP_PGD]      = "TIP.PGD",
  49        [INTEL_PT_TIP_PGE]      = "TIP.PGE",
  50        [INTEL_PT_TSC]          = "TSC",
  51        [INTEL_PT_TMA]          = "TMA",
  52        [INTEL_PT_MODE_EXEC]    = "MODE.Exec",
  53        [INTEL_PT_MODE_TSX]     = "MODE.TSX",
  54        [INTEL_PT_MTC]          = "MTC",
  55        [INTEL_PT_TIP]          = "TIP",
  56        [INTEL_PT_FUP]          = "FUP",
  57        [INTEL_PT_CYC]          = "CYC",
  58        [INTEL_PT_VMCS]         = "VMCS",
  59        [INTEL_PT_PSB]          = "PSB",
  60        [INTEL_PT_PSBEND]       = "PSBEND",
  61        [INTEL_PT_CBR]          = "CBR",
  62        [INTEL_PT_TRACESTOP]    = "TraceSTOP",
  63        [INTEL_PT_PIP]          = "PIP",
  64        [INTEL_PT_OVF]          = "OVF",
  65        [INTEL_PT_MNT]          = "MNT",
  66};
  67
  68const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
  69{
  70        return packet_name[type];
  71}
  72
  73static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len,
  74                                 struct intel_pt_pkt *packet)
  75{
  76        uint64_t payload;
  77        int count;
  78
  79        if (len < 8)
  80                return INTEL_PT_NEED_MORE_BYTES;
  81
  82        payload = le64_to_cpu(*(uint64_t *)buf);
  83
  84        for (count = 47; count; count--) {
  85                if (payload & BIT63)
  86                        break;
  87                payload <<= 1;
  88        }
  89
  90        packet->type = INTEL_PT_TNT;
  91        packet->count = count;
  92        packet->payload = payload << 1;
  93        return 8;
  94}
  95
  96static int intel_pt_get_pip(const unsigned char *buf, size_t len,
  97                            struct intel_pt_pkt *packet)
  98{
  99        uint64_t payload = 0;
 100
 101        if (len < 8)
 102                return INTEL_PT_NEED_MORE_BYTES;
 103
 104        packet->type = INTEL_PT_PIP;
 105        memcpy_le64(&payload, buf + 2, 6);
 106        packet->payload = payload >> 1;
 107        if (payload & 1)
 108                packet->payload |= NR_FLAG;
 109
 110        return 8;
 111}
 112
 113static int intel_pt_get_tracestop(struct intel_pt_pkt *packet)
 114{
 115        packet->type = INTEL_PT_TRACESTOP;
 116        return 2;
 117}
 118
 119static int intel_pt_get_cbr(const unsigned char *buf, size_t len,
 120                            struct intel_pt_pkt *packet)
 121{
 122        if (len < 4)
 123                return INTEL_PT_NEED_MORE_BYTES;
 124        packet->type = INTEL_PT_CBR;
 125        packet->payload = buf[2];
 126        return 4;
 127}
 128
 129static int intel_pt_get_vmcs(const unsigned char *buf, size_t len,
 130                             struct intel_pt_pkt *packet)
 131{
 132        unsigned int count = (52 - 5) >> 3;
 133
 134        if (count < 1 || count > 7)
 135                return INTEL_PT_BAD_PACKET;
 136
 137        if (len < count + 2)
 138                return INTEL_PT_NEED_MORE_BYTES;
 139
 140        packet->type = INTEL_PT_VMCS;
 141        packet->count = count;
 142        memcpy_le64(&packet->payload, buf + 2, count);
 143
 144        return count + 2;
 145}
 146
 147static int intel_pt_get_ovf(struct intel_pt_pkt *packet)
 148{
 149        packet->type = INTEL_PT_OVF;
 150        return 2;
 151}
 152
 153static int intel_pt_get_psb(const unsigned char *buf, size_t len,
 154                            struct intel_pt_pkt *packet)
 155{
 156        int i;
 157
 158        if (len < 16)
 159                return INTEL_PT_NEED_MORE_BYTES;
 160
 161        for (i = 2; i < 16; i += 2) {
 162                if (buf[i] != 2 || buf[i + 1] != 0x82)
 163                        return INTEL_PT_BAD_PACKET;
 164        }
 165
 166        packet->type = INTEL_PT_PSB;
 167        return 16;
 168}
 169
 170static int intel_pt_get_psbend(struct intel_pt_pkt *packet)
 171{
 172        packet->type = INTEL_PT_PSBEND;
 173        return 2;
 174}
 175
 176static int intel_pt_get_tma(const unsigned char *buf, size_t len,
 177                            struct intel_pt_pkt *packet)
 178{
 179        if (len < 7)
 180                return INTEL_PT_NEED_MORE_BYTES;
 181
 182        packet->type = INTEL_PT_TMA;
 183        packet->payload = buf[2] | (buf[3] << 8);
 184        packet->count = buf[5] | ((buf[6] & BIT(0)) << 8);
 185        return 7;
 186}
 187
 188static int intel_pt_get_pad(struct intel_pt_pkt *packet)
 189{
 190        packet->type = INTEL_PT_PAD;
 191        return 1;
 192}
 193
 194static int intel_pt_get_mnt(const unsigned char *buf, size_t len,
 195                            struct intel_pt_pkt *packet)
 196{
 197        if (len < 11)
 198                return INTEL_PT_NEED_MORE_BYTES;
 199        packet->type = INTEL_PT_MNT;
 200        memcpy_le64(&packet->payload, buf + 3, 8);
 201        return 11
 202;
 203}
 204
 205static int intel_pt_get_3byte(const unsigned char *buf, size_t len,
 206                              struct intel_pt_pkt *packet)
 207{
 208        if (len < 3)
 209                return INTEL_PT_NEED_MORE_BYTES;
 210
 211        switch (buf[2]) {
 212        case 0x88: /* MNT */
 213                return intel_pt_get_mnt(buf, len, packet);
 214        default:
 215                return INTEL_PT_BAD_PACKET;
 216        }
 217}
 218
 219static int intel_pt_get_ext(const unsigned char *buf, size_t len,
 220                            struct intel_pt_pkt *packet)
 221{
 222        if (len < 2)
 223                return INTEL_PT_NEED_MORE_BYTES;
 224
 225        switch (buf[1]) {
 226        case 0xa3: /* Long TNT */
 227                return intel_pt_get_long_tnt(buf, len, packet);
 228        case 0x43: /* PIP */
 229                return intel_pt_get_pip(buf, len, packet);
 230        case 0x83: /* TraceStop */
 231                return intel_pt_get_tracestop(packet);
 232        case 0x03: /* CBR */
 233                return intel_pt_get_cbr(buf, len, packet);
 234        case 0xc8: /* VMCS */
 235                return intel_pt_get_vmcs(buf, len, packet);
 236        case 0xf3: /* OVF */
 237                return intel_pt_get_ovf(packet);
 238        case 0x82: /* PSB */
 239                return intel_pt_get_psb(buf, len, packet);
 240        case 0x23: /* PSBEND */
 241                return intel_pt_get_psbend(packet);
 242        case 0x73: /* TMA */
 243                return intel_pt_get_tma(buf, len, packet);
 244        case 0xC3: /* 3-byte header */
 245                return intel_pt_get_3byte(buf, len, packet);
 246        default:
 247                return INTEL_PT_BAD_PACKET;
 248        }
 249}
 250
 251static int intel_pt_get_short_tnt(unsigned int byte,
 252                                  struct intel_pt_pkt *packet)
 253{
 254        int count;
 255
 256        for (count = 6; count; count--) {
 257                if (byte & BIT(7))
 258                        break;
 259                byte <<= 1;
 260        }
 261
 262        packet->type = INTEL_PT_TNT;
 263        packet->count = count;
 264        packet->payload = (uint64_t)byte << 57;
 265
 266        return 1;
 267}
 268
 269static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf,
 270                            size_t len, struct intel_pt_pkt *packet)
 271{
 272        unsigned int offs = 1, shift;
 273        uint64_t payload = byte >> 3;
 274
 275        byte >>= 2;
 276        len -= 1;
 277        for (shift = 5; byte & 1; shift += 7) {
 278                if (offs > 9)
 279                        return INTEL_PT_BAD_PACKET;
 280                if (len < offs)
 281                        return INTEL_PT_NEED_MORE_BYTES;
 282                byte = buf[offs++];
 283                payload |= (byte >> 1) << shift;
 284        }
 285
 286        packet->type = INTEL_PT_CYC;
 287        packet->payload = payload;
 288        return offs;
 289}
 290
 291static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
 292                           const unsigned char *buf, size_t len,
 293                           struct intel_pt_pkt *packet)
 294{
 295        int ip_len;
 296
 297        packet->count = byte >> 5;
 298
 299        switch (packet->count) {
 300        case 0:
 301                ip_len = 0;
 302                break;
 303        case 1:
 304                if (len < 3)
 305                        return INTEL_PT_NEED_MORE_BYTES;
 306                ip_len = 2;
 307                packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
 308                break;
 309        case 2:
 310                if (len < 5)
 311                        return INTEL_PT_NEED_MORE_BYTES;
 312                ip_len = 4;
 313                packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
 314                break;
 315        case 3:
 316        case 4:
 317                if (len < 7)
 318                        return INTEL_PT_NEED_MORE_BYTES;
 319                ip_len = 6;
 320                memcpy_le64(&packet->payload, buf + 1, 6);
 321                break;
 322        case 6:
 323                if (len < 9)
 324                        return INTEL_PT_NEED_MORE_BYTES;
 325                ip_len = 8;
 326                packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
 327                break;
 328        default:
 329                return INTEL_PT_BAD_PACKET;
 330        }
 331
 332        packet->type = type;
 333
 334        return ip_len + 1;
 335}
 336
 337static int intel_pt_get_mode(const unsigned char *buf, size_t len,
 338                             struct intel_pt_pkt *packet)
 339{
 340        if (len < 2)
 341                return INTEL_PT_NEED_MORE_BYTES;
 342
 343        switch (buf[1] >> 5) {
 344        case 0:
 345                packet->type = INTEL_PT_MODE_EXEC;
 346                switch (buf[1] & 3) {
 347                case 0:
 348                        packet->payload = 16;
 349                        break;
 350                case 1:
 351                        packet->payload = 64;
 352                        break;
 353                case 2:
 354                        packet->payload = 32;
 355                        break;
 356                default:
 357                        return INTEL_PT_BAD_PACKET;
 358                }
 359                break;
 360        case 1:
 361                packet->type = INTEL_PT_MODE_TSX;
 362                if ((buf[1] & 3) == 3)
 363                        return INTEL_PT_BAD_PACKET;
 364                packet->payload = buf[1] & 3;
 365                break;
 366        default:
 367                return INTEL_PT_BAD_PACKET;
 368        }
 369
 370        return 2;
 371}
 372
 373static int intel_pt_get_tsc(const unsigned char *buf, size_t len,
 374                            struct intel_pt_pkt *packet)
 375{
 376        if (len < 8)
 377                return INTEL_PT_NEED_MORE_BYTES;
 378        packet->type = INTEL_PT_TSC;
 379        memcpy_le64(&packet->payload, buf + 1, 7);
 380        return 8;
 381}
 382
 383static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
 384                            struct intel_pt_pkt *packet)
 385{
 386        if (len < 2)
 387                return INTEL_PT_NEED_MORE_BYTES;
 388        packet->type = INTEL_PT_MTC;
 389        packet->payload = buf[1];
 390        return 2;
 391}
 392
 393static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 394                                  struct intel_pt_pkt *packet)
 395{
 396        unsigned int byte;
 397
 398        memset(packet, 0, sizeof(struct intel_pt_pkt));
 399
 400        if (!len)
 401                return INTEL_PT_NEED_MORE_BYTES;
 402
 403        byte = buf[0];
 404        if (!(byte & BIT(0))) {
 405                if (byte == 0)
 406                        return intel_pt_get_pad(packet);
 407                if (byte == 2)
 408                        return intel_pt_get_ext(buf, len, packet);
 409                return intel_pt_get_short_tnt(byte, packet);
 410        }
 411
 412        if ((byte & 2))
 413                return intel_pt_get_cyc(byte, buf, len, packet);
 414
 415        switch (byte & 0x1f) {
 416        case 0x0D:
 417                return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
 418        case 0x11:
 419                return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
 420                                       packet);
 421        case 0x01:
 422                return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
 423                                       packet);
 424        case 0x1D:
 425                return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
 426        case 0x19:
 427                switch (byte) {
 428                case 0x99:
 429                        return intel_pt_get_mode(buf, len, packet);
 430                case 0x19:
 431                        return intel_pt_get_tsc(buf, len, packet);
 432                case 0x59:
 433                        return intel_pt_get_mtc(buf, len, packet);
 434                default:
 435                        return INTEL_PT_BAD_PACKET;
 436                }
 437        default:
 438                return INTEL_PT_BAD_PACKET;
 439        }
 440}
 441
 442int intel_pt_get_packet(const unsigned char *buf, size_t len,
 443                        struct intel_pt_pkt *packet)
 444{
 445        int ret;
 446
 447        ret = intel_pt_do_get_packet(buf, len, packet);
 448        if (ret > 0) {
 449                while (ret < 8 && len > (size_t)ret && !buf[ret])
 450                        ret += 1;
 451        }
 452        return ret;
 453}
 454
 455int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 456                      size_t buf_len)
 457{
 458        int ret, i, nr;
 459        unsigned long long payload = packet->payload;
 460        const char *name = intel_pt_pkt_name(packet->type);
 461
 462        switch (packet->type) {
 463        case INTEL_PT_BAD:
 464        case INTEL_PT_PAD:
 465        case INTEL_PT_PSB:
 466        case INTEL_PT_PSBEND:
 467        case INTEL_PT_TRACESTOP:
 468        case INTEL_PT_OVF:
 469                return snprintf(buf, buf_len, "%s", name);
 470        case INTEL_PT_TNT: {
 471                size_t blen = buf_len;
 472
 473                ret = snprintf(buf, blen, "%s ", name);
 474                if (ret < 0)
 475                        return ret;
 476                buf += ret;
 477                blen -= ret;
 478                for (i = 0; i < packet->count; i++) {
 479                        if (payload & BIT63)
 480                                ret = snprintf(buf, blen, "T");
 481                        else
 482                                ret = snprintf(buf, blen, "N");
 483                        if (ret < 0)
 484                                return ret;
 485                        buf += ret;
 486                        blen -= ret;
 487                        payload <<= 1;
 488                }
 489                ret = snprintf(buf, blen, " (%d)", packet->count);
 490                if (ret < 0)
 491                        return ret;
 492                blen -= ret;
 493                return buf_len - blen;
 494        }
 495        case INTEL_PT_TIP_PGD:
 496        case INTEL_PT_TIP_PGE:
 497        case INTEL_PT_TIP:
 498        case INTEL_PT_FUP:
 499                if (!(packet->count))
 500                        return snprintf(buf, buf_len, "%s no ip", name);
 501        case INTEL_PT_CYC:
 502        case INTEL_PT_VMCS:
 503        case INTEL_PT_MTC:
 504        case INTEL_PT_MNT:
 505        case INTEL_PT_CBR:
 506        case INTEL_PT_TSC:
 507                return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
 508        case INTEL_PT_TMA:
 509                return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name,
 510                                (unsigned)payload, packet->count);
 511        case INTEL_PT_MODE_EXEC:
 512                return snprintf(buf, buf_len, "%s %lld", name, payload);
 513        case INTEL_PT_MODE_TSX:
 514                return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
 515                                name, (unsigned)(payload >> 1) & 1,
 516                                (unsigned)payload & 1);
 517        case INTEL_PT_PIP:
 518                nr = packet->payload & NR_FLAG ? 1 : 0;
 519                payload &= ~NR_FLAG;
 520                ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
 521                               name, payload, nr);
 522                return ret;
 523        default:
 524                break;
 525        }
 526        return snprintf(buf, buf_len, "%s 0x%llx (%d)",
 527                        name, payload, packet->count);
 528}
 529