| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * intel_pt_decoder.c: Intel Processor Trace support |
|---|
| 3 | 4 | * 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 | 5 | */ |
|---|
| 15 | 6 | |
|---|
| 16 | 7 | #ifndef _GNU_SOURCE |
|---|
| .. | .. |
|---|
| 23 | 14 | #include <stdint.h> |
|---|
| 24 | 15 | #include <inttypes.h> |
|---|
| 25 | 16 | #include <linux/compiler.h> |
|---|
| 17 | +#include <linux/string.h> |
|---|
| 18 | +#include <linux/zalloc.h> |
|---|
| 26 | 19 | |
|---|
| 27 | | -#include "../cache.h" |
|---|
| 28 | | -#include "../util.h" |
|---|
| 29 | 20 | #include "../auxtrace.h" |
|---|
| 30 | 21 | |
|---|
| 31 | 22 | #include "intel-pt-insn-decoder.h" |
|---|
| 32 | 23 | #include "intel-pt-pkt-decoder.h" |
|---|
| 33 | 24 | #include "intel-pt-decoder.h" |
|---|
| 34 | 25 | #include "intel-pt-log.h" |
|---|
| 26 | + |
|---|
| 27 | +#define BITULL(x) (1ULL << (x)) |
|---|
| 28 | + |
|---|
| 29 | +/* IA32_RTIT_CTL MSR bits */ |
|---|
| 30 | +#define INTEL_PT_CYC_ENABLE BITULL(1) |
|---|
| 31 | +#define INTEL_PT_CYC_THRESHOLD (BITULL(22) | BITULL(21) | BITULL(20) | BITULL(19)) |
|---|
| 32 | +#define INTEL_PT_CYC_THRESHOLD_SHIFT 19 |
|---|
| 35 | 33 | |
|---|
| 36 | 34 | #define INTEL_PT_BLK_SIZE 1024 |
|---|
| 37 | 35 | |
|---|
| .. | .. |
|---|
| 64 | 62 | INTEL_PT_STATE_TIP_PGD, |
|---|
| 65 | 63 | INTEL_PT_STATE_FUP, |
|---|
| 66 | 64 | INTEL_PT_STATE_FUP_NO_TIP, |
|---|
| 65 | + INTEL_PT_STATE_RESAMPLE, |
|---|
| 67 | 66 | }; |
|---|
| 68 | 67 | |
|---|
| 69 | 68 | static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state) |
|---|
| .. | .. |
|---|
| 74 | 73 | case INTEL_PT_STATE_ERR_RESYNC: |
|---|
| 75 | 74 | case INTEL_PT_STATE_IN_SYNC: |
|---|
| 76 | 75 | case INTEL_PT_STATE_TNT_CONT: |
|---|
| 76 | + case INTEL_PT_STATE_RESAMPLE: |
|---|
| 77 | 77 | return true; |
|---|
| 78 | 78 | case INTEL_PT_STATE_TNT: |
|---|
| 79 | 79 | case INTEL_PT_STATE_TIP: |
|---|
| .. | .. |
|---|
| 104 | 104 | uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, |
|---|
| 105 | 105 | uint64_t max_insn_cnt, void *data); |
|---|
| 106 | 106 | bool (*pgd_ip)(uint64_t ip, void *data); |
|---|
| 107 | + int (*lookahead)(void *data, intel_pt_lookahead_cb_t cb, void *cb_data); |
|---|
| 107 | 108 | void *data; |
|---|
| 108 | 109 | struct intel_pt_state state; |
|---|
| 109 | 110 | const unsigned char *buf; |
|---|
| .. | .. |
|---|
| 116 | 117 | bool have_cyc; |
|---|
| 117 | 118 | bool fixup_last_mtc; |
|---|
| 118 | 119 | bool have_last_ip; |
|---|
| 120 | + bool in_psb; |
|---|
| 121 | + bool hop; |
|---|
| 122 | + bool hop_psb_fup; |
|---|
| 123 | + bool leap; |
|---|
| 119 | 124 | enum intel_pt_param_flags flags; |
|---|
| 120 | 125 | uint64_t pos; |
|---|
| 121 | 126 | uint64_t last_ip; |
|---|
| .. | .. |
|---|
| 124 | 129 | uint64_t timestamp; |
|---|
| 125 | 130 | uint64_t tsc_timestamp; |
|---|
| 126 | 131 | uint64_t ref_timestamp; |
|---|
| 132 | + uint64_t buf_timestamp; |
|---|
| 127 | 133 | uint64_t sample_timestamp; |
|---|
| 128 | 134 | uint64_t ret_addr; |
|---|
| 129 | 135 | uint64_t ctc_timestamp; |
|---|
| .. | .. |
|---|
| 139 | 145 | int mtc_shift; |
|---|
| 140 | 146 | struct intel_pt_stack stack; |
|---|
| 141 | 147 | enum intel_pt_pkt_state pkt_state; |
|---|
| 148 | + enum intel_pt_pkt_ctx pkt_ctx; |
|---|
| 149 | + enum intel_pt_pkt_ctx prev_pkt_ctx; |
|---|
| 150 | + enum intel_pt_blk_type blk_type; |
|---|
| 151 | + int blk_type_pos; |
|---|
| 142 | 152 | struct intel_pt_pkt packet; |
|---|
| 143 | 153 | struct intel_pt_pkt tnt; |
|---|
| 144 | 154 | int pkt_step; |
|---|
| .. | .. |
|---|
| 160 | 170 | uint64_t period_mask; |
|---|
| 161 | 171 | uint64_t period_ticks; |
|---|
| 162 | 172 | uint64_t last_masked_timestamp; |
|---|
| 173 | + uint64_t tot_cyc_cnt; |
|---|
| 174 | + uint64_t sample_tot_cyc_cnt; |
|---|
| 175 | + uint64_t base_cyc_cnt; |
|---|
| 176 | + uint64_t cyc_cnt_timestamp; |
|---|
| 177 | + uint64_t ctl; |
|---|
| 178 | + uint64_t cyc_threshold; |
|---|
| 179 | + double tsc_to_cyc; |
|---|
| 163 | 180 | bool continuous_period; |
|---|
| 164 | 181 | bool overflow; |
|---|
| 165 | 182 | bool set_fup_tx_flags; |
|---|
| .. | .. |
|---|
| 167 | 184 | bool set_fup_mwait; |
|---|
| 168 | 185 | bool set_fup_pwre; |
|---|
| 169 | 186 | bool set_fup_exstop; |
|---|
| 187 | + bool set_fup_bep; |
|---|
| 188 | + bool sample_cyc; |
|---|
| 170 | 189 | unsigned int fup_tx_flags; |
|---|
| 171 | 190 | unsigned int tx_flags; |
|---|
| 172 | 191 | uint64_t fup_ptw_payload; |
|---|
| .. | .. |
|---|
| 192 | 211 | x >>= 1; |
|---|
| 193 | 212 | |
|---|
| 194 | 213 | return x << i; |
|---|
| 214 | +} |
|---|
| 215 | + |
|---|
| 216 | +static uint64_t intel_pt_cyc_threshold(uint64_t ctl) |
|---|
| 217 | +{ |
|---|
| 218 | + if (!(ctl & INTEL_PT_CYC_ENABLE)) |
|---|
| 219 | + return 0; |
|---|
| 220 | + |
|---|
| 221 | + return (ctl & INTEL_PT_CYC_THRESHOLD) >> INTEL_PT_CYC_THRESHOLD_SHIFT; |
|---|
| 195 | 222 | } |
|---|
| 196 | 223 | |
|---|
| 197 | 224 | static void intel_pt_setup_period(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 226 | 253 | decoder->get_trace = params->get_trace; |
|---|
| 227 | 254 | decoder->walk_insn = params->walk_insn; |
|---|
| 228 | 255 | decoder->pgd_ip = params->pgd_ip; |
|---|
| 256 | + decoder->lookahead = params->lookahead; |
|---|
| 229 | 257 | decoder->data = params->data; |
|---|
| 230 | 258 | decoder->return_compression = params->return_compression; |
|---|
| 231 | 259 | decoder->branch_enable = params->branch_enable; |
|---|
| 260 | + decoder->hop = params->quick >= 1; |
|---|
| 261 | + decoder->leap = params->quick >= 2; |
|---|
| 232 | 262 | |
|---|
| 233 | 263 | decoder->flags = params->flags; |
|---|
| 234 | 264 | |
|---|
| 265 | + decoder->ctl = params->ctl; |
|---|
| 235 | 266 | decoder->period = params->period; |
|---|
| 236 | 267 | decoder->period_type = params->period_type; |
|---|
| 237 | 268 | |
|---|
| 238 | 269 | decoder->max_non_turbo_ratio = params->max_non_turbo_ratio; |
|---|
| 239 | 270 | decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio; |
|---|
| 271 | + |
|---|
| 272 | + decoder->cyc_threshold = intel_pt_cyc_threshold(decoder->ctl); |
|---|
| 240 | 273 | |
|---|
| 241 | 274 | intel_pt_setup_period(decoder); |
|---|
| 242 | 275 | |
|---|
| .. | .. |
|---|
| 268 | 301 | intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d); |
|---|
| 269 | 302 | intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult); |
|---|
| 270 | 303 | intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip); |
|---|
| 304 | + |
|---|
| 305 | + if (decoder->hop) |
|---|
| 306 | + intel_pt_log("Hop mode: decoding FUP and TIPs, but not TNT\n"); |
|---|
| 271 | 307 | |
|---|
| 272 | 308 | return decoder; |
|---|
| 273 | 309 | } |
|---|
| .. | .. |
|---|
| 479 | 515 | return -EBADMSG; |
|---|
| 480 | 516 | } |
|---|
| 481 | 517 | |
|---|
| 482 | | -static int intel_pt_get_data(struct intel_pt_decoder *decoder) |
|---|
| 518 | +static inline void intel_pt_update_sample_time(struct intel_pt_decoder *decoder) |
|---|
| 519 | +{ |
|---|
| 520 | + decoder->sample_timestamp = decoder->timestamp; |
|---|
| 521 | + decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; |
|---|
| 522 | +} |
|---|
| 523 | + |
|---|
| 524 | +static void intel_pt_reposition(struct intel_pt_decoder *decoder) |
|---|
| 525 | +{ |
|---|
| 526 | + decoder->ip = 0; |
|---|
| 527 | + decoder->pkt_state = INTEL_PT_STATE_NO_PSB; |
|---|
| 528 | + decoder->timestamp = 0; |
|---|
| 529 | + decoder->have_tma = false; |
|---|
| 530 | +} |
|---|
| 531 | + |
|---|
| 532 | +static int intel_pt_get_data(struct intel_pt_decoder *decoder, bool reposition) |
|---|
| 483 | 533 | { |
|---|
| 484 | 534 | struct intel_pt_buffer buffer = { .buf = 0, }; |
|---|
| 485 | 535 | int ret; |
|---|
| .. | .. |
|---|
| 496 | 546 | intel_pt_log("No more data\n"); |
|---|
| 497 | 547 | return -ENODATA; |
|---|
| 498 | 548 | } |
|---|
| 499 | | - if (!buffer.consecutive) { |
|---|
| 500 | | - decoder->ip = 0; |
|---|
| 501 | | - decoder->pkt_state = INTEL_PT_STATE_NO_PSB; |
|---|
| 549 | + decoder->buf_timestamp = buffer.ref_timestamp; |
|---|
| 550 | + if (!buffer.consecutive || reposition) { |
|---|
| 551 | + intel_pt_reposition(decoder); |
|---|
| 502 | 552 | decoder->ref_timestamp = buffer.ref_timestamp; |
|---|
| 503 | | - decoder->timestamp = 0; |
|---|
| 504 | | - decoder->have_tma = false; |
|---|
| 505 | 553 | decoder->state.trace_nr = buffer.trace_nr; |
|---|
| 506 | 554 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", |
|---|
| 507 | 555 | decoder->ref_timestamp); |
|---|
| .. | .. |
|---|
| 511 | 559 | return 0; |
|---|
| 512 | 560 | } |
|---|
| 513 | 561 | |
|---|
| 514 | | -static int intel_pt_get_next_data(struct intel_pt_decoder *decoder) |
|---|
| 562 | +static int intel_pt_get_next_data(struct intel_pt_decoder *decoder, |
|---|
| 563 | + bool reposition) |
|---|
| 515 | 564 | { |
|---|
| 516 | 565 | if (!decoder->next_buf) |
|---|
| 517 | | - return intel_pt_get_data(decoder); |
|---|
| 566 | + return intel_pt_get_data(decoder, reposition); |
|---|
| 518 | 567 | |
|---|
| 519 | 568 | decoder->buf = decoder->next_buf; |
|---|
| 520 | 569 | decoder->len = decoder->next_len; |
|---|
| .. | .. |
|---|
| 533 | 582 | len = decoder->len; |
|---|
| 534 | 583 | memcpy(buf, decoder->buf, len); |
|---|
| 535 | 584 | |
|---|
| 536 | | - ret = intel_pt_get_data(decoder); |
|---|
| 585 | + ret = intel_pt_get_data(decoder, false); |
|---|
| 537 | 586 | if (ret) { |
|---|
| 538 | 587 | decoder->pos += old_len; |
|---|
| 539 | 588 | return ret < 0 ? ret : -EINVAL; |
|---|
| .. | .. |
|---|
| 545 | 594 | memcpy(buf + len, decoder->buf, n); |
|---|
| 546 | 595 | len += n; |
|---|
| 547 | 596 | |
|---|
| 548 | | - ret = intel_pt_get_packet(buf, len, &decoder->packet); |
|---|
| 597 | + decoder->prev_pkt_ctx = decoder->pkt_ctx; |
|---|
| 598 | + ret = intel_pt_get_packet(buf, len, &decoder->packet, &decoder->pkt_ctx); |
|---|
| 549 | 599 | if (ret < (int)old_len) { |
|---|
| 550 | 600 | decoder->next_buf = decoder->buf; |
|---|
| 551 | 601 | decoder->next_len = decoder->len; |
|---|
| .. | .. |
|---|
| 580 | 630 | { |
|---|
| 581 | 631 | struct intel_pt_pkt_info pkt_info; |
|---|
| 582 | 632 | const unsigned char *buf = decoder->buf; |
|---|
| 633 | + enum intel_pt_pkt_ctx pkt_ctx = decoder->pkt_ctx; |
|---|
| 583 | 634 | size_t len = decoder->len; |
|---|
| 584 | 635 | int ret; |
|---|
| 585 | 636 | |
|---|
| .. | .. |
|---|
| 598 | 649 | if (!len) |
|---|
| 599 | 650 | return INTEL_PT_NEED_MORE_BYTES; |
|---|
| 600 | 651 | |
|---|
| 601 | | - ret = intel_pt_get_packet(buf, len, &pkt_info.packet); |
|---|
| 652 | + ret = intel_pt_get_packet(buf, len, &pkt_info.packet, |
|---|
| 653 | + &pkt_ctx); |
|---|
| 602 | 654 | if (!ret) |
|---|
| 603 | 655 | return INTEL_PT_NEED_MORE_BYTES; |
|---|
| 604 | 656 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 673 | 725 | case INTEL_PT_MNT: |
|---|
| 674 | 726 | case INTEL_PT_PTWRITE: |
|---|
| 675 | 727 | case INTEL_PT_PTWRITE_IP: |
|---|
| 728 | + case INTEL_PT_BBP: |
|---|
| 729 | + case INTEL_PT_BIP: |
|---|
| 730 | + case INTEL_PT_BEP: |
|---|
| 731 | + case INTEL_PT_BEP_IP: |
|---|
| 676 | 732 | return 0; |
|---|
| 677 | 733 | |
|---|
| 678 | 734 | case INTEL_PT_MTC: |
|---|
| .. | .. |
|---|
| 859 | 915 | decoder->len -= decoder->pkt_step; |
|---|
| 860 | 916 | |
|---|
| 861 | 917 | if (!decoder->len) { |
|---|
| 862 | | - ret = intel_pt_get_next_data(decoder); |
|---|
| 918 | + ret = intel_pt_get_next_data(decoder, false); |
|---|
| 863 | 919 | if (ret) |
|---|
| 864 | 920 | return ret; |
|---|
| 865 | 921 | } |
|---|
| 866 | 922 | |
|---|
| 923 | + decoder->prev_pkt_ctx = decoder->pkt_ctx; |
|---|
| 867 | 924 | ret = intel_pt_get_packet(decoder->buf, decoder->len, |
|---|
| 868 | | - &decoder->packet); |
|---|
| 869 | | - if (ret == INTEL_PT_NEED_MORE_BYTES && |
|---|
| 925 | + &decoder->packet, &decoder->pkt_ctx); |
|---|
| 926 | + if (ret == INTEL_PT_NEED_MORE_BYTES && BITS_PER_LONG == 32 && |
|---|
| 870 | 927 | decoder->len < INTEL_PT_PKT_MAX_SZ && !decoder->next_buf) { |
|---|
| 871 | 928 | ret = intel_pt_get_split_packet(decoder); |
|---|
| 872 | 929 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 1057 | 1114 | |
|---|
| 1058 | 1115 | static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) |
|---|
| 1059 | 1116 | { |
|---|
| 1117 | + enum intel_pt_sample_type type = decoder->state.type; |
|---|
| 1060 | 1118 | bool ret = false; |
|---|
| 1119 | + |
|---|
| 1120 | + decoder->state.type &= ~INTEL_PT_BRANCH; |
|---|
| 1061 | 1121 | |
|---|
| 1062 | 1122 | if (decoder->set_fup_tx_flags) { |
|---|
| 1063 | 1123 | decoder->set_fup_tx_flags = false; |
|---|
| 1064 | 1124 | decoder->tx_flags = decoder->fup_tx_flags; |
|---|
| 1065 | | - decoder->state.type = INTEL_PT_TRANSACTION; |
|---|
| 1125 | + decoder->state.type |= INTEL_PT_TRANSACTION; |
|---|
| 1066 | 1126 | if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX) |
|---|
| 1067 | 1127 | decoder->state.type |= INTEL_PT_BRANCH; |
|---|
| 1068 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 1069 | | - decoder->state.to_ip = 0; |
|---|
| 1070 | 1128 | decoder->state.flags = decoder->fup_tx_flags; |
|---|
| 1071 | | - return true; |
|---|
| 1129 | + ret = true; |
|---|
| 1072 | 1130 | } |
|---|
| 1073 | 1131 | if (decoder->set_fup_ptw) { |
|---|
| 1074 | 1132 | decoder->set_fup_ptw = false; |
|---|
| 1075 | | - decoder->state.type = INTEL_PT_PTW; |
|---|
| 1133 | + decoder->state.type |= INTEL_PT_PTW; |
|---|
| 1076 | 1134 | decoder->state.flags |= INTEL_PT_FUP_IP; |
|---|
| 1077 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 1078 | | - decoder->state.to_ip = 0; |
|---|
| 1079 | 1135 | decoder->state.ptw_payload = decoder->fup_ptw_payload; |
|---|
| 1080 | | - return true; |
|---|
| 1136 | + ret = true; |
|---|
| 1081 | 1137 | } |
|---|
| 1082 | 1138 | if (decoder->set_fup_mwait) { |
|---|
| 1083 | 1139 | decoder->set_fup_mwait = false; |
|---|
| 1084 | | - decoder->state.type = INTEL_PT_MWAIT_OP; |
|---|
| 1085 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 1086 | | - decoder->state.to_ip = 0; |
|---|
| 1140 | + decoder->state.type |= INTEL_PT_MWAIT_OP; |
|---|
| 1087 | 1141 | decoder->state.mwait_payload = decoder->fup_mwait_payload; |
|---|
| 1088 | 1142 | ret = true; |
|---|
| 1089 | 1143 | } |
|---|
| 1090 | 1144 | if (decoder->set_fup_pwre) { |
|---|
| 1091 | 1145 | decoder->set_fup_pwre = false; |
|---|
| 1092 | 1146 | decoder->state.type |= INTEL_PT_PWR_ENTRY; |
|---|
| 1093 | | - decoder->state.type &= ~INTEL_PT_BRANCH; |
|---|
| 1094 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 1095 | | - decoder->state.to_ip = 0; |
|---|
| 1096 | 1147 | decoder->state.pwre_payload = decoder->fup_pwre_payload; |
|---|
| 1097 | 1148 | ret = true; |
|---|
| 1098 | 1149 | } |
|---|
| 1099 | 1150 | if (decoder->set_fup_exstop) { |
|---|
| 1100 | 1151 | decoder->set_fup_exstop = false; |
|---|
| 1101 | 1152 | decoder->state.type |= INTEL_PT_EX_STOP; |
|---|
| 1102 | | - decoder->state.type &= ~INTEL_PT_BRANCH; |
|---|
| 1103 | 1153 | decoder->state.flags |= INTEL_PT_FUP_IP; |
|---|
| 1154 | + ret = true; |
|---|
| 1155 | + } |
|---|
| 1156 | + if (decoder->set_fup_bep) { |
|---|
| 1157 | + decoder->set_fup_bep = false; |
|---|
| 1158 | + decoder->state.type |= INTEL_PT_BLK_ITEMS; |
|---|
| 1159 | + ret = true; |
|---|
| 1160 | + } |
|---|
| 1161 | + if (decoder->overflow) { |
|---|
| 1162 | + decoder->overflow = false; |
|---|
| 1163 | + if (!ret && !decoder->pge) { |
|---|
| 1164 | + if (decoder->hop) { |
|---|
| 1165 | + decoder->state.type = 0; |
|---|
| 1166 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
|---|
| 1167 | + } |
|---|
| 1168 | + decoder->pge = true; |
|---|
| 1169 | + decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN; |
|---|
| 1170 | + decoder->state.from_ip = 0; |
|---|
| 1171 | + decoder->state.to_ip = decoder->ip; |
|---|
| 1172 | + return true; |
|---|
| 1173 | + } |
|---|
| 1174 | + } |
|---|
| 1175 | + if (ret) { |
|---|
| 1104 | 1176 | decoder->state.from_ip = decoder->ip; |
|---|
| 1105 | 1177 | decoder->state.to_ip = 0; |
|---|
| 1106 | | - ret = true; |
|---|
| 1178 | + } else { |
|---|
| 1179 | + decoder->state.type = type; |
|---|
| 1107 | 1180 | } |
|---|
| 1108 | 1181 | return ret; |
|---|
| 1109 | 1182 | } |
|---|
| .. | .. |
|---|
| 1176 | 1249 | decoder->pge = false; |
|---|
| 1177 | 1250 | decoder->continuous_period = false; |
|---|
| 1178 | 1251 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1179 | | - decoder->state.to_ip = 0; |
|---|
| 1252 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 1180 | 1253 | return 0; |
|---|
| 1181 | 1254 | } |
|---|
| 1182 | 1255 | if (err == INTEL_PT_RETURN) |
|---|
| .. | .. |
|---|
| 1190 | 1263 | decoder->continuous_period = false; |
|---|
| 1191 | 1264 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1192 | 1265 | decoder->state.from_ip = decoder->ip; |
|---|
| 1193 | | - decoder->state.to_ip = 0; |
|---|
| 1194 | | - if (decoder->packet.count != 0) |
|---|
| 1266 | + if (decoder->packet.count == 0) { |
|---|
| 1267 | + decoder->state.to_ip = 0; |
|---|
| 1268 | + } else { |
|---|
| 1269 | + decoder->state.to_ip = decoder->last_ip; |
|---|
| 1195 | 1270 | decoder->ip = decoder->last_ip; |
|---|
| 1271 | + } |
|---|
| 1272 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 1196 | 1273 | } else { |
|---|
| 1197 | 1274 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1198 | 1275 | decoder->state.from_ip = decoder->ip; |
|---|
| .. | .. |
|---|
| 1219 | 1296 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1220 | 1297 | decoder->ip = to_ip; |
|---|
| 1221 | 1298 | decoder->state.from_ip = decoder->ip; |
|---|
| 1222 | | - decoder->state.to_ip = 0; |
|---|
| 1299 | + decoder->state.to_ip = to_ip; |
|---|
| 1300 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 1223 | 1301 | return 0; |
|---|
| 1224 | 1302 | } |
|---|
| 1225 | 1303 | intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", |
|---|
| .. | .. |
|---|
| 1317 | 1395 | decoder->ip += intel_pt_insn.length; |
|---|
| 1318 | 1396 | return 0; |
|---|
| 1319 | 1397 | } |
|---|
| 1398 | + decoder->sample_cyc = false; |
|---|
| 1320 | 1399 | decoder->ip += intel_pt_insn.length; |
|---|
| 1321 | 1400 | if (!decoder->tnt.count) { |
|---|
| 1322 | | - decoder->sample_timestamp = decoder->timestamp; |
|---|
| 1323 | | - decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; |
|---|
| 1401 | + intel_pt_update_sample_time(decoder); |
|---|
| 1324 | 1402 | return -EAGAIN; |
|---|
| 1325 | 1403 | } |
|---|
| 1326 | 1404 | decoder->tnt.payload <<= 1; |
|---|
| .. | .. |
|---|
| 1354 | 1432 | return 0; |
|---|
| 1355 | 1433 | } |
|---|
| 1356 | 1434 | |
|---|
| 1435 | +static uint64_t intel_pt_8b_tsc(uint64_t timestamp, uint64_t ref_timestamp) |
|---|
| 1436 | +{ |
|---|
| 1437 | + timestamp |= (ref_timestamp & (0xffULL << 56)); |
|---|
| 1438 | + |
|---|
| 1439 | + if (timestamp < ref_timestamp) { |
|---|
| 1440 | + if (ref_timestamp - timestamp > (1ULL << 55)) |
|---|
| 1441 | + timestamp += (1ULL << 56); |
|---|
| 1442 | + } else { |
|---|
| 1443 | + if (timestamp - ref_timestamp > (1ULL << 55)) |
|---|
| 1444 | + timestamp -= (1ULL << 56); |
|---|
| 1445 | + } |
|---|
| 1446 | + |
|---|
| 1447 | + return timestamp; |
|---|
| 1448 | +} |
|---|
| 1449 | + |
|---|
| 1357 | 1450 | static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) |
|---|
| 1358 | 1451 | { |
|---|
| 1359 | 1452 | uint64_t timestamp; |
|---|
| .. | .. |
|---|
| 1361 | 1454 | decoder->have_tma = false; |
|---|
| 1362 | 1455 | |
|---|
| 1363 | 1456 | if (decoder->ref_timestamp) { |
|---|
| 1364 | | - timestamp = decoder->packet.payload | |
|---|
| 1365 | | - (decoder->ref_timestamp & (0xffULL << 56)); |
|---|
| 1366 | | - if (timestamp < decoder->ref_timestamp) { |
|---|
| 1367 | | - if (decoder->ref_timestamp - timestamp > (1ULL << 55)) |
|---|
| 1368 | | - timestamp += (1ULL << 56); |
|---|
| 1369 | | - } else { |
|---|
| 1370 | | - if (timestamp - decoder->ref_timestamp > (1ULL << 55)) |
|---|
| 1371 | | - timestamp -= (1ULL << 56); |
|---|
| 1372 | | - } |
|---|
| 1457 | + timestamp = intel_pt_8b_tsc(decoder->packet.payload, |
|---|
| 1458 | + decoder->ref_timestamp); |
|---|
| 1373 | 1459 | decoder->tsc_timestamp = timestamp; |
|---|
| 1374 | 1460 | decoder->timestamp = timestamp; |
|---|
| 1375 | 1461 | decoder->ref_timestamp = 0; |
|---|
| .. | .. |
|---|
| 1408 | 1494 | intel_pt_log("ERROR: Buffer overflow\n"); |
|---|
| 1409 | 1495 | intel_pt_clear_tx_flags(decoder); |
|---|
| 1410 | 1496 | decoder->timestamp_insn_cnt = 0; |
|---|
| 1411 | | - decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; |
|---|
| 1497 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1498 | + decoder->state.from_ip = decoder->ip; |
|---|
| 1499 | + decoder->ip = 0; |
|---|
| 1500 | + decoder->pge = false; |
|---|
| 1501 | + decoder->set_fup_tx_flags = false; |
|---|
| 1502 | + decoder->set_fup_ptw = false; |
|---|
| 1503 | + decoder->set_fup_mwait = false; |
|---|
| 1504 | + decoder->set_fup_pwre = false; |
|---|
| 1505 | + decoder->set_fup_exstop = false; |
|---|
| 1506 | + decoder->set_fup_bep = false; |
|---|
| 1412 | 1507 | decoder->overflow = true; |
|---|
| 1413 | 1508 | return -EOVERFLOW; |
|---|
| 1509 | +} |
|---|
| 1510 | + |
|---|
| 1511 | +static inline void intel_pt_mtc_cyc_cnt_pge(struct intel_pt_decoder *decoder) |
|---|
| 1512 | +{ |
|---|
| 1513 | + if (decoder->have_cyc) |
|---|
| 1514 | + return; |
|---|
| 1515 | + |
|---|
| 1516 | + decoder->cyc_cnt_timestamp = decoder->timestamp; |
|---|
| 1517 | + decoder->base_cyc_cnt = decoder->tot_cyc_cnt; |
|---|
| 1518 | +} |
|---|
| 1519 | + |
|---|
| 1520 | +static inline void intel_pt_mtc_cyc_cnt_cbr(struct intel_pt_decoder *decoder) |
|---|
| 1521 | +{ |
|---|
| 1522 | + decoder->tsc_to_cyc = decoder->cbr / decoder->max_non_turbo_ratio_fp; |
|---|
| 1523 | + |
|---|
| 1524 | + if (decoder->pge) |
|---|
| 1525 | + intel_pt_mtc_cyc_cnt_pge(decoder); |
|---|
| 1526 | +} |
|---|
| 1527 | + |
|---|
| 1528 | +static inline void intel_pt_mtc_cyc_cnt_upd(struct intel_pt_decoder *decoder) |
|---|
| 1529 | +{ |
|---|
| 1530 | + uint64_t tot_cyc_cnt, tsc_delta; |
|---|
| 1531 | + |
|---|
| 1532 | + if (decoder->have_cyc) |
|---|
| 1533 | + return; |
|---|
| 1534 | + |
|---|
| 1535 | + decoder->sample_cyc = true; |
|---|
| 1536 | + |
|---|
| 1537 | + if (!decoder->pge || decoder->timestamp <= decoder->cyc_cnt_timestamp) |
|---|
| 1538 | + return; |
|---|
| 1539 | + |
|---|
| 1540 | + tsc_delta = decoder->timestamp - decoder->cyc_cnt_timestamp; |
|---|
| 1541 | + tot_cyc_cnt = tsc_delta * decoder->tsc_to_cyc + decoder->base_cyc_cnt; |
|---|
| 1542 | + |
|---|
| 1543 | + if (tot_cyc_cnt > decoder->tot_cyc_cnt) |
|---|
| 1544 | + decoder->tot_cyc_cnt = tot_cyc_cnt; |
|---|
| 1414 | 1545 | } |
|---|
| 1415 | 1546 | |
|---|
| 1416 | 1547 | static void intel_pt_calc_tma(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 1421 | 1552 | |
|---|
| 1422 | 1553 | if (!decoder->tsc_ctc_ratio_d) |
|---|
| 1423 | 1554 | return; |
|---|
| 1555 | + |
|---|
| 1556 | + if (decoder->pge && !decoder->in_psb) |
|---|
| 1557 | + intel_pt_mtc_cyc_cnt_pge(decoder); |
|---|
| 1558 | + else |
|---|
| 1559 | + intel_pt_mtc_cyc_cnt_upd(decoder); |
|---|
| 1424 | 1560 | |
|---|
| 1425 | 1561 | decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; |
|---|
| 1426 | 1562 | decoder->ctc_timestamp = decoder->tsc_timestamp - fc; |
|---|
| .. | .. |
|---|
| 1477 | 1613 | else |
|---|
| 1478 | 1614 | decoder->timestamp = timestamp; |
|---|
| 1479 | 1615 | |
|---|
| 1616 | + intel_pt_mtc_cyc_cnt_upd(decoder); |
|---|
| 1617 | + |
|---|
| 1480 | 1618 | decoder->timestamp_insn_cnt = 0; |
|---|
| 1481 | 1619 | decoder->last_mtc = mtc; |
|---|
| 1482 | 1620 | |
|---|
| .. | .. |
|---|
| 1486 | 1624 | decoder->have_calc_cyc_to_tsc = false; |
|---|
| 1487 | 1625 | intel_pt_calc_cyc_to_tsc(decoder, true); |
|---|
| 1488 | 1626 | } |
|---|
| 1627 | + |
|---|
| 1628 | + intel_pt_log_to("Setting timestamp", decoder->timestamp); |
|---|
| 1489 | 1629 | } |
|---|
| 1490 | 1630 | |
|---|
| 1491 | 1631 | static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 1499 | 1639 | |
|---|
| 1500 | 1640 | decoder->cbr = cbr; |
|---|
| 1501 | 1641 | decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr; |
|---|
| 1642 | + decoder->cyc_ref_timestamp = decoder->timestamp; |
|---|
| 1643 | + decoder->cycle_cnt = 0; |
|---|
| 1644 | + |
|---|
| 1645 | + intel_pt_mtc_cyc_cnt_cbr(decoder); |
|---|
| 1502 | 1646 | } |
|---|
| 1503 | 1647 | |
|---|
| 1504 | 1648 | static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 1508 | 1652 | decoder->have_cyc = true; |
|---|
| 1509 | 1653 | |
|---|
| 1510 | 1654 | decoder->cycle_cnt += decoder->packet.payload; |
|---|
| 1655 | + if (decoder->pge) |
|---|
| 1656 | + decoder->tot_cyc_cnt += decoder->packet.payload; |
|---|
| 1657 | + decoder->sample_cyc = true; |
|---|
| 1511 | 1658 | |
|---|
| 1512 | 1659 | if (!decoder->cyc_ref_timestamp) |
|---|
| 1513 | 1660 | return; |
|---|
| .. | .. |
|---|
| 1526 | 1673 | decoder->timestamp = timestamp; |
|---|
| 1527 | 1674 | |
|---|
| 1528 | 1675 | decoder->timestamp_insn_cnt = 0; |
|---|
| 1676 | + |
|---|
| 1677 | + intel_pt_log_to("Setting timestamp", decoder->timestamp); |
|---|
| 1678 | +} |
|---|
| 1679 | + |
|---|
| 1680 | +static void intel_pt_bbp(struct intel_pt_decoder *decoder) |
|---|
| 1681 | +{ |
|---|
| 1682 | + if (decoder->prev_pkt_ctx == INTEL_PT_NO_CTX) { |
|---|
| 1683 | + memset(decoder->state.items.mask, 0, sizeof(decoder->state.items.mask)); |
|---|
| 1684 | + decoder->state.items.is_32_bit = false; |
|---|
| 1685 | + } |
|---|
| 1686 | + decoder->blk_type = decoder->packet.payload; |
|---|
| 1687 | + decoder->blk_type_pos = intel_pt_blk_type_pos(decoder->blk_type); |
|---|
| 1688 | + if (decoder->blk_type == INTEL_PT_GP_REGS) |
|---|
| 1689 | + decoder->state.items.is_32_bit = decoder->packet.count; |
|---|
| 1690 | + if (decoder->blk_type_pos < 0) { |
|---|
| 1691 | + intel_pt_log("WARNING: Unknown block type %u\n", |
|---|
| 1692 | + decoder->blk_type); |
|---|
| 1693 | + } else if (decoder->state.items.mask[decoder->blk_type_pos]) { |
|---|
| 1694 | + intel_pt_log("WARNING: Duplicate block type %u\n", |
|---|
| 1695 | + decoder->blk_type); |
|---|
| 1696 | + } |
|---|
| 1697 | +} |
|---|
| 1698 | + |
|---|
| 1699 | +static void intel_pt_bip(struct intel_pt_decoder *decoder) |
|---|
| 1700 | +{ |
|---|
| 1701 | + uint32_t id = decoder->packet.count; |
|---|
| 1702 | + uint32_t bit = 1 << id; |
|---|
| 1703 | + int pos = decoder->blk_type_pos; |
|---|
| 1704 | + |
|---|
| 1705 | + if (pos < 0 || id >= INTEL_PT_BLK_ITEM_ID_CNT) { |
|---|
| 1706 | + intel_pt_log("WARNING: Unknown block item %u type %d\n", |
|---|
| 1707 | + id, decoder->blk_type); |
|---|
| 1708 | + return; |
|---|
| 1709 | + } |
|---|
| 1710 | + |
|---|
| 1711 | + if (decoder->state.items.mask[pos] & bit) { |
|---|
| 1712 | + intel_pt_log("WARNING: Duplicate block item %u type %d\n", |
|---|
| 1713 | + id, decoder->blk_type); |
|---|
| 1714 | + } |
|---|
| 1715 | + |
|---|
| 1716 | + decoder->state.items.mask[pos] |= bit; |
|---|
| 1717 | + decoder->state.items.val[pos][id] = decoder->packet.payload; |
|---|
| 1529 | 1718 | } |
|---|
| 1530 | 1719 | |
|---|
| 1531 | 1720 | /* Walk PSB+ packets when already in sync. */ |
|---|
| .. | .. |
|---|
| 1533 | 1722 | { |
|---|
| 1534 | 1723 | int err; |
|---|
| 1535 | 1724 | |
|---|
| 1725 | + decoder->in_psb = true; |
|---|
| 1726 | + |
|---|
| 1536 | 1727 | while (1) { |
|---|
| 1537 | 1728 | err = intel_pt_get_next_packet(decoder); |
|---|
| 1538 | 1729 | if (err) |
|---|
| 1539 | | - return err; |
|---|
| 1730 | + goto out; |
|---|
| 1540 | 1731 | |
|---|
| 1541 | 1732 | switch (decoder->packet.type) { |
|---|
| 1542 | 1733 | case INTEL_PT_PSBEND: |
|---|
| 1543 | | - return 0; |
|---|
| 1734 | + err = 0; |
|---|
| 1735 | + goto out; |
|---|
| 1544 | 1736 | |
|---|
| 1545 | 1737 | case INTEL_PT_TIP_PGD: |
|---|
| 1546 | 1738 | case INTEL_PT_TIP_PGE: |
|---|
| .. | .. |
|---|
| 1556 | 1748 | case INTEL_PT_MWAIT: |
|---|
| 1557 | 1749 | case INTEL_PT_PWRE: |
|---|
| 1558 | 1750 | case INTEL_PT_PWRX: |
|---|
| 1751 | + case INTEL_PT_BBP: |
|---|
| 1752 | + case INTEL_PT_BIP: |
|---|
| 1753 | + case INTEL_PT_BEP: |
|---|
| 1754 | + case INTEL_PT_BEP_IP: |
|---|
| 1559 | 1755 | decoder->have_tma = false; |
|---|
| 1560 | 1756 | intel_pt_log("ERROR: Unexpected packet\n"); |
|---|
| 1561 | | - return -EAGAIN; |
|---|
| 1757 | + err = -EAGAIN; |
|---|
| 1758 | + goto out; |
|---|
| 1562 | 1759 | |
|---|
| 1563 | 1760 | case INTEL_PT_OVF: |
|---|
| 1564 | | - return intel_pt_overflow(decoder); |
|---|
| 1761 | + err = intel_pt_overflow(decoder); |
|---|
| 1762 | + goto out; |
|---|
| 1565 | 1763 | |
|---|
| 1566 | 1764 | case INTEL_PT_TSC: |
|---|
| 1567 | 1765 | intel_pt_calc_tsc_timestamp(decoder); |
|---|
| .. | .. |
|---|
| 1585 | 1783 | |
|---|
| 1586 | 1784 | case INTEL_PT_FUP: |
|---|
| 1587 | 1785 | decoder->pge = true; |
|---|
| 1588 | | - if (decoder->packet.count) |
|---|
| 1786 | + if (decoder->packet.count) { |
|---|
| 1589 | 1787 | intel_pt_set_last_ip(decoder); |
|---|
| 1788 | + if (decoder->hop) { |
|---|
| 1789 | + /* Act on FUP at PSBEND */ |
|---|
| 1790 | + decoder->ip = decoder->last_ip; |
|---|
| 1791 | + decoder->hop_psb_fup = true; |
|---|
| 1792 | + } |
|---|
| 1793 | + } |
|---|
| 1590 | 1794 | break; |
|---|
| 1591 | 1795 | |
|---|
| 1592 | 1796 | case INTEL_PT_MODE_TSX: |
|---|
| .. | .. |
|---|
| 1610 | 1814 | break; |
|---|
| 1611 | 1815 | } |
|---|
| 1612 | 1816 | } |
|---|
| 1817 | +out: |
|---|
| 1818 | + decoder->in_psb = false; |
|---|
| 1819 | + |
|---|
| 1820 | + return err; |
|---|
| 1613 | 1821 | } |
|---|
| 1614 | 1822 | |
|---|
| 1615 | 1823 | static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 1646 | 1854 | case INTEL_PT_MWAIT: |
|---|
| 1647 | 1855 | case INTEL_PT_PWRE: |
|---|
| 1648 | 1856 | case INTEL_PT_PWRX: |
|---|
| 1857 | + case INTEL_PT_BBP: |
|---|
| 1858 | + case INTEL_PT_BIP: |
|---|
| 1859 | + case INTEL_PT_BEP: |
|---|
| 1860 | + case INTEL_PT_BEP_IP: |
|---|
| 1649 | 1861 | intel_pt_log("ERROR: Missing TIP after FUP\n"); |
|---|
| 1650 | 1862 | decoder->pkt_state = INTEL_PT_STATE_ERR3; |
|---|
| 1651 | 1863 | decoder->pkt_step = 0; |
|---|
| .. | .. |
|---|
| 1660 | 1872 | |
|---|
| 1661 | 1873 | case INTEL_PT_TIP_PGD: |
|---|
| 1662 | 1874 | decoder->state.from_ip = decoder->ip; |
|---|
| 1663 | | - decoder->state.to_ip = 0; |
|---|
| 1664 | | - if (decoder->packet.count != 0) { |
|---|
| 1875 | + if (decoder->packet.count == 0) { |
|---|
| 1876 | + decoder->state.to_ip = 0; |
|---|
| 1877 | + } else { |
|---|
| 1665 | 1878 | intel_pt_set_ip(decoder); |
|---|
| 1666 | | - intel_pt_log("Omitting PGD ip " x64_fmt "\n", |
|---|
| 1667 | | - decoder->ip); |
|---|
| 1879 | + decoder->state.to_ip = decoder->ip; |
|---|
| 1668 | 1880 | } |
|---|
| 1669 | 1881 | decoder->pge = false; |
|---|
| 1670 | 1882 | decoder->continuous_period = false; |
|---|
| 1883 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 1671 | 1884 | return 0; |
|---|
| 1672 | 1885 | |
|---|
| 1673 | 1886 | case INTEL_PT_TIP_PGE: |
|---|
| .. | .. |
|---|
| 1681 | 1894 | intel_pt_set_ip(decoder); |
|---|
| 1682 | 1895 | decoder->state.to_ip = decoder->ip; |
|---|
| 1683 | 1896 | } |
|---|
| 1897 | + decoder->state.type |= INTEL_PT_TRACE_BEGIN; |
|---|
| 1898 | + intel_pt_mtc_cyc_cnt_pge(decoder); |
|---|
| 1684 | 1899 | return 0; |
|---|
| 1685 | 1900 | |
|---|
| 1686 | 1901 | case INTEL_PT_TIP: |
|---|
| .. | .. |
|---|
| 1722 | 1937 | } |
|---|
| 1723 | 1938 | } |
|---|
| 1724 | 1939 | |
|---|
| 1940 | +static int intel_pt_resample(struct intel_pt_decoder *decoder) |
|---|
| 1941 | +{ |
|---|
| 1942 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 1943 | + decoder->state.type = INTEL_PT_INSTRUCTION; |
|---|
| 1944 | + decoder->state.from_ip = decoder->ip; |
|---|
| 1945 | + decoder->state.to_ip = 0; |
|---|
| 1946 | + return 0; |
|---|
| 1947 | +} |
|---|
| 1948 | + |
|---|
| 1949 | +#define HOP_PROCESS 0 |
|---|
| 1950 | +#define HOP_IGNORE 1 |
|---|
| 1951 | +#define HOP_RETURN 2 |
|---|
| 1952 | +#define HOP_AGAIN 3 |
|---|
| 1953 | + |
|---|
| 1954 | +static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder); |
|---|
| 1955 | + |
|---|
| 1956 | +/* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */ |
|---|
| 1957 | +static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err) |
|---|
| 1958 | +{ |
|---|
| 1959 | + *err = 0; |
|---|
| 1960 | + |
|---|
| 1961 | + /* Leap from PSB to PSB, getting ip from FUP within PSB+ */ |
|---|
| 1962 | + if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) { |
|---|
| 1963 | + *err = intel_pt_scan_for_psb(decoder); |
|---|
| 1964 | + if (*err) |
|---|
| 1965 | + return HOP_RETURN; |
|---|
| 1966 | + } |
|---|
| 1967 | + |
|---|
| 1968 | + switch (decoder->packet.type) { |
|---|
| 1969 | + case INTEL_PT_TNT: |
|---|
| 1970 | + return HOP_IGNORE; |
|---|
| 1971 | + |
|---|
| 1972 | + case INTEL_PT_TIP_PGD: |
|---|
| 1973 | + decoder->pge = false; |
|---|
| 1974 | + if (!decoder->packet.count) |
|---|
| 1975 | + return HOP_IGNORE; |
|---|
| 1976 | + intel_pt_set_ip(decoder); |
|---|
| 1977 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 1978 | + decoder->state.from_ip = 0; |
|---|
| 1979 | + decoder->state.to_ip = decoder->ip; |
|---|
| 1980 | + return HOP_RETURN; |
|---|
| 1981 | + |
|---|
| 1982 | + case INTEL_PT_TIP: |
|---|
| 1983 | + if (!decoder->packet.count) |
|---|
| 1984 | + return HOP_IGNORE; |
|---|
| 1985 | + intel_pt_set_ip(decoder); |
|---|
| 1986 | + decoder->state.type = INTEL_PT_INSTRUCTION; |
|---|
| 1987 | + decoder->state.from_ip = decoder->ip; |
|---|
| 1988 | + decoder->state.to_ip = 0; |
|---|
| 1989 | + return HOP_RETURN; |
|---|
| 1990 | + |
|---|
| 1991 | + case INTEL_PT_FUP: |
|---|
| 1992 | + if (!decoder->packet.count) |
|---|
| 1993 | + return HOP_IGNORE; |
|---|
| 1994 | + intel_pt_set_ip(decoder); |
|---|
| 1995 | + if (decoder->set_fup_mwait || decoder->set_fup_pwre) |
|---|
| 1996 | + *no_tip = true; |
|---|
| 1997 | + if (!decoder->branch_enable || !decoder->pge) |
|---|
| 1998 | + *no_tip = true; |
|---|
| 1999 | + if (*no_tip) { |
|---|
| 2000 | + decoder->state.type = INTEL_PT_INSTRUCTION; |
|---|
| 2001 | + decoder->state.from_ip = decoder->ip; |
|---|
| 2002 | + decoder->state.to_ip = 0; |
|---|
| 2003 | + intel_pt_fup_event(decoder); |
|---|
| 2004 | + return HOP_RETURN; |
|---|
| 2005 | + } |
|---|
| 2006 | + intel_pt_fup_event(decoder); |
|---|
| 2007 | + decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH; |
|---|
| 2008 | + *err = intel_pt_walk_fup_tip(decoder); |
|---|
| 2009 | + if (!*err && decoder->state.to_ip) |
|---|
| 2010 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
|---|
| 2011 | + return HOP_RETURN; |
|---|
| 2012 | + |
|---|
| 2013 | + case INTEL_PT_PSB: |
|---|
| 2014 | + decoder->last_ip = 0; |
|---|
| 2015 | + decoder->have_last_ip = true; |
|---|
| 2016 | + decoder->hop_psb_fup = false; |
|---|
| 2017 | + *err = intel_pt_walk_psbend(decoder); |
|---|
| 2018 | + if (*err == -EAGAIN) |
|---|
| 2019 | + return HOP_AGAIN; |
|---|
| 2020 | + if (*err) |
|---|
| 2021 | + return HOP_RETURN; |
|---|
| 2022 | + if (decoder->hop_psb_fup) { |
|---|
| 2023 | + decoder->hop_psb_fup = false; |
|---|
| 2024 | + decoder->state.type = INTEL_PT_INSTRUCTION; |
|---|
| 2025 | + decoder->state.from_ip = decoder->ip; |
|---|
| 2026 | + decoder->state.to_ip = 0; |
|---|
| 2027 | + return HOP_RETURN; |
|---|
| 2028 | + } |
|---|
| 2029 | + if (decoder->cbr != decoder->cbr_seen) { |
|---|
| 2030 | + decoder->state.type = 0; |
|---|
| 2031 | + return HOP_RETURN; |
|---|
| 2032 | + } |
|---|
| 2033 | + return HOP_IGNORE; |
|---|
| 2034 | + |
|---|
| 2035 | + case INTEL_PT_BAD: |
|---|
| 2036 | + case INTEL_PT_PAD: |
|---|
| 2037 | + case INTEL_PT_TIP_PGE: |
|---|
| 2038 | + case INTEL_PT_TSC: |
|---|
| 2039 | + case INTEL_PT_TMA: |
|---|
| 2040 | + case INTEL_PT_MODE_EXEC: |
|---|
| 2041 | + case INTEL_PT_MODE_TSX: |
|---|
| 2042 | + case INTEL_PT_MTC: |
|---|
| 2043 | + case INTEL_PT_CYC: |
|---|
| 2044 | + case INTEL_PT_VMCS: |
|---|
| 2045 | + case INTEL_PT_PSBEND: |
|---|
| 2046 | + case INTEL_PT_CBR: |
|---|
| 2047 | + case INTEL_PT_TRACESTOP: |
|---|
| 2048 | + case INTEL_PT_PIP: |
|---|
| 2049 | + case INTEL_PT_OVF: |
|---|
| 2050 | + case INTEL_PT_MNT: |
|---|
| 2051 | + case INTEL_PT_PTWRITE: |
|---|
| 2052 | + case INTEL_PT_PTWRITE_IP: |
|---|
| 2053 | + case INTEL_PT_EXSTOP: |
|---|
| 2054 | + case INTEL_PT_EXSTOP_IP: |
|---|
| 2055 | + case INTEL_PT_MWAIT: |
|---|
| 2056 | + case INTEL_PT_PWRE: |
|---|
| 2057 | + case INTEL_PT_PWRX: |
|---|
| 2058 | + case INTEL_PT_BBP: |
|---|
| 2059 | + case INTEL_PT_BIP: |
|---|
| 2060 | + case INTEL_PT_BEP: |
|---|
| 2061 | + case INTEL_PT_BEP_IP: |
|---|
| 2062 | + default: |
|---|
| 2063 | + return HOP_PROCESS; |
|---|
| 2064 | + } |
|---|
| 2065 | +} |
|---|
| 2066 | + |
|---|
| 1725 | 2067 | static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) |
|---|
| 1726 | 2068 | { |
|---|
| 2069 | + int last_packet_type = INTEL_PT_PAD; |
|---|
| 1727 | 2070 | bool no_tip = false; |
|---|
| 1728 | 2071 | int err; |
|---|
| 1729 | 2072 | |
|---|
| .. | .. |
|---|
| 1732 | 2075 | if (err) |
|---|
| 1733 | 2076 | return err; |
|---|
| 1734 | 2077 | next: |
|---|
| 2078 | + err = 0; |
|---|
| 2079 | + if (decoder->cyc_threshold) { |
|---|
| 2080 | + if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) |
|---|
| 2081 | + decoder->sample_cyc = false; |
|---|
| 2082 | + last_packet_type = decoder->packet.type; |
|---|
| 2083 | + } |
|---|
| 2084 | + |
|---|
| 2085 | + if (decoder->hop) { |
|---|
| 2086 | + switch (intel_pt_hop_trace(decoder, &no_tip, &err)) { |
|---|
| 2087 | + case HOP_IGNORE: |
|---|
| 2088 | + continue; |
|---|
| 2089 | + case HOP_RETURN: |
|---|
| 2090 | + return err; |
|---|
| 2091 | + case HOP_AGAIN: |
|---|
| 2092 | + goto next; |
|---|
| 2093 | + default: |
|---|
| 2094 | + break; |
|---|
| 2095 | + } |
|---|
| 2096 | + } |
|---|
| 2097 | + |
|---|
| 1735 | 2098 | switch (decoder->packet.type) { |
|---|
| 1736 | 2099 | case INTEL_PT_TNT: |
|---|
| 1737 | 2100 | if (!decoder->packet.count) |
|---|
| .. | .. |
|---|
| 1751 | 2114 | |
|---|
| 1752 | 2115 | case INTEL_PT_TIP_PGE: { |
|---|
| 1753 | 2116 | decoder->pge = true; |
|---|
| 2117 | + decoder->overflow = false; |
|---|
| 2118 | + intel_pt_mtc_cyc_cnt_pge(decoder); |
|---|
| 1754 | 2119 | if (decoder->packet.count == 0) { |
|---|
| 1755 | 2120 | intel_pt_log_at("Skipping zero TIP.PGE", |
|---|
| 1756 | 2121 | decoder->pos); |
|---|
| .. | .. |
|---|
| 1759 | 2124 | intel_pt_set_ip(decoder); |
|---|
| 1760 | 2125 | decoder->state.from_ip = 0; |
|---|
| 1761 | 2126 | decoder->state.to_ip = decoder->ip; |
|---|
| 2127 | + decoder->state.type |= INTEL_PT_TRACE_BEGIN; |
|---|
| 2128 | + /* |
|---|
| 2129 | + * In hop mode, resample to get the to_ip as an |
|---|
| 2130 | + * "instruction" sample. |
|---|
| 2131 | + */ |
|---|
| 2132 | + if (decoder->hop) |
|---|
| 2133 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
|---|
| 1762 | 2134 | return 0; |
|---|
| 1763 | 2135 | } |
|---|
| 1764 | 2136 | |
|---|
| .. | .. |
|---|
| 1779 | 2151 | break; |
|---|
| 1780 | 2152 | } |
|---|
| 1781 | 2153 | intel_pt_set_last_ip(decoder); |
|---|
| 1782 | | - if (!decoder->branch_enable) { |
|---|
| 2154 | + if (!decoder->branch_enable || !decoder->pge) { |
|---|
| 1783 | 2155 | decoder->ip = decoder->last_ip; |
|---|
| 1784 | 2156 | if (intel_pt_fup_event(decoder)) |
|---|
| 1785 | 2157 | return 0; |
|---|
| .. | .. |
|---|
| 1817 | 2189 | goto next; |
|---|
| 1818 | 2190 | if (err) |
|---|
| 1819 | 2191 | return err; |
|---|
| 2192 | + /* |
|---|
| 2193 | + * PSB+ CBR will not have changed but cater for the |
|---|
| 2194 | + * possibility of another CBR change that gets caught up |
|---|
| 2195 | + * in the PSB+. |
|---|
| 2196 | + */ |
|---|
| 2197 | + if (decoder->cbr != decoder->cbr_seen) { |
|---|
| 2198 | + decoder->state.type = 0; |
|---|
| 2199 | + return 0; |
|---|
| 2200 | + } |
|---|
| 1820 | 2201 | break; |
|---|
| 1821 | 2202 | |
|---|
| 1822 | 2203 | case INTEL_PT_PIP: |
|---|
| .. | .. |
|---|
| 1857 | 2238 | |
|---|
| 1858 | 2239 | case INTEL_PT_CBR: |
|---|
| 1859 | 2240 | intel_pt_calc_cbr(decoder); |
|---|
| 1860 | | - if (!decoder->branch_enable && |
|---|
| 1861 | | - decoder->cbr != decoder->cbr_seen) { |
|---|
| 1862 | | - decoder->cbr_seen = decoder->cbr; |
|---|
| 1863 | | - decoder->state.type = INTEL_PT_CBR_CHG; |
|---|
| 1864 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 1865 | | - decoder->state.to_ip = 0; |
|---|
| 1866 | | - decoder->state.cbr_payload = |
|---|
| 1867 | | - decoder->packet.payload; |
|---|
| 2241 | + if (decoder->cbr != decoder->cbr_seen) { |
|---|
| 2242 | + decoder->state.type = 0; |
|---|
| 1868 | 2243 | return 0; |
|---|
| 1869 | 2244 | } |
|---|
| 1870 | 2245 | break; |
|---|
| .. | .. |
|---|
| 1875 | 2250 | |
|---|
| 1876 | 2251 | case INTEL_PT_MODE_TSX: |
|---|
| 1877 | 2252 | /* MODE_TSX need not be followed by FUP */ |
|---|
| 1878 | | - if (!decoder->pge) { |
|---|
| 2253 | + if (!decoder->pge || decoder->in_psb) { |
|---|
| 1879 | 2254 | intel_pt_update_in_tx(decoder); |
|---|
| 1880 | 2255 | break; |
|---|
| 1881 | 2256 | } |
|---|
| .. | .. |
|---|
| 1958 | 2333 | decoder->state.pwrx_payload = decoder->packet.payload; |
|---|
| 1959 | 2334 | return 0; |
|---|
| 1960 | 2335 | |
|---|
| 2336 | + case INTEL_PT_BBP: |
|---|
| 2337 | + intel_pt_bbp(decoder); |
|---|
| 2338 | + break; |
|---|
| 2339 | + |
|---|
| 2340 | + case INTEL_PT_BIP: |
|---|
| 2341 | + intel_pt_bip(decoder); |
|---|
| 2342 | + break; |
|---|
| 2343 | + |
|---|
| 2344 | + case INTEL_PT_BEP: |
|---|
| 2345 | + decoder->state.type = INTEL_PT_BLK_ITEMS; |
|---|
| 2346 | + decoder->state.from_ip = decoder->ip; |
|---|
| 2347 | + decoder->state.to_ip = 0; |
|---|
| 2348 | + return 0; |
|---|
| 2349 | + |
|---|
| 2350 | + case INTEL_PT_BEP_IP: |
|---|
| 2351 | + err = intel_pt_get_next_packet(decoder); |
|---|
| 2352 | + if (err) |
|---|
| 2353 | + return err; |
|---|
| 2354 | + if (decoder->packet.type == INTEL_PT_FUP) { |
|---|
| 2355 | + decoder->set_fup_bep = true; |
|---|
| 2356 | + no_tip = true; |
|---|
| 2357 | + } else { |
|---|
| 2358 | + intel_pt_log_at("ERROR: Missing FUP after BEP", |
|---|
| 2359 | + decoder->pos); |
|---|
| 2360 | + } |
|---|
| 2361 | + goto next; |
|---|
| 2362 | + |
|---|
| 1961 | 2363 | default: |
|---|
| 1962 | 2364 | return intel_pt_bug(decoder); |
|---|
| 1963 | 2365 | } |
|---|
| .. | .. |
|---|
| 1976 | 2378 | { |
|---|
| 1977 | 2379 | int err; |
|---|
| 1978 | 2380 | |
|---|
| 2381 | + decoder->in_psb = true; |
|---|
| 2382 | + |
|---|
| 1979 | 2383 | while (1) { |
|---|
| 1980 | 2384 | err = intel_pt_get_next_packet(decoder); |
|---|
| 1981 | 2385 | if (err) |
|---|
| 1982 | | - return err; |
|---|
| 2386 | + goto out; |
|---|
| 1983 | 2387 | |
|---|
| 1984 | 2388 | switch (decoder->packet.type) { |
|---|
| 1985 | 2389 | case INTEL_PT_TIP_PGD: |
|---|
| .. | .. |
|---|
| 1994 | 2398 | case INTEL_PT_MWAIT: |
|---|
| 1995 | 2399 | case INTEL_PT_PWRE: |
|---|
| 1996 | 2400 | case INTEL_PT_PWRX: |
|---|
| 2401 | + case INTEL_PT_BBP: |
|---|
| 2402 | + case INTEL_PT_BIP: |
|---|
| 2403 | + case INTEL_PT_BEP: |
|---|
| 2404 | + case INTEL_PT_BEP_IP: |
|---|
| 1997 | 2405 | intel_pt_log("ERROR: Unexpected packet\n"); |
|---|
| 1998 | | - return -ENOENT; |
|---|
| 2406 | + err = -ENOENT; |
|---|
| 2407 | + goto out; |
|---|
| 1999 | 2408 | |
|---|
| 2000 | 2409 | case INTEL_PT_FUP: |
|---|
| 2001 | 2410 | decoder->pge = true; |
|---|
| .. | .. |
|---|
| 2054 | 2463 | decoder->pkt_state = INTEL_PT_STATE_ERR4; |
|---|
| 2055 | 2464 | else |
|---|
| 2056 | 2465 | decoder->pkt_state = INTEL_PT_STATE_ERR3; |
|---|
| 2057 | | - return -ENOENT; |
|---|
| 2466 | + err = -ENOENT; |
|---|
| 2467 | + goto out; |
|---|
| 2058 | 2468 | |
|---|
| 2059 | 2469 | case INTEL_PT_BAD: /* Does not happen */ |
|---|
| 2060 | | - return intel_pt_bug(decoder); |
|---|
| 2470 | + err = intel_pt_bug(decoder); |
|---|
| 2471 | + goto out; |
|---|
| 2061 | 2472 | |
|---|
| 2062 | 2473 | case INTEL_PT_OVF: |
|---|
| 2063 | | - return intel_pt_overflow(decoder); |
|---|
| 2474 | + err = intel_pt_overflow(decoder); |
|---|
| 2475 | + goto out; |
|---|
| 2064 | 2476 | |
|---|
| 2065 | 2477 | case INTEL_PT_PSBEND: |
|---|
| 2066 | | - return 0; |
|---|
| 2478 | + err = 0; |
|---|
| 2479 | + goto out; |
|---|
| 2067 | 2480 | |
|---|
| 2068 | 2481 | case INTEL_PT_PSB: |
|---|
| 2069 | 2482 | case INTEL_PT_VMCS: |
|---|
| .. | .. |
|---|
| 2073 | 2486 | break; |
|---|
| 2074 | 2487 | } |
|---|
| 2075 | 2488 | } |
|---|
| 2489 | +out: |
|---|
| 2490 | + decoder->in_psb = false; |
|---|
| 2491 | + |
|---|
| 2492 | + return err; |
|---|
| 2076 | 2493 | } |
|---|
| 2077 | 2494 | |
|---|
| 2078 | 2495 | static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) |
|---|
| .. | .. |
|---|
| 2087 | 2504 | switch (decoder->packet.type) { |
|---|
| 2088 | 2505 | case INTEL_PT_TIP_PGD: |
|---|
| 2089 | 2506 | decoder->continuous_period = false; |
|---|
| 2090 | | - __fallthrough; |
|---|
| 2091 | | - case INTEL_PT_TIP_PGE: |
|---|
| 2092 | | - case INTEL_PT_TIP: |
|---|
| 2093 | | - decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; |
|---|
| 2507 | + decoder->pge = false; |
|---|
| 2094 | 2508 | if (intel_pt_have_ip(decoder)) |
|---|
| 2095 | 2509 | intel_pt_set_ip(decoder); |
|---|
| 2096 | | - if (decoder->ip) |
|---|
| 2097 | | - return 0; |
|---|
| 2098 | | - break; |
|---|
| 2510 | + if (!decoder->ip) |
|---|
| 2511 | + break; |
|---|
| 2512 | + decoder->state.type |= INTEL_PT_TRACE_END; |
|---|
| 2513 | + return 0; |
|---|
| 2514 | + |
|---|
| 2515 | + case INTEL_PT_TIP_PGE: |
|---|
| 2516 | + decoder->pge = true; |
|---|
| 2517 | + intel_pt_mtc_cyc_cnt_pge(decoder); |
|---|
| 2518 | + if (intel_pt_have_ip(decoder)) |
|---|
| 2519 | + intel_pt_set_ip(decoder); |
|---|
| 2520 | + if (!decoder->ip) |
|---|
| 2521 | + break; |
|---|
| 2522 | + decoder->state.type |= INTEL_PT_TRACE_BEGIN; |
|---|
| 2523 | + return 0; |
|---|
| 2524 | + |
|---|
| 2525 | + case INTEL_PT_TIP: |
|---|
| 2526 | + decoder->pge = true; |
|---|
| 2527 | + if (intel_pt_have_ip(decoder)) |
|---|
| 2528 | + intel_pt_set_ip(decoder); |
|---|
| 2529 | + if (!decoder->ip) |
|---|
| 2530 | + break; |
|---|
| 2531 | + return 0; |
|---|
| 2099 | 2532 | |
|---|
| 2100 | 2533 | case INTEL_PT_FUP: |
|---|
| 2101 | 2534 | if (intel_pt_have_ip(decoder)) |
|---|
| .. | .. |
|---|
| 2175 | 2608 | case INTEL_PT_MWAIT: |
|---|
| 2176 | 2609 | case INTEL_PT_PWRE: |
|---|
| 2177 | 2610 | case INTEL_PT_PWRX: |
|---|
| 2611 | + case INTEL_PT_BBP: |
|---|
| 2612 | + case INTEL_PT_BIP: |
|---|
| 2613 | + case INTEL_PT_BEP: |
|---|
| 2614 | + case INTEL_PT_BEP_IP: |
|---|
| 2178 | 2615 | default: |
|---|
| 2179 | 2616 | break; |
|---|
| 2180 | 2617 | } |
|---|
| .. | .. |
|---|
| 2190 | 2627 | decoder->set_fup_mwait = false; |
|---|
| 2191 | 2628 | decoder->set_fup_pwre = false; |
|---|
| 2192 | 2629 | decoder->set_fup_exstop = false; |
|---|
| 2630 | + decoder->set_fup_bep = false; |
|---|
| 2631 | + decoder->overflow = false; |
|---|
| 2193 | 2632 | |
|---|
| 2194 | 2633 | if (!decoder->branch_enable) { |
|---|
| 2195 | 2634 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2196 | | - decoder->overflow = false; |
|---|
| 2197 | 2635 | decoder->state.type = 0; /* Do not have a sample */ |
|---|
| 2198 | 2636 | return 0; |
|---|
| 2199 | 2637 | } |
|---|
| .. | .. |
|---|
| 2203 | 2641 | if (err) |
|---|
| 2204 | 2642 | return err; |
|---|
| 2205 | 2643 | |
|---|
| 2206 | | - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2207 | | - decoder->overflow = false; |
|---|
| 2644 | + /* In hop mode, resample to get the to_ip as an "instruction" sample */ |
|---|
| 2645 | + if (decoder->hop) |
|---|
| 2646 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
|---|
| 2647 | + else |
|---|
| 2648 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2208 | 2649 | |
|---|
| 2209 | 2650 | decoder->state.from_ip = 0; |
|---|
| 2210 | 2651 | decoder->state.to_ip = decoder->ip; |
|---|
| .. | .. |
|---|
| 2247 | 2688 | decoder->pos += decoder->len; |
|---|
| 2248 | 2689 | decoder->len = 0; |
|---|
| 2249 | 2690 | |
|---|
| 2250 | | - ret = intel_pt_get_next_data(decoder); |
|---|
| 2691 | + ret = intel_pt_get_next_data(decoder, false); |
|---|
| 2251 | 2692 | if (ret) |
|---|
| 2252 | 2693 | return ret; |
|---|
| 2253 | 2694 | |
|---|
| .. | .. |
|---|
| 2273 | 2714 | intel_pt_log("Scanning for PSB\n"); |
|---|
| 2274 | 2715 | while (1) { |
|---|
| 2275 | 2716 | if (!decoder->len) { |
|---|
| 2276 | | - ret = intel_pt_get_next_data(decoder); |
|---|
| 2717 | + ret = intel_pt_get_next_data(decoder, false); |
|---|
| 2277 | 2718 | if (ret) |
|---|
| 2278 | 2719 | return ret; |
|---|
| 2279 | 2720 | } |
|---|
| .. | .. |
|---|
| 2311 | 2752 | decoder->ip = 0; |
|---|
| 2312 | 2753 | intel_pt_clear_stack(&decoder->stack); |
|---|
| 2313 | 2754 | |
|---|
| 2755 | +leap: |
|---|
| 2314 | 2756 | err = intel_pt_scan_for_psb(decoder); |
|---|
| 2315 | 2757 | if (err) |
|---|
| 2316 | 2758 | return err; |
|---|
| 2317 | 2759 | |
|---|
| 2318 | 2760 | decoder->have_last_ip = true; |
|---|
| 2319 | | - decoder->pkt_state = INTEL_PT_STATE_NO_IP; |
|---|
| 2761 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2320 | 2762 | |
|---|
| 2321 | 2763 | err = intel_pt_walk_psb(decoder); |
|---|
| 2322 | 2764 | if (err) |
|---|
| .. | .. |
|---|
| 2324 | 2766 | |
|---|
| 2325 | 2767 | if (decoder->ip) { |
|---|
| 2326 | 2768 | decoder->state.type = 0; /* Do not have a sample */ |
|---|
| 2327 | | - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2769 | + /* |
|---|
| 2770 | + * In hop mode, resample to get the PSB FUP ip as an |
|---|
| 2771 | + * "instruction" sample. |
|---|
| 2772 | + */ |
|---|
| 2773 | + if (decoder->hop) |
|---|
| 2774 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
|---|
| 2775 | + else |
|---|
| 2776 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
|---|
| 2777 | + } else if (decoder->leap) { |
|---|
| 2778 | + /* |
|---|
| 2779 | + * In leap mode, only PSB+ is decoded, so keeping leaping to the |
|---|
| 2780 | + * next PSB until there is an ip. |
|---|
| 2781 | + */ |
|---|
| 2782 | + goto leap; |
|---|
| 2328 | 2783 | } else { |
|---|
| 2329 | 2784 | return intel_pt_sync_ip(decoder); |
|---|
| 2330 | 2785 | } |
|---|
| .. | .. |
|---|
| 2388 | 2843 | if (err == -EAGAIN) |
|---|
| 2389 | 2844 | err = intel_pt_walk_trace(decoder); |
|---|
| 2390 | 2845 | break; |
|---|
| 2846 | + case INTEL_PT_STATE_RESAMPLE: |
|---|
| 2847 | + err = intel_pt_resample(decoder); |
|---|
| 2848 | + break; |
|---|
| 2391 | 2849 | default: |
|---|
| 2392 | 2850 | err = intel_pt_bug(decoder); |
|---|
| 2393 | 2851 | break; |
|---|
| .. | .. |
|---|
| 2396 | 2854 | |
|---|
| 2397 | 2855 | if (err) { |
|---|
| 2398 | 2856 | decoder->state.err = intel_pt_ext_err(err); |
|---|
| 2399 | | - decoder->state.from_ip = decoder->ip; |
|---|
| 2400 | | - decoder->sample_timestamp = decoder->timestamp; |
|---|
| 2401 | | - decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; |
|---|
| 2857 | + if (err != -EOVERFLOW) |
|---|
| 2858 | + decoder->state.from_ip = decoder->ip; |
|---|
| 2859 | + intel_pt_update_sample_time(decoder); |
|---|
| 2860 | + decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; |
|---|
| 2402 | 2861 | } else { |
|---|
| 2403 | 2862 | decoder->state.err = 0; |
|---|
| 2404 | | - if (decoder->cbr != decoder->cbr_seen && decoder->state.type) { |
|---|
| 2863 | + if (decoder->cbr != decoder->cbr_seen) { |
|---|
| 2405 | 2864 | decoder->cbr_seen = decoder->cbr; |
|---|
| 2865 | + if (!decoder->state.type) { |
|---|
| 2866 | + decoder->state.from_ip = decoder->ip; |
|---|
| 2867 | + decoder->state.to_ip = 0; |
|---|
| 2868 | + } |
|---|
| 2406 | 2869 | decoder->state.type |= INTEL_PT_CBR_CHG; |
|---|
| 2407 | 2870 | decoder->state.cbr_payload = decoder->cbr_payload; |
|---|
| 2871 | + decoder->state.cbr = decoder->cbr; |
|---|
| 2408 | 2872 | } |
|---|
| 2409 | 2873 | if (intel_pt_sample_time(decoder->pkt_state)) { |
|---|
| 2410 | | - decoder->sample_timestamp = decoder->timestamp; |
|---|
| 2411 | | - decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; |
|---|
| 2874 | + intel_pt_update_sample_time(decoder); |
|---|
| 2875 | + if (decoder->sample_cyc) { |
|---|
| 2876 | + decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; |
|---|
| 2877 | + decoder->state.flags |= INTEL_PT_SAMPLE_IPC; |
|---|
| 2878 | + decoder->sample_cyc = false; |
|---|
| 2879 | + } |
|---|
| 2412 | 2880 | } |
|---|
| 2881 | + /* |
|---|
| 2882 | + * When using only TSC/MTC to compute cycles, IPC can be |
|---|
| 2883 | + * sampled as soon as the cycle count changes. |
|---|
| 2884 | + */ |
|---|
| 2885 | + if (!decoder->have_cyc) |
|---|
| 2886 | + decoder->state.flags |= INTEL_PT_SAMPLE_IPC; |
|---|
| 2413 | 2887 | } |
|---|
| 2414 | 2888 | |
|---|
| 2415 | 2889 | decoder->state.timestamp = decoder->sample_timestamp; |
|---|
| 2416 | 2890 | decoder->state.est_timestamp = intel_pt_est_timestamp(decoder); |
|---|
| 2417 | 2891 | decoder->state.cr3 = decoder->cr3; |
|---|
| 2418 | 2892 | decoder->state.tot_insn_cnt = decoder->tot_insn_cnt; |
|---|
| 2893 | + decoder->state.tot_cyc_cnt = decoder->sample_tot_cyc_cnt; |
|---|
| 2419 | 2894 | |
|---|
| 2420 | 2895 | return &decoder->state; |
|---|
| 2421 | 2896 | } |
|---|
| .. | .. |
|---|
| 2519 | 2994 | static bool intel_pt_next_tsc(unsigned char *buf, size_t len, uint64_t *tsc, |
|---|
| 2520 | 2995 | size_t *rem) |
|---|
| 2521 | 2996 | { |
|---|
| 2997 | + enum intel_pt_pkt_ctx ctx = INTEL_PT_NO_CTX; |
|---|
| 2522 | 2998 | struct intel_pt_pkt packet; |
|---|
| 2523 | 2999 | int ret; |
|---|
| 2524 | 3000 | |
|---|
| 2525 | 3001 | while (len) { |
|---|
| 2526 | | - ret = intel_pt_get_packet(buf, len, &packet); |
|---|
| 3002 | + ret = intel_pt_get_packet(buf, len, &packet, &ctx); |
|---|
| 2527 | 3003 | if (ret <= 0) |
|---|
| 2528 | 3004 | return false; |
|---|
| 2529 | 3005 | if (packet.type == INTEL_PT_TSC) { |
|---|
| .. | .. |
|---|
| 2725 | 3201 | return buf_b; /* No overlap */ |
|---|
| 2726 | 3202 | } |
|---|
| 2727 | 3203 | } |
|---|
| 3204 | + |
|---|
| 3205 | +/** |
|---|
| 3206 | + * struct fast_forward_data - data used by intel_pt_ff_cb(). |
|---|
| 3207 | + * @timestamp: timestamp to fast forward towards |
|---|
| 3208 | + * @buf_timestamp: buffer timestamp of last buffer with trace data earlier than |
|---|
| 3209 | + * the fast forward timestamp. |
|---|
| 3210 | + */ |
|---|
| 3211 | +struct fast_forward_data { |
|---|
| 3212 | + uint64_t timestamp; |
|---|
| 3213 | + uint64_t buf_timestamp; |
|---|
| 3214 | +}; |
|---|
| 3215 | + |
|---|
| 3216 | +/** |
|---|
| 3217 | + * intel_pt_ff_cb - fast forward lookahead callback. |
|---|
| 3218 | + * @buffer: Intel PT trace buffer |
|---|
| 3219 | + * @data: opaque pointer to fast forward data (struct fast_forward_data) |
|---|
| 3220 | + * |
|---|
| 3221 | + * Determine if @buffer trace is past the fast forward timestamp. |
|---|
| 3222 | + * |
|---|
| 3223 | + * Return: 1 (stop lookahead) if @buffer trace is past the fast forward |
|---|
| 3224 | + * timestamp, and 0 otherwise. |
|---|
| 3225 | + */ |
|---|
| 3226 | +static int intel_pt_ff_cb(struct intel_pt_buffer *buffer, void *data) |
|---|
| 3227 | +{ |
|---|
| 3228 | + struct fast_forward_data *d = data; |
|---|
| 3229 | + unsigned char *buf; |
|---|
| 3230 | + uint64_t tsc; |
|---|
| 3231 | + size_t rem; |
|---|
| 3232 | + size_t len; |
|---|
| 3233 | + |
|---|
| 3234 | + buf = (unsigned char *)buffer->buf; |
|---|
| 3235 | + len = buffer->len; |
|---|
| 3236 | + |
|---|
| 3237 | + if (!intel_pt_next_psb(&buf, &len) || |
|---|
| 3238 | + !intel_pt_next_tsc(buf, len, &tsc, &rem)) |
|---|
| 3239 | + return 0; |
|---|
| 3240 | + |
|---|
| 3241 | + tsc = intel_pt_8b_tsc(tsc, buffer->ref_timestamp); |
|---|
| 3242 | + |
|---|
| 3243 | + intel_pt_log("Buffer 1st timestamp " x64_fmt " ref timestamp " x64_fmt "\n", |
|---|
| 3244 | + tsc, buffer->ref_timestamp); |
|---|
| 3245 | + |
|---|
| 3246 | + /* |
|---|
| 3247 | + * If the buffer contains a timestamp earlier that the fast forward |
|---|
| 3248 | + * timestamp, then record it, else stop. |
|---|
| 3249 | + */ |
|---|
| 3250 | + if (tsc < d->timestamp) |
|---|
| 3251 | + d->buf_timestamp = buffer->ref_timestamp; |
|---|
| 3252 | + else |
|---|
| 3253 | + return 1; |
|---|
| 3254 | + |
|---|
| 3255 | + return 0; |
|---|
| 3256 | +} |
|---|
| 3257 | + |
|---|
| 3258 | +/** |
|---|
| 3259 | + * intel_pt_fast_forward - reposition decoder forwards. |
|---|
| 3260 | + * @decoder: Intel PT decoder |
|---|
| 3261 | + * @timestamp: timestamp to fast forward towards |
|---|
| 3262 | + * |
|---|
| 3263 | + * Reposition decoder at the last PSB with a timestamp earlier than @timestamp. |
|---|
| 3264 | + * |
|---|
| 3265 | + * Return: 0 on success or negative error code on failure. |
|---|
| 3266 | + */ |
|---|
| 3267 | +int intel_pt_fast_forward(struct intel_pt_decoder *decoder, uint64_t timestamp) |
|---|
| 3268 | +{ |
|---|
| 3269 | + struct fast_forward_data d = { .timestamp = timestamp }; |
|---|
| 3270 | + unsigned char *buf; |
|---|
| 3271 | + size_t len; |
|---|
| 3272 | + int err; |
|---|
| 3273 | + |
|---|
| 3274 | + intel_pt_log("Fast forward towards timestamp " x64_fmt "\n", timestamp); |
|---|
| 3275 | + |
|---|
| 3276 | + /* Find buffer timestamp of buffer to fast forward to */ |
|---|
| 3277 | + err = decoder->lookahead(decoder->data, intel_pt_ff_cb, &d); |
|---|
| 3278 | + if (err < 0) |
|---|
| 3279 | + return err; |
|---|
| 3280 | + |
|---|
| 3281 | + /* Walk to buffer with same buffer timestamp */ |
|---|
| 3282 | + if (d.buf_timestamp) { |
|---|
| 3283 | + do { |
|---|
| 3284 | + decoder->pos += decoder->len; |
|---|
| 3285 | + decoder->len = 0; |
|---|
| 3286 | + err = intel_pt_get_next_data(decoder, true); |
|---|
| 3287 | + /* -ENOLINK means non-consecutive trace */ |
|---|
| 3288 | + if (err && err != -ENOLINK) |
|---|
| 3289 | + return err; |
|---|
| 3290 | + } while (decoder->buf_timestamp != d.buf_timestamp); |
|---|
| 3291 | + } |
|---|
| 3292 | + |
|---|
| 3293 | + if (!decoder->buf) |
|---|
| 3294 | + return 0; |
|---|
| 3295 | + |
|---|
| 3296 | + buf = (unsigned char *)decoder->buf; |
|---|
| 3297 | + len = decoder->len; |
|---|
| 3298 | + |
|---|
| 3299 | + if (!intel_pt_next_psb(&buf, &len)) |
|---|
| 3300 | + return 0; |
|---|
| 3301 | + |
|---|
| 3302 | + /* |
|---|
| 3303 | + * Walk PSBs while the PSB timestamp is less than the fast forward |
|---|
| 3304 | + * timestamp. |
|---|
| 3305 | + */ |
|---|
| 3306 | + do { |
|---|
| 3307 | + uint64_t tsc; |
|---|
| 3308 | + size_t rem; |
|---|
| 3309 | + |
|---|
| 3310 | + if (!intel_pt_next_tsc(buf, len, &tsc, &rem)) |
|---|
| 3311 | + break; |
|---|
| 3312 | + tsc = intel_pt_8b_tsc(tsc, decoder->buf_timestamp); |
|---|
| 3313 | + /* |
|---|
| 3314 | + * A TSC packet can slip past MTC packets but, after fast |
|---|
| 3315 | + * forward, decoding starts at the TSC timestamp. That means |
|---|
| 3316 | + * the timestamps may not be exactly the same as the timestamps |
|---|
| 3317 | + * that would have been decoded without fast forward. |
|---|
| 3318 | + */ |
|---|
| 3319 | + if (tsc < timestamp) { |
|---|
| 3320 | + intel_pt_log("Fast forward to next PSB timestamp " x64_fmt "\n", tsc); |
|---|
| 3321 | + decoder->pos += decoder->len - len; |
|---|
| 3322 | + decoder->buf = buf; |
|---|
| 3323 | + decoder->len = len; |
|---|
| 3324 | + intel_pt_reposition(decoder); |
|---|
| 3325 | + } else { |
|---|
| 3326 | + break; |
|---|
| 3327 | + } |
|---|
| 3328 | + } while (intel_pt_step_psb(&buf, &len)); |
|---|
| 3329 | + |
|---|
| 3330 | + return 0; |
|---|
| 3331 | +} |
|---|