|
@@ -123,8 +123,6 @@ struct intel_pt_decoder {
|
|
|
bool have_calc_cyc_to_tsc;
|
|
|
int exec_mode;
|
|
|
unsigned int insn_bytes;
|
|
|
- uint64_t sign_bit;
|
|
|
- uint64_t sign_bits;
|
|
|
uint64_t period;
|
|
|
enum intel_pt_period_type period_type;
|
|
|
uint64_t tot_insn_cnt;
|
|
@@ -191,9 +189,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
|
decoder->data = params->data;
|
|
|
decoder->return_compression = params->return_compression;
|
|
|
|
|
|
- decoder->sign_bit = (uint64_t)1 << 47;
|
|
|
- decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
|
|
|
-
|
|
|
decoder->period = params->period;
|
|
|
decoder->period_type = params->period_type;
|
|
|
|
|
@@ -362,21 +357,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
|
|
|
- const struct intel_pt_pkt *packet,
|
|
|
+static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
|
|
|
uint64_t last_ip)
|
|
|
{
|
|
|
uint64_t ip;
|
|
|
|
|
|
switch (packet->count) {
|
|
|
- case 2:
|
|
|
+ case 1:
|
|
|
ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
|
|
|
packet->payload;
|
|
|
break;
|
|
|
- case 4:
|
|
|
+ case 2:
|
|
|
ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
|
|
|
packet->payload;
|
|
|
break;
|
|
|
+ case 3:
|
|
|
+ ip = packet->payload;
|
|
|
+ /* Sign-extend 6-byte ip */
|
|
|
+ if (ip & (uint64_t)0x800000000000ULL)
|
|
|
+ ip |= (uint64_t)0xffff000000000000ULL;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
|
|
|
+ packet->payload;
|
|
|
+ break;
|
|
|
case 6:
|
|
|
ip = packet->payload;
|
|
|
break;
|
|
@@ -384,16 +388,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (ip & decoder->sign_bit)
|
|
|
- return ip | decoder->sign_bits;
|
|
|
-
|
|
|
return ip;
|
|
|
}
|
|
|
|
|
|
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
|
|
|
{
|
|
|
- decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet,
|
|
|
- decoder->last_ip);
|
|
|
+ decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
|
|
|
}
|
|
|
|
|
|
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
|
|
@@ -1657,6 +1657,12 @@ next:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
|
|
|
+{
|
|
|
+ return decoder->last_ip || decoder->packet.count == 0 ||
|
|
|
+ decoder->packet.count == 3 || decoder->packet.count == 6;
|
|
|
+}
|
|
|
+
|
|
|
/* Walk PSB+ packets to get in sync. */
|
|
|
static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
|
{
|
|
@@ -1677,8 +1683,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
case INTEL_PT_FUP:
|
|
|
decoder->pge = true;
|
|
|
- if (decoder->last_ip || decoder->packet.count == 6 ||
|
|
|
- decoder->packet.count == 0) {
|
|
|
+ if (intel_pt_have_ip(decoder)) {
|
|
|
uint64_t current_ip = decoder->ip;
|
|
|
|
|
|
intel_pt_set_ip(decoder);
|
|
@@ -1767,8 +1772,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
|
case INTEL_PT_TIP_PGE:
|
|
|
case INTEL_PT_TIP:
|
|
|
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
|
|
|
- if (decoder->last_ip || decoder->packet.count == 6 ||
|
|
|
- decoder->packet.count == 0)
|
|
|
+ if (intel_pt_have_ip(decoder))
|
|
|
intel_pt_set_ip(decoder);
|
|
|
if (decoder->ip)
|
|
|
return 0;
|
|
@@ -1776,9 +1780,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
case INTEL_PT_FUP:
|
|
|
if (decoder->overflow) {
|
|
|
- if (decoder->last_ip ||
|
|
|
- decoder->packet.count == 6 ||
|
|
|
- decoder->packet.count == 0)
|
|
|
+ if (intel_pt_have_ip(decoder))
|
|
|
intel_pt_set_ip(decoder);
|
|
|
if (decoder->ip)
|
|
|
return 0;
|