]>
Commit | Line | Data |
---|---|---|
2025cf9e | 1 | // SPDX-License-Identifier: GPL-2.0-only |
a4e92590 AH |
2 | /* |
3 | * intel_pt_pkt_decoder.c: Intel Processor Trace support | |
4 | * Copyright (c) 2013-2014, Intel Corporation. | |
a4e92590 AH |
5 | */ |
6 | ||
7 | #include <stdio.h> | |
8 | #include <string.h> | |
9 | #include <endian.h> | |
10 | #include <byteswap.h> | |
7ea6856d | 11 | #include <linux/compiler.h> |
a4e92590 AH |
12 | |
13 | #include "intel-pt-pkt-decoder.h" | |
14 | ||
15 | #define BIT(n) (1 << (n)) | |
16 | ||
17 | #define BIT63 ((uint64_t)1 << 63) | |
18 | ||
3d498078 AH |
19 | #define NR_FLAG BIT63 |
20 | ||
a4e92590 AH |
21 | #if __BYTE_ORDER == __BIG_ENDIAN |
22 | #define le16_to_cpu bswap_16 | |
23 | #define le32_to_cpu bswap_32 | |
24 | #define le64_to_cpu bswap_64 | |
25 | #define memcpy_le64(d, s, n) do { \ | |
26 | memcpy((d), (s), (n)); \ | |
27 | *(d) = le64_to_cpu(*(d)); \ | |
28 | } while (0) | |
29 | #else | |
30 | #define le16_to_cpu | |
31 | #define le32_to_cpu | |
32 | #define le64_to_cpu | |
33 | #define memcpy_le64 memcpy | |
34 | #endif | |
35 | ||
36 | static const char * const packet_name[] = { | |
37 | [INTEL_PT_BAD] = "Bad Packet!", | |
38 | [INTEL_PT_PAD] = "PAD", | |
39 | [INTEL_PT_TNT] = "TNT", | |
40 | [INTEL_PT_TIP_PGD] = "TIP.PGD", | |
41 | [INTEL_PT_TIP_PGE] = "TIP.PGE", | |
42 | [INTEL_PT_TSC] = "TSC", | |
3d498078 | 43 | [INTEL_PT_TMA] = "TMA", |
a4e92590 AH |
44 | [INTEL_PT_MODE_EXEC] = "MODE.Exec", |
45 | [INTEL_PT_MODE_TSX] = "MODE.TSX", | |
3d498078 | 46 | [INTEL_PT_MTC] = "MTC", |
a4e92590 AH |
47 | [INTEL_PT_TIP] = "TIP", |
48 | [INTEL_PT_FUP] = "FUP", | |
3d498078 AH |
49 | [INTEL_PT_CYC] = "CYC", |
50 | [INTEL_PT_VMCS] = "VMCS", | |
a4e92590 AH |
51 | [INTEL_PT_PSB] = "PSB", |
52 | [INTEL_PT_PSBEND] = "PSBEND", | |
53 | [INTEL_PT_CBR] = "CBR", | |
3d498078 | 54 | [INTEL_PT_TRACESTOP] = "TraceSTOP", |
a4e92590 AH |
55 | [INTEL_PT_PIP] = "PIP", |
56 | [INTEL_PT_OVF] = "OVF", | |
3d498078 | 57 | [INTEL_PT_MNT] = "MNT", |
a472e65f AH |
58 | [INTEL_PT_PTWRITE] = "PTWRITE", |
59 | [INTEL_PT_PTWRITE_IP] = "PTWRITE", | |
60 | [INTEL_PT_EXSTOP] = "EXSTOP", | |
61 | [INTEL_PT_EXSTOP_IP] = "EXSTOP", | |
62 | [INTEL_PT_MWAIT] = "MWAIT", | |
63 | [INTEL_PT_PWRE] = "PWRE", | |
64 | [INTEL_PT_PWRX] = "PWRX", | |
edff7809 AH |
65 | [INTEL_PT_BBP] = "BBP", |
66 | [INTEL_PT_BIP] = "BIP", | |
67 | [INTEL_PT_BEP] = "BEP", | |
68 | [INTEL_PT_BEP_IP] = "BEP", | |
a4e92590 AH |
69 | }; |
70 | ||
71 | const char *intel_pt_pkt_name(enum intel_pt_pkt_type type) | |
72 | { | |
73 | return packet_name[type]; | |
74 | } | |
75 | ||
76 | static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len, | |
77 | struct intel_pt_pkt *packet) | |
78 | { | |
79 | uint64_t payload; | |
80 | int count; | |
81 | ||
82 | if (len < 8) | |
83 | return INTEL_PT_NEED_MORE_BYTES; | |
84 | ||
85 | payload = le64_to_cpu(*(uint64_t *)buf); | |
86 | ||
87 | for (count = 47; count; count--) { | |
88 | if (payload & BIT63) | |
89 | break; | |
90 | payload <<= 1; | |
91 | } | |
92 | ||
93 | packet->type = INTEL_PT_TNT; | |
94 | packet->count = count; | |
95 | packet->payload = payload << 1; | |
96 | return 8; | |
97 | } | |
98 | ||
99 | static int intel_pt_get_pip(const unsigned char *buf, size_t len, | |
100 | struct intel_pt_pkt *packet) | |
101 | { | |
102 | uint64_t payload = 0; | |
103 | ||
104 | if (len < 8) | |
105 | return INTEL_PT_NEED_MORE_BYTES; | |
106 | ||
107 | packet->type = INTEL_PT_PIP; | |
108 | memcpy_le64(&payload, buf + 2, 6); | |
109 | packet->payload = payload >> 1; | |
3d498078 AH |
110 | if (payload & 1) |
111 | packet->payload |= NR_FLAG; | |
a4e92590 AH |
112 | |
113 | return 8; | |
114 | } | |
115 | ||
3d498078 AH |
116 | static int intel_pt_get_tracestop(struct intel_pt_pkt *packet) |
117 | { | |
118 | packet->type = INTEL_PT_TRACESTOP; | |
119 | return 2; | |
120 | } | |
121 | ||
a4e92590 AH |
122 | static int intel_pt_get_cbr(const unsigned char *buf, size_t len, |
123 | struct intel_pt_pkt *packet) | |
124 | { | |
125 | if (len < 4) | |
126 | return INTEL_PT_NEED_MORE_BYTES; | |
127 | packet->type = INTEL_PT_CBR; | |
26fb2fb1 | 128 | packet->payload = le16_to_cpu(*(uint16_t *)(buf + 2)); |
a4e92590 AH |
129 | return 4; |
130 | } | |
131 | ||
3d498078 AH |
132 | static int intel_pt_get_vmcs(const unsigned char *buf, size_t len, |
133 | struct intel_pt_pkt *packet) | |
134 | { | |
135 | unsigned int count = (52 - 5) >> 3; | |
136 | ||
137 | if (count < 1 || count > 7) | |
138 | return INTEL_PT_BAD_PACKET; | |
139 | ||
140 | if (len < count + 2) | |
141 | return INTEL_PT_NEED_MORE_BYTES; | |
142 | ||
143 | packet->type = INTEL_PT_VMCS; | |
144 | packet->count = count; | |
145 | memcpy_le64(&packet->payload, buf + 2, count); | |
146 | ||
147 | return count + 2; | |
148 | } | |
149 | ||
a4e92590 AH |
150 | static int intel_pt_get_ovf(struct intel_pt_pkt *packet) |
151 | { | |
152 | packet->type = INTEL_PT_OVF; | |
153 | return 2; | |
154 | } | |
155 | ||
156 | static int intel_pt_get_psb(const unsigned char *buf, size_t len, | |
157 | struct intel_pt_pkt *packet) | |
158 | { | |
159 | int i; | |
160 | ||
161 | if (len < 16) | |
162 | return INTEL_PT_NEED_MORE_BYTES; | |
163 | ||
164 | for (i = 2; i < 16; i += 2) { | |
165 | if (buf[i] != 2 || buf[i + 1] != 0x82) | |
166 | return INTEL_PT_BAD_PACKET; | |
167 | } | |
168 | ||
169 | packet->type = INTEL_PT_PSB; | |
170 | return 16; | |
171 | } | |
172 | ||
173 | static int intel_pt_get_psbend(struct intel_pt_pkt *packet) | |
174 | { | |
175 | packet->type = INTEL_PT_PSBEND; | |
176 | return 2; | |
177 | } | |
178 | ||
3d498078 AH |
179 | static int intel_pt_get_tma(const unsigned char *buf, size_t len, |
180 | struct intel_pt_pkt *packet) | |
181 | { | |
182 | if (len < 7) | |
183 | return INTEL_PT_NEED_MORE_BYTES; | |
184 | ||
185 | packet->type = INTEL_PT_TMA; | |
186 | packet->payload = buf[2] | (buf[3] << 8); | |
187 | packet->count = buf[5] | ((buf[6] & BIT(0)) << 8); | |
188 | return 7; | |
189 | } | |
190 | ||
a4e92590 AH |
191 | static int intel_pt_get_pad(struct intel_pt_pkt *packet) |
192 | { | |
193 | packet->type = INTEL_PT_PAD; | |
194 | return 1; | |
195 | } | |
196 | ||
3d498078 AH |
197 | static int intel_pt_get_mnt(const unsigned char *buf, size_t len, |
198 | struct intel_pt_pkt *packet) | |
199 | { | |
200 | if (len < 11) | |
201 | return INTEL_PT_NEED_MORE_BYTES; | |
202 | packet->type = INTEL_PT_MNT; | |
203 | memcpy_le64(&packet->payload, buf + 3, 8); | |
204 | return 11 | |
205 | ; | |
206 | } | |
207 | ||
208 | static int intel_pt_get_3byte(const unsigned char *buf, size_t len, | |
209 | struct intel_pt_pkt *packet) | |
210 | { | |
211 | if (len < 3) | |
212 | return INTEL_PT_NEED_MORE_BYTES; | |
213 | ||
214 | switch (buf[2]) { | |
215 | case 0x88: /* MNT */ | |
216 | return intel_pt_get_mnt(buf, len, packet); | |
217 | default: | |
218 | return INTEL_PT_BAD_PACKET; | |
219 | } | |
220 | } | |
221 | ||
a472e65f AH |
222 | static int intel_pt_get_ptwrite(const unsigned char *buf, size_t len, |
223 | struct intel_pt_pkt *packet) | |
224 | { | |
225 | packet->count = (buf[1] >> 5) & 0x3; | |
226 | packet->type = buf[1] & BIT(7) ? INTEL_PT_PTWRITE_IP : | |
227 | INTEL_PT_PTWRITE; | |
228 | ||
229 | switch (packet->count) { | |
230 | case 0: | |
231 | if (len < 6) | |
232 | return INTEL_PT_NEED_MORE_BYTES; | |
233 | packet->payload = le32_to_cpu(*(uint32_t *)(buf + 2)); | |
234 | return 6; | |
235 | case 1: | |
236 | if (len < 10) | |
237 | return INTEL_PT_NEED_MORE_BYTES; | |
238 | packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); | |
239 | return 10; | |
240 | default: | |
241 | return INTEL_PT_BAD_PACKET; | |
242 | } | |
243 | } | |
244 | ||
245 | static int intel_pt_get_exstop(struct intel_pt_pkt *packet) | |
246 | { | |
247 | packet->type = INTEL_PT_EXSTOP; | |
248 | return 2; | |
249 | } | |
250 | ||
251 | static int intel_pt_get_exstop_ip(struct intel_pt_pkt *packet) | |
252 | { | |
253 | packet->type = INTEL_PT_EXSTOP_IP; | |
254 | return 2; | |
255 | } | |
256 | ||
257 | static int intel_pt_get_mwait(const unsigned char *buf, size_t len, | |
258 | struct intel_pt_pkt *packet) | |
259 | { | |
260 | if (len < 10) | |
261 | return INTEL_PT_NEED_MORE_BYTES; | |
262 | packet->type = INTEL_PT_MWAIT; | |
263 | packet->payload = le64_to_cpu(*(uint64_t *)(buf + 2)); | |
264 | return 10; | |
265 | } | |
266 | ||
267 | static int intel_pt_get_pwre(const unsigned char *buf, size_t len, | |
268 | struct intel_pt_pkt *packet) | |
269 | { | |
270 | if (len < 4) | |
271 | return INTEL_PT_NEED_MORE_BYTES; | |
272 | packet->type = INTEL_PT_PWRE; | |
273 | memcpy_le64(&packet->payload, buf + 2, 2); | |
274 | return 4; | |
275 | } | |
276 | ||
277 | static int intel_pt_get_pwrx(const unsigned char *buf, size_t len, | |
278 | struct intel_pt_pkt *packet) | |
279 | { | |
280 | if (len < 7) | |
281 | return INTEL_PT_NEED_MORE_BYTES; | |
282 | packet->type = INTEL_PT_PWRX; | |
283 | memcpy_le64(&packet->payload, buf + 2, 5); | |
284 | return 7; | |
285 | } | |
286 | ||
edff7809 AH |
287 | static int intel_pt_get_bbp(const unsigned char *buf, size_t len, |
288 | struct intel_pt_pkt *packet) | |
289 | { | |
290 | if (len < 3) | |
291 | return INTEL_PT_NEED_MORE_BYTES; | |
292 | packet->type = INTEL_PT_BBP; | |
293 | packet->count = buf[2] >> 7; | |
294 | packet->payload = buf[2] & 0x1f; | |
295 | return 3; | |
296 | } | |
297 | ||
298 | static int intel_pt_get_bip_4(const unsigned char *buf, size_t len, | |
299 | struct intel_pt_pkt *packet) | |
300 | { | |
301 | if (len < 5) | |
302 | return INTEL_PT_NEED_MORE_BYTES; | |
303 | packet->type = INTEL_PT_BIP; | |
304 | packet->count = buf[0] >> 3; | |
305 | memcpy_le64(&packet->payload, buf + 1, 4); | |
306 | return 5; | |
307 | } | |
308 | ||
309 | static int intel_pt_get_bip_8(const unsigned char *buf, size_t len, | |
310 | struct intel_pt_pkt *packet) | |
311 | { | |
312 | if (len < 9) | |
313 | return INTEL_PT_NEED_MORE_BYTES; | |
314 | packet->type = INTEL_PT_BIP; | |
315 | packet->count = buf[0] >> 3; | |
316 | memcpy_le64(&packet->payload, buf + 1, 8); | |
317 | return 9; | |
318 | } | |
319 | ||
320 | static int intel_pt_get_bep(size_t len, struct intel_pt_pkt *packet) | |
321 | { | |
322 | if (len < 2) | |
323 | return INTEL_PT_NEED_MORE_BYTES; | |
324 | packet->type = INTEL_PT_BEP; | |
325 | return 2; | |
326 | } | |
327 | ||
328 | static int intel_pt_get_bep_ip(size_t len, struct intel_pt_pkt *packet) | |
329 | { | |
330 | if (len < 2) | |
331 | return INTEL_PT_NEED_MORE_BYTES; | |
332 | packet->type = INTEL_PT_BEP_IP; | |
333 | return 2; | |
334 | } | |
335 | ||
a4e92590 AH |
336 | static int intel_pt_get_ext(const unsigned char *buf, size_t len, |
337 | struct intel_pt_pkt *packet) | |
338 | { | |
339 | if (len < 2) | |
340 | return INTEL_PT_NEED_MORE_BYTES; | |
341 | ||
a472e65f AH |
342 | if ((buf[1] & 0x1f) == 0x12) |
343 | return intel_pt_get_ptwrite(buf, len, packet); | |
344 | ||
a4e92590 AH |
345 | switch (buf[1]) { |
346 | case 0xa3: /* Long TNT */ | |
347 | return intel_pt_get_long_tnt(buf, len, packet); | |
348 | case 0x43: /* PIP */ | |
349 | return intel_pt_get_pip(buf, len, packet); | |
3d498078 AH |
350 | case 0x83: /* TraceStop */ |
351 | return intel_pt_get_tracestop(packet); | |
a4e92590 AH |
352 | case 0x03: /* CBR */ |
353 | return intel_pt_get_cbr(buf, len, packet); | |
3d498078 AH |
354 | case 0xc8: /* VMCS */ |
355 | return intel_pt_get_vmcs(buf, len, packet); | |
a4e92590 AH |
356 | case 0xf3: /* OVF */ |
357 | return intel_pt_get_ovf(packet); | |
358 | case 0x82: /* PSB */ | |
359 | return intel_pt_get_psb(buf, len, packet); | |
360 | case 0x23: /* PSBEND */ | |
361 | return intel_pt_get_psbend(packet); | |
3d498078 AH |
362 | case 0x73: /* TMA */ |
363 | return intel_pt_get_tma(buf, len, packet); | |
364 | case 0xC3: /* 3-byte header */ | |
365 | return intel_pt_get_3byte(buf, len, packet); | |
a472e65f AH |
366 | case 0x62: /* EXSTOP no IP */ |
367 | return intel_pt_get_exstop(packet); | |
368 | case 0xE2: /* EXSTOP with IP */ | |
369 | return intel_pt_get_exstop_ip(packet); | |
370 | case 0xC2: /* MWAIT */ | |
371 | return intel_pt_get_mwait(buf, len, packet); | |
372 | case 0x22: /* PWRE */ | |
373 | return intel_pt_get_pwre(buf, len, packet); | |
374 | case 0xA2: /* PWRX */ | |
375 | return intel_pt_get_pwrx(buf, len, packet); | |
edff7809 AH |
376 | case 0x63: /* BBP */ |
377 | return intel_pt_get_bbp(buf, len, packet); | |
378 | case 0x33: /* BEP no IP */ | |
379 | return intel_pt_get_bep(len, packet); | |
380 | case 0xb3: /* BEP with IP */ | |
381 | return intel_pt_get_bep_ip(len, packet); | |
a4e92590 AH |
382 | default: |
383 | return INTEL_PT_BAD_PACKET; | |
384 | } | |
385 | } | |
386 | ||
387 | static int intel_pt_get_short_tnt(unsigned int byte, | |
388 | struct intel_pt_pkt *packet) | |
389 | { | |
390 | int count; | |
391 | ||
392 | for (count = 6; count; count--) { | |
393 | if (byte & BIT(7)) | |
394 | break; | |
395 | byte <<= 1; | |
396 | } | |
397 | ||
398 | packet->type = INTEL_PT_TNT; | |
399 | packet->count = count; | |
400 | packet->payload = (uint64_t)byte << 57; | |
401 | ||
402 | return 1; | |
403 | } | |
404 | ||
3d498078 AH |
405 | static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, |
406 | size_t len, struct intel_pt_pkt *packet) | |
407 | { | |
408 | unsigned int offs = 1, shift; | |
409 | uint64_t payload = byte >> 3; | |
410 | ||
411 | byte >>= 2; | |
412 | len -= 1; | |
413 | for (shift = 5; byte & 1; shift += 7) { | |
414 | if (offs > 9) | |
415 | return INTEL_PT_BAD_PACKET; | |
416 | if (len < offs) | |
417 | return INTEL_PT_NEED_MORE_BYTES; | |
418 | byte = buf[offs++]; | |
621a5a32 | 419 | payload |= ((uint64_t)byte >> 1) << shift; |
3d498078 AH |
420 | } |
421 | ||
422 | packet->type = INTEL_PT_CYC; | |
423 | packet->payload = payload; | |
424 | return offs; | |
425 | } | |
426 | ||
a4e92590 AH |
427 | static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte, |
428 | const unsigned char *buf, size_t len, | |
429 | struct intel_pt_pkt *packet) | |
430 | { | |
e1717e04 AH |
431 | int ip_len; |
432 | ||
433 | packet->count = byte >> 5; | |
434 | ||
435 | switch (packet->count) { | |
a4e92590 | 436 | case 0: |
e1717e04 | 437 | ip_len = 0; |
a4e92590 AH |
438 | break; |
439 | case 1: | |
440 | if (len < 3) | |
441 | return INTEL_PT_NEED_MORE_BYTES; | |
e1717e04 | 442 | ip_len = 2; |
a4e92590 AH |
443 | packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); |
444 | break; | |
445 | case 2: | |
446 | if (len < 5) | |
447 | return INTEL_PT_NEED_MORE_BYTES; | |
e1717e04 | 448 | ip_len = 4; |
a4e92590 AH |
449 | packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); |
450 | break; | |
451 | case 3: | |
e1717e04 | 452 | case 4: |
a4e92590 AH |
453 | if (len < 7) |
454 | return INTEL_PT_NEED_MORE_BYTES; | |
e1717e04 | 455 | ip_len = 6; |
a4e92590 AH |
456 | memcpy_le64(&packet->payload, buf + 1, 6); |
457 | break; | |
e1717e04 AH |
458 | case 6: |
459 | if (len < 9) | |
460 | return INTEL_PT_NEED_MORE_BYTES; | |
461 | ip_len = 8; | |
462 | packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1)); | |
463 | break; | |
a4e92590 AH |
464 | default: |
465 | return INTEL_PT_BAD_PACKET; | |
466 | } | |
467 | ||
468 | packet->type = type; | |
469 | ||
e1717e04 | 470 | return ip_len + 1; |
a4e92590 AH |
471 | } |
472 | ||
473 | static int intel_pt_get_mode(const unsigned char *buf, size_t len, | |
474 | struct intel_pt_pkt *packet) | |
475 | { | |
476 | if (len < 2) | |
477 | return INTEL_PT_NEED_MORE_BYTES; | |
478 | ||
479 | switch (buf[1] >> 5) { | |
480 | case 0: | |
481 | packet->type = INTEL_PT_MODE_EXEC; | |
482 | switch (buf[1] & 3) { | |
483 | case 0: | |
484 | packet->payload = 16; | |
485 | break; | |
486 | case 1: | |
487 | packet->payload = 64; | |
488 | break; | |
489 | case 2: | |
490 | packet->payload = 32; | |
491 | break; | |
492 | default: | |
493 | return INTEL_PT_BAD_PACKET; | |
494 | } | |
495 | break; | |
496 | case 1: | |
497 | packet->type = INTEL_PT_MODE_TSX; | |
498 | if ((buf[1] & 3) == 3) | |
499 | return INTEL_PT_BAD_PACKET; | |
500 | packet->payload = buf[1] & 3; | |
501 | break; | |
502 | default: | |
503 | return INTEL_PT_BAD_PACKET; | |
504 | } | |
505 | ||
506 | return 2; | |
507 | } | |
508 | ||
509 | static int intel_pt_get_tsc(const unsigned char *buf, size_t len, | |
510 | struct intel_pt_pkt *packet) | |
511 | { | |
512 | if (len < 8) | |
513 | return INTEL_PT_NEED_MORE_BYTES; | |
514 | packet->type = INTEL_PT_TSC; | |
515 | memcpy_le64(&packet->payload, buf + 1, 7); | |
516 | return 8; | |
517 | } | |
518 | ||
3d498078 AH |
519 | static int intel_pt_get_mtc(const unsigned char *buf, size_t len, |
520 | struct intel_pt_pkt *packet) | |
521 | { | |
522 | if (len < 2) | |
523 | return INTEL_PT_NEED_MORE_BYTES; | |
524 | packet->type = INTEL_PT_MTC; | |
525 | packet->payload = buf[1]; | |
526 | return 2; | |
527 | } | |
528 | ||
a4e92590 | 529 | static int intel_pt_do_get_packet(const unsigned char *buf, size_t len, |
edff7809 AH |
530 | struct intel_pt_pkt *packet, |
531 | enum intel_pt_pkt_ctx ctx) | |
a4e92590 AH |
532 | { |
533 | unsigned int byte; | |
534 | ||
535 | memset(packet, 0, sizeof(struct intel_pt_pkt)); | |
536 | ||
537 | if (!len) | |
538 | return INTEL_PT_NEED_MORE_BYTES; | |
539 | ||
540 | byte = buf[0]; | |
edff7809 AH |
541 | |
542 | switch (ctx) { | |
543 | case INTEL_PT_NO_CTX: | |
544 | break; | |
545 | case INTEL_PT_BLK_4_CTX: | |
546 | if ((byte & 0x7) == 4) | |
547 | return intel_pt_get_bip_4(buf, len, packet); | |
548 | break; | |
549 | case INTEL_PT_BLK_8_CTX: | |
550 | if ((byte & 0x7) == 4) | |
551 | return intel_pt_get_bip_8(buf, len, packet); | |
552 | break; | |
553 | default: | |
554 | break; | |
8284bbea | 555 | } |
edff7809 | 556 | |
a4e92590 AH |
557 | if (!(byte & BIT(0))) { |
558 | if (byte == 0) | |
559 | return intel_pt_get_pad(packet); | |
560 | if (byte == 2) | |
561 | return intel_pt_get_ext(buf, len, packet); | |
562 | return intel_pt_get_short_tnt(byte, packet); | |
563 | } | |
564 | ||
3d498078 AH |
565 | if ((byte & 2)) |
566 | return intel_pt_get_cyc(byte, buf, len, packet); | |
567 | ||
a4e92590 AH |
568 | switch (byte & 0x1f) { |
569 | case 0x0D: | |
570 | return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet); | |
571 | case 0x11: | |
572 | return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len, | |
573 | packet); | |
574 | case 0x01: | |
575 | return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len, | |
576 | packet); | |
577 | case 0x1D: | |
578 | return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet); | |
579 | case 0x19: | |
580 | switch (byte) { | |
581 | case 0x99: | |
582 | return intel_pt_get_mode(buf, len, packet); | |
583 | case 0x19: | |
584 | return intel_pt_get_tsc(buf, len, packet); | |
3d498078 AH |
585 | case 0x59: |
586 | return intel_pt_get_mtc(buf, len, packet); | |
a4e92590 AH |
587 | default: |
588 | return INTEL_PT_BAD_PACKET; | |
589 | } | |
590 | default: | |
591 | return INTEL_PT_BAD_PACKET; | |
592 | } | |
593 | } | |
594 | ||
edff7809 AH |
595 | void intel_pt_upd_pkt_ctx(const struct intel_pt_pkt *packet, |
596 | enum intel_pt_pkt_ctx *ctx) | |
597 | { | |
598 | switch (packet->type) { | |
599 | case INTEL_PT_BAD: | |
600 | case INTEL_PT_PAD: | |
601 | case INTEL_PT_TSC: | |
602 | case INTEL_PT_TMA: | |
603 | case INTEL_PT_MTC: | |
604 | case INTEL_PT_FUP: | |
605 | case INTEL_PT_CYC: | |
606 | case INTEL_PT_CBR: | |
607 | case INTEL_PT_MNT: | |
608 | case INTEL_PT_EXSTOP: | |
609 | case INTEL_PT_EXSTOP_IP: | |
610 | case INTEL_PT_PWRE: | |
611 | case INTEL_PT_PWRX: | |
612 | case INTEL_PT_BIP: | |
613 | break; | |
614 | case INTEL_PT_TNT: | |
615 | case INTEL_PT_TIP: | |
616 | case INTEL_PT_TIP_PGD: | |
617 | case INTEL_PT_TIP_PGE: | |
618 | case INTEL_PT_MODE_EXEC: | |
619 | case INTEL_PT_MODE_TSX: | |
620 | case INTEL_PT_PIP: | |
621 | case INTEL_PT_OVF: | |
622 | case INTEL_PT_VMCS: | |
623 | case INTEL_PT_TRACESTOP: | |
624 | case INTEL_PT_PSB: | |
625 | case INTEL_PT_PSBEND: | |
626 | case INTEL_PT_PTWRITE: | |
627 | case INTEL_PT_PTWRITE_IP: | |
628 | case INTEL_PT_MWAIT: | |
629 | case INTEL_PT_BEP: | |
630 | case INTEL_PT_BEP_IP: | |
631 | *ctx = INTEL_PT_NO_CTX; | |
632 | break; | |
633 | case INTEL_PT_BBP: | |
634 | if (packet->count) | |
635 | *ctx = INTEL_PT_BLK_4_CTX; | |
636 | else | |
637 | *ctx = INTEL_PT_BLK_8_CTX; | |
638 | break; | |
639 | default: | |
640 | break; | |
641 | } | |
642 | } | |
643 | ||
a4e92590 | 644 | int intel_pt_get_packet(const unsigned char *buf, size_t len, |
edff7809 | 645 | struct intel_pt_pkt *packet, enum intel_pt_pkt_ctx *ctx) |
a4e92590 AH |
646 | { |
647 | int ret; | |
648 | ||
edff7809 | 649 | ret = intel_pt_do_get_packet(buf, len, packet, *ctx); |
a4e92590 AH |
650 | if (ret > 0) { |
651 | while (ret < 8 && len > (size_t)ret && !buf[ret]) | |
652 | ret += 1; | |
edff7809 | 653 | intel_pt_upd_pkt_ctx(packet, ctx); |
a4e92590 AH |
654 | } |
655 | return ret; | |
656 | } | |
657 | ||
658 | int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf, | |
659 | size_t buf_len) | |
660 | { | |
3d498078 | 661 | int ret, i, nr; |
a4e92590 AH |
662 | unsigned long long payload = packet->payload; |
663 | const char *name = intel_pt_pkt_name(packet->type); | |
664 | ||
665 | switch (packet->type) { | |
666 | case INTEL_PT_BAD: | |
667 | case INTEL_PT_PAD: | |
668 | case INTEL_PT_PSB: | |
669 | case INTEL_PT_PSBEND: | |
3d498078 | 670 | case INTEL_PT_TRACESTOP: |
a4e92590 AH |
671 | case INTEL_PT_OVF: |
672 | return snprintf(buf, buf_len, "%s", name); | |
673 | case INTEL_PT_TNT: { | |
674 | size_t blen = buf_len; | |
675 | ||
676 | ret = snprintf(buf, blen, "%s ", name); | |
677 | if (ret < 0) | |
678 | return ret; | |
679 | buf += ret; | |
680 | blen -= ret; | |
681 | for (i = 0; i < packet->count; i++) { | |
682 | if (payload & BIT63) | |
683 | ret = snprintf(buf, blen, "T"); | |
684 | else | |
685 | ret = snprintf(buf, blen, "N"); | |
686 | if (ret < 0) | |
687 | return ret; | |
688 | buf += ret; | |
689 | blen -= ret; | |
690 | payload <<= 1; | |
691 | } | |
692 | ret = snprintf(buf, blen, " (%d)", packet->count); | |
693 | if (ret < 0) | |
694 | return ret; | |
695 | blen -= ret; | |
696 | return buf_len - blen; | |
697 | } | |
698 | case INTEL_PT_TIP_PGD: | |
699 | case INTEL_PT_TIP_PGE: | |
700 | case INTEL_PT_TIP: | |
701 | case INTEL_PT_FUP: | |
702 | if (!(packet->count)) | |
703 | return snprintf(buf, buf_len, "%s no ip", name); | |
7ea6856d | 704 | __fallthrough; |
3d498078 AH |
705 | case INTEL_PT_CYC: |
706 | case INTEL_PT_VMCS: | |
707 | case INTEL_PT_MTC: | |
708 | case INTEL_PT_MNT: | |
a4e92590 | 709 | case INTEL_PT_CBR: |
a4e92590 | 710 | case INTEL_PT_TSC: |
3d498078 AH |
711 | return snprintf(buf, buf_len, "%s 0x%llx", name, payload); |
712 | case INTEL_PT_TMA: | |
713 | return snprintf(buf, buf_len, "%s CTC 0x%x FC 0x%x", name, | |
714 | (unsigned)payload, packet->count); | |
a4e92590 AH |
715 | case INTEL_PT_MODE_EXEC: |
716 | return snprintf(buf, buf_len, "%s %lld", name, payload); | |
717 | case INTEL_PT_MODE_TSX: | |
718 | return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u", | |
719 | name, (unsigned)(payload >> 1) & 1, | |
720 | (unsigned)payload & 1); | |
721 | case INTEL_PT_PIP: | |
3d498078 AH |
722 | nr = packet->payload & NR_FLAG ? 1 : 0; |
723 | payload &= ~NR_FLAG; | |
724 | ret = snprintf(buf, buf_len, "%s 0x%llx (NR=%d)", | |
725 | name, payload, nr); | |
a4e92590 | 726 | return ret; |
a472e65f AH |
727 | case INTEL_PT_PTWRITE: |
728 | return snprintf(buf, buf_len, "%s 0x%llx IP:0", name, payload); | |
729 | case INTEL_PT_PTWRITE_IP: | |
730 | return snprintf(buf, buf_len, "%s 0x%llx IP:1", name, payload); | |
edff7809 | 731 | case INTEL_PT_BEP: |
a472e65f AH |
732 | case INTEL_PT_EXSTOP: |
733 | return snprintf(buf, buf_len, "%s IP:0", name); | |
edff7809 | 734 | case INTEL_PT_BEP_IP: |
a472e65f AH |
735 | case INTEL_PT_EXSTOP_IP: |
736 | return snprintf(buf, buf_len, "%s IP:1", name); | |
737 | case INTEL_PT_MWAIT: | |
738 | return snprintf(buf, buf_len, "%s 0x%llx Hints 0x%x Extensions 0x%x", | |
739 | name, payload, (unsigned int)(payload & 0xff), | |
740 | (unsigned int)((payload >> 32) & 0x3)); | |
741 | case INTEL_PT_PWRE: | |
742 | return snprintf(buf, buf_len, "%s 0x%llx HW:%u CState:%u Sub-CState:%u", | |
743 | name, payload, !!(payload & 0x80), | |
744 | (unsigned int)((payload >> 12) & 0xf), | |
745 | (unsigned int)((payload >> 8) & 0xf)); | |
746 | case INTEL_PT_PWRX: | |
747 | return snprintf(buf, buf_len, "%s 0x%llx Last CState:%u Deepest CState:%u Wake Reason 0x%x", | |
748 | name, payload, | |
749 | (unsigned int)((payload >> 4) & 0xf), | |
750 | (unsigned int)(payload & 0xf), | |
751 | (unsigned int)((payload >> 8) & 0xf)); | |
edff7809 AH |
752 | case INTEL_PT_BBP: |
753 | return snprintf(buf, buf_len, "%s SZ %s-byte Type 0x%llx", | |
754 | name, packet->count ? "4" : "8", payload); | |
755 | case INTEL_PT_BIP: | |
756 | return snprintf(buf, buf_len, "%s ID 0x%02x Value 0x%llx", | |
757 | name, packet->count, payload); | |
a4e92590 AH |
758 | default: |
759 | break; | |
760 | } | |
761 | return snprintf(buf, buf_len, "%s 0x%llx (%d)", | |
762 | name, payload, packet->count); | |
763 | } |