2 * Copyright (c) 2013-2018, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include "pt_packet.h"
30 #include "pt_opcodes.h"
37 static uint64_t pt_pkt_read_value(const uint8_t *pos, int size)
42 for (val = 0, idx = 0; idx < size; ++idx) {
43 uint64_t byte = *pos++;
52 int pt_pkt_read_unknown(struct pt_packet *packet, const uint8_t *pos,
53 const struct pt_config *config)
55 int (*decode)(struct pt_packet_unknown *, const struct pt_config *,
56 const uint8_t *, void *);
59 if (!packet || !pos || !config)
62 decode = config->decode.callback;
66 /* Fill in some default values. */
67 packet->payload.unknown.packet = pos;
68 packet->payload.unknown.priv = NULL;
70 /* We accept a size of zero to allow the callback to modify the
71 * trace buffer and resume normal decoding.
73 size = (*decode)(&packet->payload.unknown, config, pos,
74 config->decode.context);
81 packet->type = ppt_unknown;
82 packet->size = (uint8_t) size;
84 if (config->end < pos + size)
90 int pt_pkt_read_psb(const uint8_t *pos, const struct pt_config *config)
97 if (config->end < pos + ptps_psb)
102 for (count = 0; count < pt_psb_repeat_count; ++count) {
103 if (*pos++ != pt_psb_hi)
104 return -pte_bad_packet;
105 if (*pos++ != pt_psb_lo)
106 return -pte_bad_packet;
112 static int pt_pkt_ip_size(enum pt_ip_compression ipc)
115 case pt_ipc_suppressed:
118 case pt_ipc_update_16:
121 case pt_ipc_update_32:
124 case pt_ipc_update_48:
132 return -pte_bad_packet;
135 int pt_pkt_read_ip(struct pt_packet_ip *packet, const uint8_t *pos,
136 const struct pt_config *config)
142 if (!packet || !pos || !config)
143 return -pte_internal;
145 ipc = (*pos++ >> pt_opm_ipc_shr) & pt_opm_ipc_shr_mask;
148 ipsize = pt_pkt_ip_size((enum pt_ip_compression) ipc);
152 if (config->end < pos + ipsize)
156 ip = pt_pkt_read_value(pos, ipsize);
158 packet->ipc = (enum pt_ip_compression) ipc;
164 static uint8_t pt_pkt_tnt_bit_size(uint64_t payload)
168 /* The payload bit-size is the bit-index of the payload's stop-bit,
169 * which itself is not part of the payload proper.
171 for (size = 0; ; size += 1) {
180 static int pt_pkt_read_tnt(struct pt_packet_tnt *packet, uint64_t payload)
185 return -pte_internal;
187 bit_size = pt_pkt_tnt_bit_size(payload);
189 return -pte_bad_packet;
191 /* Remove the stop bit from the payload. */
192 payload &= ~(1ull << bit_size);
194 packet->payload = payload;
195 packet->bit_size = bit_size;
200 int pt_pkt_read_tnt_8(struct pt_packet_tnt *packet, const uint8_t *pos,
201 const struct pt_config *config)
208 return -pte_internal;
210 errcode = pt_pkt_read_tnt(packet, pos[0] >> pt_opm_tnt_8_shr);
217 int pt_pkt_read_tnt_64(struct pt_packet_tnt *packet, const uint8_t *pos,
218 const struct pt_config *config)
224 return -pte_internal;
226 if (config->end < pos + ptps_tnt_64)
229 payload = pt_pkt_read_value(pos + pt_opcs_tnt_64, pt_pl_tnt_64_size);
231 errcode = pt_pkt_read_tnt(packet, payload);
238 int pt_pkt_read_pip(struct pt_packet_pip *packet, const uint8_t *pos,
239 const struct pt_config *config)
243 if (!packet || !pos || !config)
244 return -pte_internal;
246 if (config->end < pos + ptps_pip)
249 /* Read the payload. */
250 payload = pt_pkt_read_value(pos + pt_opcs_pip, pt_pl_pip_size);
252 /* Extract the non-root information from the payload. */
253 packet->nr = payload & pt_pl_pip_nr;
255 /* Create the cr3 value. */
256 payload >>= pt_pl_pip_shr;
257 payload <<= pt_pl_pip_shl;
258 packet->cr3 = payload;
263 static int pt_pkt_read_mode_exec(struct pt_packet_mode_exec *packet,
267 return -pte_internal;
269 packet->csl = (mode & pt_mob_exec_csl) != 0;
270 packet->csd = (mode & pt_mob_exec_csd) != 0;
275 static int pt_pkt_read_mode_tsx(struct pt_packet_mode_tsx *packet,
279 return -pte_internal;
281 packet->intx = (mode & pt_mob_tsx_intx) != 0;
282 packet->abrt = (mode & pt_mob_tsx_abrt) != 0;
287 int pt_pkt_read_mode(struct pt_packet_mode *packet, const uint8_t *pos,
288 const struct pt_config *config)
290 uint8_t payload, mode, leaf;
292 if (!packet || !pos || !config)
293 return -pte_internal;
295 if (config->end < pos + ptps_mode)
298 payload = pos[pt_opcs_mode];
299 leaf = payload & pt_mom_leaf;
300 mode = payload & pt_mom_bits;
302 packet->leaf = (enum pt_mode_leaf) leaf;
305 return -pte_bad_packet;
308 return pt_pkt_read_mode_exec(&packet->bits.exec, mode);
311 return pt_pkt_read_mode_tsx(&packet->bits.tsx, mode);
315 int pt_pkt_read_tsc(struct pt_packet_tsc *packet, const uint8_t *pos,
316 const struct pt_config *config)
318 if (!packet || !pos || !config)
319 return -pte_internal;
321 if (config->end < pos + ptps_tsc)
324 packet->tsc = pt_pkt_read_value(pos + pt_opcs_tsc, pt_pl_tsc_size);
329 int pt_pkt_read_cbr(struct pt_packet_cbr *packet, const uint8_t *pos,
330 const struct pt_config *config)
332 if (!packet || !pos || !config)
333 return -pte_internal;
335 if (config->end < pos + ptps_cbr)
338 packet->ratio = pos[2];
343 int pt_pkt_read_tma(struct pt_packet_tma *packet, const uint8_t *pos,
344 const struct pt_config *config)
348 if (!packet || !pos || !config)
349 return -pte_internal;
351 if (config->end < pos + ptps_tma)
354 ctc = pos[pt_pl_tma_ctc_0];
355 ctc |= pos[pt_pl_tma_ctc_1] << 8;
357 fc = pos[pt_pl_tma_fc_0];
358 fc |= pos[pt_pl_tma_fc_1] << 8;
360 if (fc & ~pt_pl_tma_fc_mask)
361 return -pte_bad_packet;
369 int pt_pkt_read_mtc(struct pt_packet_mtc *packet, const uint8_t *pos,
370 const struct pt_config *config)
372 if (!packet || !pos || !config)
373 return -pte_internal;
375 if (config->end < pos + ptps_mtc)
378 packet->ctc = pos[pt_opcs_mtc];
383 int pt_pkt_read_cyc(struct pt_packet_cyc *packet, const uint8_t *pos,
384 const struct pt_config *config)
386 const uint8_t *begin, *end;
388 uint8_t cyc, ext, shl;
390 if (!packet || !pos || !config)
391 return -pte_internal;
396 /* The first byte contains the opcode and part of the payload.
397 * We already checked that this first byte is within bounds.
401 ext = cyc & pt_opm_cyc_ext;
402 cyc >>= pt_opm_cyc_shr;
405 shl = (8 - pt_opm_cyc_shr);
414 ext = bits & pt_opm_cycx_ext;
416 bits >>= pt_opm_cycx_shr;
419 shl += (8 - pt_opm_cycx_shr);
420 if (sizeof(value) * 8 < shl)
421 return -pte_bad_packet;
426 packet->value = value;
428 return (int) (pos - begin);
431 int pt_pkt_read_vmcs(struct pt_packet_vmcs *packet, const uint8_t *pos,
432 const struct pt_config *config)
436 if (!packet || !pos || !config)
437 return -pte_internal;
439 if (config->end < pos + ptps_vmcs)
442 payload = pt_pkt_read_value(pos + pt_opcs_vmcs, pt_pl_vmcs_size);
444 packet->base = payload << pt_pl_vmcs_shl;
449 int pt_pkt_read_mnt(struct pt_packet_mnt *packet, const uint8_t *pos,
450 const struct pt_config *config)
452 if (!packet || !pos || !config)
453 return -pte_internal;
455 if (config->end < pos + ptps_mnt)
458 packet->payload = pt_pkt_read_value(pos + pt_opcs_mnt, pt_pl_mnt_size);
463 int pt_pkt_read_exstop(struct pt_packet_exstop *packet, const uint8_t *pos,
464 const struct pt_config *config)
466 if (!packet || !pos || !config)
467 return -pte_internal;
469 if (config->end < pos + ptps_exstop)
472 packet->ip = pos[1] & pt_pl_exstop_ip_mask ? 1 : 0;
477 int pt_pkt_read_mwait(struct pt_packet_mwait *packet, const uint8_t *pos,
478 const struct pt_config *config)
480 if (!packet || !pos || !config)
481 return -pte_internal;
483 if (config->end < pos + ptps_mwait)
486 packet->hints = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait,
487 pt_pl_mwait_hints_size);
488 packet->ext = (uint32_t) pt_pkt_read_value(pos + pt_opcs_mwait +
489 pt_pl_mwait_hints_size,
490 pt_pl_mwait_ext_size);
494 int pt_pkt_read_pwre(struct pt_packet_pwre *packet, const uint8_t *pos,
495 const struct pt_config *config)
499 if (!packet || !pos || !config)
500 return -pte_internal;
502 if (config->end < pos + ptps_pwre)
505 payload = pt_pkt_read_value(pos + pt_opcs_pwre, pt_pl_pwre_size);
507 memset(packet, 0, sizeof(*packet));
508 packet->state = (uint8_t) ((payload & pt_pl_pwre_state_mask) >>
509 pt_pl_pwre_state_shr);
510 packet->sub_state = (uint8_t) ((payload & pt_pl_pwre_sub_state_mask) >>
511 pt_pl_pwre_sub_state_shr);
512 if (payload & pt_pl_pwre_hw_mask)
518 int pt_pkt_read_pwrx(struct pt_packet_pwrx *packet, const uint8_t *pos,
519 const struct pt_config *config)
523 if (!packet || !pos || !config)
524 return -pte_internal;
526 if (config->end < pos + ptps_pwrx)
529 payload = pt_pkt_read_value(pos + pt_opcs_pwrx, pt_pl_pwrx_size);
531 memset(packet, 0, sizeof(*packet));
532 packet->last = (uint8_t) ((payload & pt_pl_pwrx_last_mask) >>
533 pt_pl_pwrx_last_shr);
534 packet->deepest = (uint8_t) ((payload & pt_pl_pwrx_deepest_mask) >>
535 pt_pl_pwrx_deepest_shr);
536 if (payload & pt_pl_pwrx_wr_int)
537 packet->interrupt = 1;
538 if (payload & pt_pl_pwrx_wr_store)
540 if (payload & pt_pl_pwrx_wr_hw)
541 packet->autonomous = 1;
546 int pt_pkt_read_ptw(struct pt_packet_ptw *packet, const uint8_t *pos,
547 const struct pt_config *config)
552 if (!packet || !pos || !config)
553 return -pte_internal;
555 /* Skip the ext opcode. */
559 plc = (opc >> pt_opm_ptw_pb_shr) & pt_opm_ptw_pb_shr_mask;
561 size = pt_ptw_size(plc);
565 if (config->end < pos + size)
568 packet->payload = pt_pkt_read_value(pos, size);
570 packet->ip = opc & pt_opm_ptw_ip ? 1 : 0;
572 return pt_opcs_ptw + size;