diff options
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 162 | ||||
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 |
2 files changed, 159 insertions, 4 deletions
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 4a0e9fb1d173..f7119a11a4b6 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
@@ -85,7 +85,9 @@ struct intel_pt_decoder { | |||
85 | const unsigned char *buf; | 85 | const unsigned char *buf; |
86 | size_t len; | 86 | size_t len; |
87 | bool return_compression; | 87 | bool return_compression; |
88 | bool mtc_insn; | ||
88 | bool pge; | 89 | bool pge; |
90 | bool have_tma; | ||
89 | uint64_t pos; | 91 | uint64_t pos; |
90 | uint64_t last_ip; | 92 | uint64_t last_ip; |
91 | uint64_t ip; | 93 | uint64_t ip; |
@@ -94,6 +96,15 @@ struct intel_pt_decoder { | |||
94 | uint64_t tsc_timestamp; | 96 | uint64_t tsc_timestamp; |
95 | uint64_t ref_timestamp; | 97 | uint64_t ref_timestamp; |
96 | uint64_t ret_addr; | 98 | uint64_t ret_addr; |
99 | uint64_t ctc_timestamp; | ||
100 | uint64_t ctc_delta; | ||
101 | uint32_t last_mtc; | ||
102 | uint32_t tsc_ctc_ratio_n; | ||
103 | uint32_t tsc_ctc_ratio_d; | ||
104 | uint32_t tsc_ctc_mult; | ||
105 | uint32_t tsc_slip; | ||
106 | uint32_t ctc_rem_mask; | ||
107 | int mtc_shift; | ||
97 | struct intel_pt_stack stack; | 108 | struct intel_pt_stack stack; |
98 | enum intel_pt_pkt_state pkt_state; | 109 | enum intel_pt_pkt_state pkt_state; |
99 | struct intel_pt_pkt packet; | 110 | struct intel_pt_pkt packet; |
@@ -149,6 +160,13 @@ static void intel_pt_setup_period(struct intel_pt_decoder *decoder) | |||
149 | } | 160 | } |
150 | } | 161 | } |
151 | 162 | ||
163 | static uint64_t multdiv(uint64_t t, uint32_t n, uint32_t d) | ||
164 | { | ||
165 | if (!d) | ||
166 | return 0; | ||
167 | return (t / d) * n + ((t % d) * n) / d; | ||
168 | } | ||
169 | |||
152 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | 170 | struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) |
153 | { | 171 | { |
154 | struct intel_pt_decoder *decoder; | 172 | struct intel_pt_decoder *decoder; |
@@ -175,6 +193,39 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | |||
175 | 193 | ||
176 | intel_pt_setup_period(decoder); | 194 | intel_pt_setup_period(decoder); |
177 | 195 | ||
196 | decoder->mtc_shift = params->mtc_period; | ||
197 | decoder->ctc_rem_mask = (1 << decoder->mtc_shift) - 1; | ||
198 | |||
199 | decoder->tsc_ctc_ratio_n = params->tsc_ctc_ratio_n; | ||
200 | decoder->tsc_ctc_ratio_d = params->tsc_ctc_ratio_d; | ||
201 | |||
202 | if (!decoder->tsc_ctc_ratio_n) | ||
203 | decoder->tsc_ctc_ratio_d = 0; | ||
204 | |||
205 | if (decoder->tsc_ctc_ratio_d) { | ||
206 | if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d)) | ||
207 | decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n / | ||
208 | decoder->tsc_ctc_ratio_d; | ||
209 | |||
210 | /* | ||
211 | * Allow for timestamps appearing to backwards because a TSC | ||
212 | * packet has slipped past a MTC packet, so allow 2 MTC ticks | ||
213 | * or ... | ||
214 | */ | ||
215 | decoder->tsc_slip = multdiv(2 << decoder->mtc_shift, | ||
216 | decoder->tsc_ctc_ratio_n, | ||
217 | decoder->tsc_ctc_ratio_d); | ||
218 | } | ||
219 | /* ... or 0x100 paranoia */ | ||
220 | if (decoder->tsc_slip < 0x100) | ||
221 | decoder->tsc_slip = 0x100; | ||
222 | |||
223 | intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift); | ||
224 | intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n); | ||
225 | intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d); | ||
226 | intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult); | ||
227 | intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip); | ||
228 | |||
178 | return decoder; | 229 | return decoder; |
179 | } | 230 | } |
180 | 231 | ||
@@ -368,6 +419,7 @@ static inline void intel_pt_update_in_tx(struct intel_pt_decoder *decoder) | |||
368 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) | 419 | static int intel_pt_bad_packet(struct intel_pt_decoder *decoder) |
369 | { | 420 | { |
370 | intel_pt_clear_tx_flags(decoder); | 421 | intel_pt_clear_tx_flags(decoder); |
422 | decoder->have_tma = false; | ||
371 | decoder->pkt_len = 1; | 423 | decoder->pkt_len = 1; |
372 | decoder->pkt_step = 1; | 424 | decoder->pkt_step = 1; |
373 | intel_pt_decoder_log_packet(decoder); | 425 | intel_pt_decoder_log_packet(decoder); |
@@ -400,6 +452,7 @@ static int intel_pt_get_data(struct intel_pt_decoder *decoder) | |||
400 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; | 452 | decoder->pkt_state = INTEL_PT_STATE_NO_PSB; |
401 | decoder->ref_timestamp = buffer.ref_timestamp; | 453 | decoder->ref_timestamp = buffer.ref_timestamp; |
402 | decoder->timestamp = 0; | 454 | decoder->timestamp = 0; |
455 | decoder->have_tma = false; | ||
403 | decoder->state.trace_nr = buffer.trace_nr; | 456 | decoder->state.trace_nr = buffer.trace_nr; |
404 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", | 457 | intel_pt_log("Reference timestamp 0x%" PRIx64 "\n", |
405 | decoder->ref_timestamp); | 458 | decoder->ref_timestamp); |
@@ -523,6 +576,7 @@ static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder) | |||
523 | case INTEL_PT_PERIOD_TICKS: | 576 | case INTEL_PT_PERIOD_TICKS: |
524 | return intel_pt_next_period(decoder); | 577 | return intel_pt_next_period(decoder); |
525 | case INTEL_PT_PERIOD_NONE: | 578 | case INTEL_PT_PERIOD_NONE: |
579 | case INTEL_PT_PERIOD_MTC: | ||
526 | default: | 580 | default: |
527 | return 0; | 581 | return 0; |
528 | } | 582 | } |
@@ -542,6 +596,7 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder) | |||
542 | decoder->last_masked_timestamp = masked_timestamp; | 596 | decoder->last_masked_timestamp = masked_timestamp; |
543 | break; | 597 | break; |
544 | case INTEL_PT_PERIOD_NONE: | 598 | case INTEL_PT_PERIOD_NONE: |
599 | case INTEL_PT_PERIOD_MTC: | ||
545 | default: | 600 | default: |
546 | break; | 601 | break; |
547 | } | 602 | } |
@@ -555,6 +610,9 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, | |||
555 | uint64_t max_insn_cnt, insn_cnt = 0; | 610 | uint64_t max_insn_cnt, insn_cnt = 0; |
556 | int err; | 611 | int err; |
557 | 612 | ||
613 | if (!decoder->mtc_insn) | ||
614 | decoder->mtc_insn = true; | ||
615 | |||
558 | max_insn_cnt = intel_pt_next_sample(decoder); | 616 | max_insn_cnt = intel_pt_next_sample(decoder); |
559 | 617 | ||
560 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, | 618 | err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip, |
@@ -861,6 +919,8 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
861 | { | 919 | { |
862 | uint64_t timestamp; | 920 | uint64_t timestamp; |
863 | 921 | ||
922 | decoder->have_tma = false; | ||
923 | |||
864 | if (decoder->ref_timestamp) { | 924 | if (decoder->ref_timestamp) { |
865 | timestamp = decoder->packet.payload | | 925 | timestamp = decoder->packet.payload | |
866 | (decoder->ref_timestamp & (0xffULL << 56)); | 926 | (decoder->ref_timestamp & (0xffULL << 56)); |
@@ -878,17 +938,18 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
878 | } else if (decoder->timestamp) { | 938 | } else if (decoder->timestamp) { |
879 | timestamp = decoder->packet.payload | | 939 | timestamp = decoder->packet.payload | |
880 | (decoder->timestamp & (0xffULL << 56)); | 940 | (decoder->timestamp & (0xffULL << 56)); |
941 | decoder->tsc_timestamp = timestamp; | ||
881 | if (timestamp < decoder->timestamp && | 942 | if (timestamp < decoder->timestamp && |
882 | decoder->timestamp - timestamp < 0x100) { | 943 | decoder->timestamp - timestamp < decoder->tsc_slip) { |
883 | intel_pt_log_to("ERROR: Suppressing backwards timestamp", | 944 | intel_pt_log_to("Suppressing backwards timestamp", |
884 | timestamp); | 945 | timestamp); |
885 | timestamp = decoder->timestamp; | 946 | timestamp = decoder->timestamp; |
886 | } | 947 | } |
887 | while (timestamp < decoder->timestamp) { | 948 | while (timestamp < decoder->timestamp) { |
888 | intel_pt_log_to("Wraparound timestamp", timestamp); | 949 | intel_pt_log_to("Wraparound timestamp", timestamp); |
889 | timestamp += (1ULL << 56); | 950 | timestamp += (1ULL << 56); |
951 | decoder->tsc_timestamp = timestamp; | ||
890 | } | 952 | } |
891 | decoder->tsc_timestamp = timestamp; | ||
892 | decoder->timestamp = timestamp; | 953 | decoder->timestamp = timestamp; |
893 | decoder->timestamp_insn_cnt = 0; | 954 | decoder->timestamp_insn_cnt = 0; |
894 | } | 955 | } |
@@ -900,11 +961,73 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) | |||
900 | { | 961 | { |
901 | intel_pt_log("ERROR: Buffer overflow\n"); | 962 | intel_pt_log("ERROR: Buffer overflow\n"); |
902 | intel_pt_clear_tx_flags(decoder); | 963 | intel_pt_clear_tx_flags(decoder); |
964 | decoder->have_tma = false; | ||
903 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; | 965 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; |
904 | decoder->overflow = true; | 966 | decoder->overflow = true; |
905 | return -EOVERFLOW; | 967 | return -EOVERFLOW; |
906 | } | 968 | } |
907 | 969 | ||
970 | static void intel_pt_calc_tma(struct intel_pt_decoder *decoder) | ||
971 | { | ||
972 | uint32_t ctc = decoder->packet.payload; | ||
973 | uint32_t fc = decoder->packet.count; | ||
974 | uint32_t ctc_rem = ctc & decoder->ctc_rem_mask; | ||
975 | |||
976 | if (!decoder->tsc_ctc_ratio_d) | ||
977 | return; | ||
978 | |||
979 | decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff; | ||
980 | decoder->ctc_timestamp = decoder->tsc_timestamp - fc; | ||
981 | if (decoder->tsc_ctc_mult) { | ||
982 | decoder->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult; | ||
983 | } else { | ||
984 | decoder->ctc_timestamp -= multdiv(ctc_rem, | ||
985 | decoder->tsc_ctc_ratio_n, | ||
986 | decoder->tsc_ctc_ratio_d); | ||
987 | } | ||
988 | decoder->ctc_delta = 0; | ||
989 | decoder->have_tma = true; | ||
990 | intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n", | ||
991 | decoder->ctc_timestamp, decoder->last_mtc, ctc_rem); | ||
992 | } | ||
993 | |||
994 | static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder) | ||
995 | { | ||
996 | uint64_t timestamp; | ||
997 | uint32_t mtc, mtc_delta; | ||
998 | |||
999 | if (!decoder->have_tma) | ||
1000 | return; | ||
1001 | |||
1002 | mtc = decoder->packet.payload; | ||
1003 | |||
1004 | if (mtc > decoder->last_mtc) | ||
1005 | mtc_delta = mtc - decoder->last_mtc; | ||
1006 | else | ||
1007 | mtc_delta = mtc + 256 - decoder->last_mtc; | ||
1008 | |||
1009 | decoder->ctc_delta += mtc_delta << decoder->mtc_shift; | ||
1010 | |||
1011 | if (decoder->tsc_ctc_mult) { | ||
1012 | timestamp = decoder->ctc_timestamp + | ||
1013 | decoder->ctc_delta * decoder->tsc_ctc_mult; | ||
1014 | } else { | ||
1015 | timestamp = decoder->ctc_timestamp + | ||
1016 | multdiv(decoder->ctc_delta, | ||
1017 | decoder->tsc_ctc_ratio_n, | ||
1018 | decoder->tsc_ctc_ratio_d); | ||
1019 | } | ||
1020 | |||
1021 | if (timestamp < decoder->timestamp) | ||
1022 | intel_pt_log("Suppressing MTC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n", | ||
1023 | timestamp, decoder->timestamp); | ||
1024 | else | ||
1025 | decoder->timestamp = timestamp; | ||
1026 | |||
1027 | decoder->timestamp_insn_cnt = 0; | ||
1028 | decoder->last_mtc = mtc; | ||
1029 | } | ||
1030 | |||
908 | /* Walk PSB+ packets when already in sync. */ | 1031 | /* Walk PSB+ packets when already in sync. */ |
909 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | 1032 | static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) |
910 | { | 1033 | { |
@@ -926,6 +1049,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
926 | case INTEL_PT_TRACESTOP: | 1049 | case INTEL_PT_TRACESTOP: |
927 | case INTEL_PT_BAD: | 1050 | case INTEL_PT_BAD: |
928 | case INTEL_PT_PSB: | 1051 | case INTEL_PT_PSB: |
1052 | decoder->have_tma = false; | ||
929 | intel_pt_log("ERROR: Unexpected packet\n"); | 1053 | intel_pt_log("ERROR: Unexpected packet\n"); |
930 | return -EAGAIN; | 1054 | return -EAGAIN; |
931 | 1055 | ||
@@ -937,6 +1061,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
937 | break; | 1061 | break; |
938 | 1062 | ||
939 | case INTEL_PT_TMA: | 1063 | case INTEL_PT_TMA: |
1064 | intel_pt_calc_tma(decoder); | ||
940 | break; | 1065 | break; |
941 | 1066 | ||
942 | case INTEL_PT_CBR: | 1067 | case INTEL_PT_CBR: |
@@ -961,6 +1086,9 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) | |||
961 | break; | 1086 | break; |
962 | 1087 | ||
963 | case INTEL_PT_MTC: | 1088 | case INTEL_PT_MTC: |
1089 | intel_pt_calc_mtc_timestamp(decoder); | ||
1090 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
1091 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
964 | break; | 1092 | break; |
965 | 1093 | ||
966 | case INTEL_PT_CYC: | 1094 | case INTEL_PT_CYC: |
@@ -1048,6 +1176,9 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder) | |||
1048 | break; | 1176 | break; |
1049 | 1177 | ||
1050 | case INTEL_PT_MTC: | 1178 | case INTEL_PT_MTC: |
1179 | intel_pt_calc_mtc_timestamp(decoder); | ||
1180 | if (decoder->period_type == INTEL_PT_PERIOD_MTC) | ||
1181 | decoder->state.type |= INTEL_PT_INSTRUCTION; | ||
1051 | break; | 1182 | break; |
1052 | 1183 | ||
1053 | case INTEL_PT_CYC: | 1184 | case INTEL_PT_CYC: |
@@ -1159,13 +1290,31 @@ next: | |||
1159 | break; | 1290 | break; |
1160 | 1291 | ||
1161 | case INTEL_PT_MTC: | 1292 | case INTEL_PT_MTC: |
1162 | break; | 1293 | intel_pt_calc_mtc_timestamp(decoder); |
1294 | if (decoder->period_type != INTEL_PT_PERIOD_MTC) | ||
1295 | break; | ||
1296 | /* | ||
1297 | * Ensure that there has been an instruction since the | ||
1298 | * last MTC. | ||
1299 | */ | ||
1300 | if (!decoder->mtc_insn) | ||
1301 | break; | ||
1302 | decoder->mtc_insn = false; | ||
1303 | /* Ensure that there is a timestamp */ | ||
1304 | if (!decoder->timestamp) | ||
1305 | break; | ||
1306 | decoder->state.type = INTEL_PT_INSTRUCTION; | ||
1307 | decoder->state.from_ip = decoder->ip; | ||
1308 | decoder->state.to_ip = 0; | ||
1309 | decoder->mtc_insn = false; | ||
1310 | return 0; | ||
1163 | 1311 | ||
1164 | case INTEL_PT_TSC: | 1312 | case INTEL_PT_TSC: |
1165 | intel_pt_calc_tsc_timestamp(decoder); | 1313 | intel_pt_calc_tsc_timestamp(decoder); |
1166 | break; | 1314 | break; |
1167 | 1315 | ||
1168 | case INTEL_PT_TMA: | 1316 | case INTEL_PT_TMA: |
1317 | intel_pt_calc_tma(decoder); | ||
1169 | break; | 1318 | break; |
1170 | 1319 | ||
1171 | case INTEL_PT_CYC: | 1320 | case INTEL_PT_CYC: |
@@ -1237,6 +1386,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1237 | break; | 1386 | break; |
1238 | 1387 | ||
1239 | case INTEL_PT_MTC: | 1388 | case INTEL_PT_MTC: |
1389 | intel_pt_calc_mtc_timestamp(decoder); | ||
1240 | break; | 1390 | break; |
1241 | 1391 | ||
1242 | case INTEL_PT_TSC: | 1392 | case INTEL_PT_TSC: |
@@ -1244,6 +1394,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1244 | break; | 1394 | break; |
1245 | 1395 | ||
1246 | case INTEL_PT_TMA: | 1396 | case INTEL_PT_TMA: |
1397 | intel_pt_calc_tma(decoder); | ||
1247 | break; | 1398 | break; |
1248 | 1399 | ||
1249 | case INTEL_PT_CYC: | 1400 | case INTEL_PT_CYC: |
@@ -1267,6 +1418,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) | |||
1267 | 1418 | ||
1268 | case INTEL_PT_TRACESTOP: | 1419 | case INTEL_PT_TRACESTOP: |
1269 | case INTEL_PT_TNT: | 1420 | case INTEL_PT_TNT: |
1421 | decoder->have_tma = false; | ||
1270 | intel_pt_log("ERROR: Unexpected packet\n"); | 1422 | intel_pt_log("ERROR: Unexpected packet\n"); |
1271 | if (decoder->ip) | 1423 | if (decoder->ip) |
1272 | decoder->pkt_state = INTEL_PT_STATE_ERR4; | 1424 | decoder->pkt_state = INTEL_PT_STATE_ERR4; |
@@ -1329,6 +1481,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
1329 | break; | 1481 | break; |
1330 | 1482 | ||
1331 | case INTEL_PT_MTC: | 1483 | case INTEL_PT_MTC: |
1484 | intel_pt_calc_mtc_timestamp(decoder); | ||
1332 | break; | 1485 | break; |
1333 | 1486 | ||
1334 | case INTEL_PT_TSC: | 1487 | case INTEL_PT_TSC: |
@@ -1336,6 +1489,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder) | |||
1336 | break; | 1489 | break; |
1337 | 1490 | ||
1338 | case INTEL_PT_TMA: | 1491 | case INTEL_PT_TMA: |
1492 | intel_pt_calc_tma(decoder); | ||
1339 | break; | 1493 | break; |
1340 | 1494 | ||
1341 | case INTEL_PT_CYC: | 1495 | case INTEL_PT_CYC: |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 56cc47baca11..02c38fec1c37 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h | |||
@@ -36,6 +36,7 @@ enum intel_pt_period_type { | |||
36 | INTEL_PT_PERIOD_NONE, | 36 | INTEL_PT_PERIOD_NONE, |
37 | INTEL_PT_PERIOD_INSTRUCTIONS, | 37 | INTEL_PT_PERIOD_INSTRUCTIONS, |
38 | INTEL_PT_PERIOD_TICKS, | 38 | INTEL_PT_PERIOD_TICKS, |
39 | INTEL_PT_PERIOD_MTC, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | enum { | 42 | enum { |