blob: 988c82c6652dfa17cc47bf9f91ac54442a006e9c [file] [log] [blame]
Adrian Huntera4e92592015-07-17 19:33:37 +03001/*
2 * intel_pt_pkt_decoder.c: Intel Processor Trace support
3 * Copyright (c) 2013-2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <endian.h>
19#include <byteswap.h>
20
21#include "intel-pt-pkt-decoder.h"
22
23#define BIT(n) (1 << (n))
24
25#define BIT63 ((uint64_t)1 << 63)
26
27#if __BYTE_ORDER == __BIG_ENDIAN
28#define le16_to_cpu bswap_16
29#define le32_to_cpu bswap_32
30#define le64_to_cpu bswap_64
31#define memcpy_le64(d, s, n) do { \
32 memcpy((d), (s), (n)); \
33 *(d) = le64_to_cpu(*(d)); \
34} while (0)
35#else
36#define le16_to_cpu
37#define le32_to_cpu
38#define le64_to_cpu
39#define memcpy_le64 memcpy
40#endif
41
42static const char * const packet_name[] = {
43 [INTEL_PT_BAD] = "Bad Packet!",
44 [INTEL_PT_PAD] = "PAD",
45 [INTEL_PT_TNT] = "TNT",
46 [INTEL_PT_TIP_PGD] = "TIP.PGD",
47 [INTEL_PT_TIP_PGE] = "TIP.PGE",
48 [INTEL_PT_TSC] = "TSC",
49 [INTEL_PT_MODE_EXEC] = "MODE.Exec",
50 [INTEL_PT_MODE_TSX] = "MODE.TSX",
51 [INTEL_PT_TIP] = "TIP",
52 [INTEL_PT_FUP] = "FUP",
53 [INTEL_PT_PSB] = "PSB",
54 [INTEL_PT_PSBEND] = "PSBEND",
55 [INTEL_PT_CBR] = "CBR",
56 [INTEL_PT_PIP] = "PIP",
57 [INTEL_PT_OVF] = "OVF",
58};
59
60const char *intel_pt_pkt_name(enum intel_pt_pkt_type type)
61{
62 return packet_name[type];
63}
64
65static int intel_pt_get_long_tnt(const unsigned char *buf, size_t len,
66 struct intel_pt_pkt *packet)
67{
68 uint64_t payload;
69 int count;
70
71 if (len < 8)
72 return INTEL_PT_NEED_MORE_BYTES;
73
74 payload = le64_to_cpu(*(uint64_t *)buf);
75
76 for (count = 47; count; count--) {
77 if (payload & BIT63)
78 break;
79 payload <<= 1;
80 }
81
82 packet->type = INTEL_PT_TNT;
83 packet->count = count;
84 packet->payload = payload << 1;
85 return 8;
86}
87
88static int intel_pt_get_pip(const unsigned char *buf, size_t len,
89 struct intel_pt_pkt *packet)
90{
91 uint64_t payload = 0;
92
93 if (len < 8)
94 return INTEL_PT_NEED_MORE_BYTES;
95
96 packet->type = INTEL_PT_PIP;
97 memcpy_le64(&payload, buf + 2, 6);
98 packet->payload = payload >> 1;
99
100 return 8;
101}
102
103static int intel_pt_get_cbr(const unsigned char *buf, size_t len,
104 struct intel_pt_pkt *packet)
105{
106 if (len < 4)
107 return INTEL_PT_NEED_MORE_BYTES;
108 packet->type = INTEL_PT_CBR;
109 packet->payload = buf[2];
110 return 4;
111}
112
113static int intel_pt_get_ovf(struct intel_pt_pkt *packet)
114{
115 packet->type = INTEL_PT_OVF;
116 return 2;
117}
118
119static int intel_pt_get_psb(const unsigned char *buf, size_t len,
120 struct intel_pt_pkt *packet)
121{
122 int i;
123
124 if (len < 16)
125 return INTEL_PT_NEED_MORE_BYTES;
126
127 for (i = 2; i < 16; i += 2) {
128 if (buf[i] != 2 || buf[i + 1] != 0x82)
129 return INTEL_PT_BAD_PACKET;
130 }
131
132 packet->type = INTEL_PT_PSB;
133 return 16;
134}
135
136static int intel_pt_get_psbend(struct intel_pt_pkt *packet)
137{
138 packet->type = INTEL_PT_PSBEND;
139 return 2;
140}
141
142static int intel_pt_get_pad(struct intel_pt_pkt *packet)
143{
144 packet->type = INTEL_PT_PAD;
145 return 1;
146}
147
148static int intel_pt_get_ext(const unsigned char *buf, size_t len,
149 struct intel_pt_pkt *packet)
150{
151 if (len < 2)
152 return INTEL_PT_NEED_MORE_BYTES;
153
154 switch (buf[1]) {
155 case 0xa3: /* Long TNT */
156 return intel_pt_get_long_tnt(buf, len, packet);
157 case 0x43: /* PIP */
158 return intel_pt_get_pip(buf, len, packet);
159 case 0x03: /* CBR */
160 return intel_pt_get_cbr(buf, len, packet);
161 case 0xf3: /* OVF */
162 return intel_pt_get_ovf(packet);
163 case 0x82: /* PSB */
164 return intel_pt_get_psb(buf, len, packet);
165 case 0x23: /* PSBEND */
166 return intel_pt_get_psbend(packet);
167 default:
168 return INTEL_PT_BAD_PACKET;
169 }
170}
171
172static int intel_pt_get_short_tnt(unsigned int byte,
173 struct intel_pt_pkt *packet)
174{
175 int count;
176
177 for (count = 6; count; count--) {
178 if (byte & BIT(7))
179 break;
180 byte <<= 1;
181 }
182
183 packet->type = INTEL_PT_TNT;
184 packet->count = count;
185 packet->payload = (uint64_t)byte << 57;
186
187 return 1;
188}
189
190static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
191 const unsigned char *buf, size_t len,
192 struct intel_pt_pkt *packet)
193{
194 switch (byte >> 5) {
195 case 0:
196 packet->count = 0;
197 break;
198 case 1:
199 if (len < 3)
200 return INTEL_PT_NEED_MORE_BYTES;
201 packet->count = 2;
202 packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
203 break;
204 case 2:
205 if (len < 5)
206 return INTEL_PT_NEED_MORE_BYTES;
207 packet->count = 4;
208 packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
209 break;
210 case 3:
211 case 6:
212 if (len < 7)
213 return INTEL_PT_NEED_MORE_BYTES;
214 packet->count = 6;
215 memcpy_le64(&packet->payload, buf + 1, 6);
216 break;
217 default:
218 return INTEL_PT_BAD_PACKET;
219 }
220
221 packet->type = type;
222
223 return packet->count + 1;
224}
225
226static int intel_pt_get_mode(const unsigned char *buf, size_t len,
227 struct intel_pt_pkt *packet)
228{
229 if (len < 2)
230 return INTEL_PT_NEED_MORE_BYTES;
231
232 switch (buf[1] >> 5) {
233 case 0:
234 packet->type = INTEL_PT_MODE_EXEC;
235 switch (buf[1] & 3) {
236 case 0:
237 packet->payload = 16;
238 break;
239 case 1:
240 packet->payload = 64;
241 break;
242 case 2:
243 packet->payload = 32;
244 break;
245 default:
246 return INTEL_PT_BAD_PACKET;
247 }
248 break;
249 case 1:
250 packet->type = INTEL_PT_MODE_TSX;
251 if ((buf[1] & 3) == 3)
252 return INTEL_PT_BAD_PACKET;
253 packet->payload = buf[1] & 3;
254 break;
255 default:
256 return INTEL_PT_BAD_PACKET;
257 }
258
259 return 2;
260}
261
262static int intel_pt_get_tsc(const unsigned char *buf, size_t len,
263 struct intel_pt_pkt *packet)
264{
265 if (len < 8)
266 return INTEL_PT_NEED_MORE_BYTES;
267 packet->type = INTEL_PT_TSC;
268 memcpy_le64(&packet->payload, buf + 1, 7);
269 return 8;
270}
271
272static int intel_pt_do_get_packet(const unsigned char *buf, size_t len,
273 struct intel_pt_pkt *packet)
274{
275 unsigned int byte;
276
277 memset(packet, 0, sizeof(struct intel_pt_pkt));
278
279 if (!len)
280 return INTEL_PT_NEED_MORE_BYTES;
281
282 byte = buf[0];
283 if (!(byte & BIT(0))) {
284 if (byte == 0)
285 return intel_pt_get_pad(packet);
286 if (byte == 2)
287 return intel_pt_get_ext(buf, len, packet);
288 return intel_pt_get_short_tnt(byte, packet);
289 }
290
291 switch (byte & 0x1f) {
292 case 0x0D:
293 return intel_pt_get_ip(INTEL_PT_TIP, byte, buf, len, packet);
294 case 0x11:
295 return intel_pt_get_ip(INTEL_PT_TIP_PGE, byte, buf, len,
296 packet);
297 case 0x01:
298 return intel_pt_get_ip(INTEL_PT_TIP_PGD, byte, buf, len,
299 packet);
300 case 0x1D:
301 return intel_pt_get_ip(INTEL_PT_FUP, byte, buf, len, packet);
302 case 0x19:
303 switch (byte) {
304 case 0x99:
305 return intel_pt_get_mode(buf, len, packet);
306 case 0x19:
307 return intel_pt_get_tsc(buf, len, packet);
308 default:
309 return INTEL_PT_BAD_PACKET;
310 }
311 default:
312 return INTEL_PT_BAD_PACKET;
313 }
314}
315
316int intel_pt_get_packet(const unsigned char *buf, size_t len,
317 struct intel_pt_pkt *packet)
318{
319 int ret;
320
321 ret = intel_pt_do_get_packet(buf, len, packet);
322 if (ret > 0) {
323 while (ret < 8 && len > (size_t)ret && !buf[ret])
324 ret += 1;
325 }
326 return ret;
327}
328
329int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
330 size_t buf_len)
331{
332 int ret, i;
333 unsigned long long payload = packet->payload;
334 const char *name = intel_pt_pkt_name(packet->type);
335
336 switch (packet->type) {
337 case INTEL_PT_BAD:
338 case INTEL_PT_PAD:
339 case INTEL_PT_PSB:
340 case INTEL_PT_PSBEND:
341 case INTEL_PT_OVF:
342 return snprintf(buf, buf_len, "%s", name);
343 case INTEL_PT_TNT: {
344 size_t blen = buf_len;
345
346 ret = snprintf(buf, blen, "%s ", name);
347 if (ret < 0)
348 return ret;
349 buf += ret;
350 blen -= ret;
351 for (i = 0; i < packet->count; i++) {
352 if (payload & BIT63)
353 ret = snprintf(buf, blen, "T");
354 else
355 ret = snprintf(buf, blen, "N");
356 if (ret < 0)
357 return ret;
358 buf += ret;
359 blen -= ret;
360 payload <<= 1;
361 }
362 ret = snprintf(buf, blen, " (%d)", packet->count);
363 if (ret < 0)
364 return ret;
365 blen -= ret;
366 return buf_len - blen;
367 }
368 case INTEL_PT_TIP_PGD:
369 case INTEL_PT_TIP_PGE:
370 case INTEL_PT_TIP:
371 case INTEL_PT_FUP:
372 if (!(packet->count))
373 return snprintf(buf, buf_len, "%s no ip", name);
374 case INTEL_PT_CBR:
375 return snprintf(buf, buf_len, "%s 0x%llx", name, payload);
376 case INTEL_PT_TSC:
377 if (packet->count)
378 return snprintf(buf, buf_len,
379 "%s 0x%llx CTC 0x%x FC 0x%x",
380 name, payload, packet->count & 0xffff,
381 (packet->count >> 16) & 0x1ff);
382 else
383 return snprintf(buf, buf_len, "%s 0x%llx",
384 name, payload);
385 case INTEL_PT_MODE_EXEC:
386 return snprintf(buf, buf_len, "%s %lld", name, payload);
387 case INTEL_PT_MODE_TSX:
388 return snprintf(buf, buf_len, "%s TXAbort:%u InTX:%u",
389 name, (unsigned)(payload >> 1) & 1,
390 (unsigned)payload & 1);
391 case INTEL_PT_PIP:
392 ret = snprintf(buf, buf_len, "%s 0x%llx",
393 name, payload);
394 return ret;
395 default:
396 break;
397 }
398 return snprintf(buf, buf_len, "%s 0x%llx (%d)",
399 name, payload, packet->count);
400}