Skip to content

Commit 01ac8af

Browse files
ahunter6gregkh
authored andcommitted
perf intel-pt: Fix ip compression
commit e1717e0 upstream. The June 2015 Intel SDM introduced IP Compression types 4 and 6. Refer to section 36.4.2.2 Target IP (TIP) Packet - IP Compression. Existing Intel PT packet decoder did not support type 4, and got type 6 wrong. Because type 3 and type 4 have the same number of bytes, the packet 'count' has been changed from being the number of ip bytes to being the type code. That allows the Intel PT decoder to correctly decide whether to sign-extend or use the last ip. However that also meant the code had to be adjusted in a number of places. Currently hardware is not using the new compression types, so this fix has no effect on existing hardware. Signed-off-by: Adrian Hunter <[email protected]> Cc: Jiri Olsa <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8255d26 commit 01ac8af

File tree

2 files changed

+40
-28
lines changed

2 files changed

+40
-28
lines changed

tools/perf/util/intel-pt-decoder/intel-pt-decoder.c

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ struct intel_pt_decoder {
145145
bool have_calc_cyc_to_tsc;
146146
int exec_mode;
147147
unsigned int insn_bytes;
148-
uint64_t sign_bit;
149-
uint64_t sign_bits;
150148
uint64_t period;
151149
enum intel_pt_period_type period_type;
152150
uint64_t tot_insn_cnt;
@@ -214,9 +212,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
214212
decoder->data = params->data;
215213
decoder->return_compression = params->return_compression;
216214

217-
decoder->sign_bit = (uint64_t)1 << 47;
218-
decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
219-
220215
decoder->period = params->period;
221216
decoder->period_type = params->period_type;
222217

@@ -385,38 +380,43 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
385380
return 0;
386381
}
387382

388-
static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
389-
const struct intel_pt_pkt *packet,
383+
static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
390384
uint64_t last_ip)
391385
{
392386
uint64_t ip;
393387

394388
switch (packet->count) {
395-
case 2:
389+
case 1:
396390
ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
397391
packet->payload;
398392
break;
399-
case 4:
393+
case 2:
400394
ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
401395
packet->payload;
402396
break;
397+
case 3:
398+
ip = packet->payload;
399+
/* Sign-extend 6-byte ip */
400+
if (ip & (uint64_t)0x800000000000ULL)
401+
ip |= (uint64_t)0xffff000000000000ULL;
402+
break;
403+
case 4:
404+
ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
405+
packet->payload;
406+
break;
403407
case 6:
404408
ip = packet->payload;
405409
break;
406410
default:
407411
return 0;
408412
}
409413

410-
if (ip & decoder->sign_bit)
411-
return ip | decoder->sign_bits;
412-
413414
return ip;
414415
}
415416

416417
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
417418
{
418-
decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet,
419-
decoder->last_ip);
419+
decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
420420
}
421421

422422
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -1718,6 +1718,12 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
17181718
}
17191719
}
17201720

1721+
static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
1722+
{
1723+
return decoder->last_ip || decoder->packet.count == 0 ||
1724+
decoder->packet.count == 3 || decoder->packet.count == 6;
1725+
}
1726+
17211727
/* Walk PSB+ packets to get in sync. */
17221728
static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
17231729
{
@@ -1739,8 +1745,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
17391745

17401746
case INTEL_PT_FUP:
17411747
decoder->pge = true;
1742-
if (decoder->last_ip || decoder->packet.count == 6 ||
1743-
decoder->packet.count == 0) {
1748+
if (intel_pt_have_ip(decoder)) {
17441749
uint64_t current_ip = decoder->ip;
17451750

17461751
intel_pt_set_ip(decoder);
@@ -1832,18 +1837,15 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
18321837
case INTEL_PT_TIP_PGE:
18331838
case INTEL_PT_TIP:
18341839
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
1835-
if (decoder->last_ip || decoder->packet.count == 6 ||
1836-
decoder->packet.count == 0)
1840+
if (intel_pt_have_ip(decoder))
18371841
intel_pt_set_ip(decoder);
18381842
if (decoder->ip)
18391843
return 0;
18401844
break;
18411845

18421846
case INTEL_PT_FUP:
18431847
if (decoder->overflow) {
1844-
if (decoder->last_ip ||
1845-
decoder->packet.count == 6 ||
1846-
decoder->packet.count == 0)
1848+
if (intel_pt_have_ip(decoder))
18471849
intel_pt_set_ip(decoder);
18481850
if (decoder->ip)
18491851
return 0;

tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,36 +293,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
293293
const unsigned char *buf, size_t len,
294294
struct intel_pt_pkt *packet)
295295
{
296-
switch (byte >> 5) {
296+
int ip_len;
297+
298+
packet->count = byte >> 5;
299+
300+
switch (packet->count) {
297301
case 0:
298-
packet->count = 0;
302+
ip_len = 0;
299303
break;
300304
case 1:
301305
if (len < 3)
302306
return INTEL_PT_NEED_MORE_BYTES;
303-
packet->count = 2;
307+
ip_len = 2;
304308
packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
305309
break;
306310
case 2:
307311
if (len < 5)
308312
return INTEL_PT_NEED_MORE_BYTES;
309-
packet->count = 4;
313+
ip_len = 4;
310314
packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
311315
break;
312316
case 3:
313-
case 6:
317+
case 4:
314318
if (len < 7)
315319
return INTEL_PT_NEED_MORE_BYTES;
316-
packet->count = 6;
320+
ip_len = 6;
317321
memcpy_le64(&packet->payload, buf + 1, 6);
318322
break;
323+
case 6:
324+
if (len < 9)
325+
return INTEL_PT_NEED_MORE_BYTES;
326+
ip_len = 8;
327+
packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
328+
break;
319329
default:
320330
return INTEL_PT_BAD_PACKET;
321331
}
322332

323333
packet->type = type;
324334

325-
return packet->count + 1;
335+
return ip_len + 1;
326336
}
327337

328338
static int intel_pt_get_mode(const unsigned char *buf, size_t len,

0 commit comments

Comments
 (0)