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        switch (byte >> 5) {
 296        case 0:
 297                packet->count = 0;
 298                break;
 299        case 1:
 300                if (len < 3)
 301                        return INTEL_PT_NEED_MORE_BYTES;
 302                packet->count = 2;
 303                packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
 304                break;
 305        case 2:
 306                if (len < 5)
 307                        return INTEL_PT_NEED_MORE_BYTES;
 308                packet->count = 4;
 309                packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
 310                break;
 311        case 3:
 312        case 6:
 313                if (len < 7)
 314                        return INTEL_PT_NEED_MORE_BYTES;
 315                packet->count = 6;
 316                memcpy_le64(&packet->payload, buf + 1, 6);
 317                break;
 318        default:
 319                return INTEL_PT_BAD_PACKET;
 320        }
 321
 322        packet->type = type;
 323
 324        return packet->count + 1;
 325}
 326
 327static int intel_pt_get_mode(const unsigned char *buf, size_t len,
 328                             struct intel_pt_pkt *packet)
 329{
 330        if (len < 2)
 331                return INTEL_PT_NEED_MORE_BYTES;
 332
 333        switch (buf[1] >> 5) {
 334        case 0:
 335                packet->type = INTEL_PT_MODE_EXEC;
 336                switch (buf[1] & 3) {
 337                case 0:
 338                        packet->payload = 16;
 339                        break;
 340                case 1:
 341                        packet->payload = 64;
 342                        break;
 343                case 2:
 344                        packet->payload = 32;
 345                        break;
 346                default:
 347                        return INTEL_PT_BAD_PACKET;
 348                }
 349                break;
 350        case 1:
 351                packet->type = INTEL_PT_MODE_TSX;
 352                if ((buf[1] & 3) == 3)
 353                        return INTEL_PT_BAD_PACKET;
 354                packet->payload = buf[1] & 3;
 355                break;
 356        default:
 357                return INTEL_PT_BAD_PACKET;
 358        }
 359
 360        return 2;
 361}
 362
 363static int intel_pt_get_tsc(const unsigned char *buf, size_t len,
 364                            struct intel_pt_pkt *packet)
 365{
 366        if (len < 8)
 367                return INTEL_PT_NEED_MORE_BYTES;
 368        packet->type = INTEL_PT_TSC;
 369        memcpy_le64(&packet->payload, buf + 1, 7);
 370        return 8;
 371}
 372
 373static int intel_pt_get_mtc(const unsigned char *buf, size_t len,
 374                            struct intel_pt_pkt *packet)
 375{
 376        if (len < 2)
 377                return INTEL_PT_NEED_MORE_BYTES;
 378        packet->type = INTEL_PT_MTC;
 379        packet->payload = buf[1];
 380        return 2;
 381}
 382
 383static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
 384                                  struct intel_pt_pkt *packet)
 385{
 386        unsigned int byte;
 387
 388        memset(packet, 0, sizeof(struct intel_pt_pkt));
 389
 390        if (!len)
 391                return INTEL_PT_NEED_MORE_BYTES;
 392
 393        byte = buf[0];
 394        if (!(byte & BIT(0))) {
 395                if (byte == 0)
 396                        return intel_pt_get_pad(packet);
 397                if (byte == 2)
 398                        return intel_pt_get_ext(buf, len, packet);
 399                return intel_pt_get_short_tnt(byte, packet);
 400        }
 401
 402        if ((byte & 2))
 403                return intel_pt_get_cyc(byte, buf, len, packet);
 404
 405        switch (byte & 0x1f) {
 406        case 0x0D:
 407                return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
 408        case 0x11:
 409                return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
 410                                       packet);
 411        case 0x01:
 412                return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
 413                                       packet);
 414        case 0x1D:
 415                return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
 416        case 0x19:
 417                switch (byte) {
 418                case 0x99:
 419                        return intel_pt_get_mode(buf, len, packet);
 420                case 0x19:
 421                        return intel_pt_get_tsc(buf, len, packet);
 422                case 0x59:
 423                        return intel_pt_get_mtc(buf, len, packet);
 424                default:
 425                        return INTEL_PT_BAD_PACKET;
 426                }
 427        default:
 428                return INTEL_PT_BAD_PACKET;
 429        }
 430}
 431
 432int intel_pt_get_packet(const unsigned char *buf, size_t len,
 433                        struct intel_pt_pkt *packet)
 434{
 435        int ret;
 436
 437        ret = intel_pt_do_get_packet(buf, len, packet);
 438        if (ret > 0) {
 439                while (ret < 8 && len > (size_t)ret && !buf[ret])
 440                        ret += 1;
 441        }
 442        return ret;
 443}
 444
 445int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
 446                      size_t buf_len)
 447{
 448        int ret, i, nr;
 449        unsigned long long payload = packet->payload;
 450        const char *name = intel_pt_pkt_name(packet->type);
 451
 452        switch (packet->type) {
 453        case INTEL_PT_BAD:
 454        case INTEL_PT_PAD:
 455        case INTEL_PT_PSB:
 456        case INTEL_PT_PSBEND:
 457        case INTEL_PT_TRACESTOP:
 458        case INTEL_PT_OVF:
 459                return snprintf(buf, buf_len, "%s", name);
 460        case INTEL_PT_TNT: {
 461                size_t blen = buf_len;
 462
 463                ret = snprintf(buf, blen, "%s ", name);
 464                if (ret < 0)
 465                        return ret;
 466                buf += ret;
 467                blen -= ret;
 468                for (i = 0; i < packet->count; i++) {
 469                        if (payload & BIT63)
 470                                ret = snprintf(buf, blen, "T");
 471                        else
 472                                ret = snprintf(buf, blen, "N");
 473                        if (ret < 0)
 474                                return ret;
 475                        buf += ret;
 476                        blen -= ret;
 477                        payload <<= 1;
 478                }
 479                ret = snprintf(buf, blen, " (%d)", packet->count);
 480                if (ret < 0)
 481                        return ret;
 482                blen -= ret;
 483                return buf_len - blen;
 484        }
 485        case INTEL_PT_TIP_PGD:
 486        case INTEL_PT_TIP_PGE:
 487        case INTEL_PT_TIP:
 488        case INTEL_PT_FUP:
 489                if (!(packet->count))
 490                        return snprintf(buf, buf_len, "%s no ip", name);
 491        case INTEL_PT_CYC:
 492        case INTEL_PT_VMCS:
 493        case INTEL_PT_MTC:
 494        case INTEL_PT_MNT:
 495        case INTEL_PT_CBR:
 496        case INTEL_PT_TSC:
 497                return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
 498        case INTEL_PT_TMA:
 499                return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name,
 500                                (unsigned)payload, packet->count);
 501        case INTEL_PT_MODE_EXEC:
 502                return snprintf(buf, buf_len, "%s %lld", name, payload);
 503        case INTEL_PT_MODE_TSX:
 504                return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
 505                                name, (unsigned)(payload >> 1) & 1,
 506                                (unsigned)payload & 1);
 507        case INTEL_PT_PIP:
 508                nr = packet->payload & NR_FLAG ? 1 : 0;
 509                payload &= ~NR_FLAG;
 510                ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)",
 511                               name, payload, nr);
 512                return ret;
 513        default:
 514                break;
 515        }
 516        return snprintf(buf, buf_len, "%s 0x%llx (%d)",
 517                        name, payload, packet->count);
 518}
 519