2 * Copyright (c) 2014-2019, 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_encoder.h"
30 #include "pt_config.h"
31 #include "pt_opcodes.h"
37 int pt_encoder_init(struct pt_encoder *encoder, const struct pt_config *config)
44 memset(encoder, 0, sizeof(*encoder));
46 errcode = pt_config_from_user(&encoder->config, config);
50 encoder->pos = encoder->config.begin;
55 void pt_encoder_fini(struct pt_encoder *encoder)
62 struct pt_encoder *pt_alloc_encoder(const struct pt_config *config)
64 struct pt_encoder *encoder;
67 encoder = malloc(sizeof(*encoder));
71 errcode = pt_encoder_init(encoder, config);
80 void pt_free_encoder(struct pt_encoder *encoder)
82 pt_encoder_fini(encoder);
86 int pt_enc_sync_set(struct pt_encoder *encoder, uint64_t offset)
88 uint8_t *begin, *end, *pos;
93 begin = encoder->config.begin;
94 end = encoder->config.end;
97 if (end < pos || pos < begin)
104 int pt_enc_get_offset(const struct pt_encoder *encoder, uint64_t *offset)
106 const uint8_t *raw, *begin;
108 if (!encoder || !offset)
111 /* The encoder is synchronized at all times. */
114 return -pte_internal;
116 begin = encoder->config.begin;
118 return -pte_internal;
120 *offset = (uint64_t) (int64_t) (raw - begin);
124 const struct pt_config *pt_enc_get_config(const struct pt_encoder *encoder)
129 return &encoder->config;
132 /* Check the remaining space.
134 * Returns zero if there are at least \@size bytes of free space available in
135 * \@encoder's Intel PT buffer.
137 * Returns -pte_eos if not enough space is available.
138 * Returns -pte_internal if \@encoder is NULL.
139 * Returns -pte_internal if \@encoder is not synchronized.
141 static int pt_reserve(const struct pt_encoder *encoder, unsigned int size)
143 const uint8_t *begin, *end, *pos;
146 return -pte_internal;
148 /* The encoder is synchronized at all times. */
151 return -pte_internal;
153 begin = encoder->config.begin;
154 end = encoder->config.end;
157 if (pos < begin || end < pos)
163 /* Return the size of an IP payload based on its IP compression.
165 * Returns -pte_bad_packet if \@ipc is not a valid IP compression.
167 static int pt_ipc_size(enum pt_ip_compression ipc)
170 case pt_ipc_suppressed:
173 case pt_ipc_update_16:
174 return pt_pl_ip_upd16_size;
176 case pt_ipc_update_32:
177 return pt_pl_ip_upd32_size;
179 case pt_ipc_update_48:
180 return pt_pl_ip_upd48_size;
183 return pt_pl_ip_sext48_size;
186 return pt_pl_ip_full_size;
192 /* Encode an integer value.
194 * Writes the \@size least signifficant bytes of \@value starting from \@pos.
196 * The caller needs to ensure that there is enough space available.
198 * Returns the updated position.
200 static uint8_t *pt_encode_int(uint8_t *pos, uint64_t val, int size)
202 for (; size; --size, val >>= 8)
203 *pos++ = (uint8_t) val;
208 /* Encode an IP packet.
210 * Write an IP packet with opcode \@opc and payload from \@packet if there is
211 * enough space in \@encoder's Intel PT buffer.
213 * Returns the number of bytes written on success.
215 * Returns -pte_eos if there is not enough space.
216 * Returns -pte_internal if \@encoder or \@packet is NULL.
217 * Returns -pte_invalid if \@packet.ipc is not valid.
219 static int pt_encode_ip(struct pt_encoder *encoder, enum pt_opcode op,
220 const struct pt_packet_ip *packet)
226 if (!encoder || !packet)
229 size = pt_ipc_size(packet->ipc);
233 errcode = pt_reserve(encoder,
234 /* opc size = */ 1u + (unsigned int) size);
238 /* We already checked the ipc in pt_ipc_size(). */
239 ipc = (uint8_t) (packet->ipc << pt_opm_ipc_shr);
245 encoder->pos = pt_encode_int(pos, packet->ip, size);
246 return /* opc size = */ 1 + size;
249 int pt_enc_next(struct pt_encoder *encoder, const struct pt_packet *packet)
251 uint8_t *pos, *begin;
254 if (!encoder || !packet)
257 pos = begin = encoder->pos;
258 switch (packet->type) {
260 errcode = pt_reserve(encoder, ptps_pad);
267 return (int) (pos - begin);
272 errcode = pt_reserve(encoder, ptps_psb);
276 psb = ((uint64_t) pt_psb_hilo << 48 |
277 (uint64_t) pt_psb_hilo << 32 |
278 (uint64_t) pt_psb_hilo << 16 |
279 (uint64_t) pt_psb_hilo);
281 pos = pt_encode_int(pos, psb, 8);
282 pos = pt_encode_int(pos, psb, 8);
285 return (int) (pos - begin);
289 errcode = pt_reserve(encoder, ptps_psbend);
294 *pos++ = pt_ext_psbend;
297 return (int) (pos - begin);
300 errcode = pt_reserve(encoder, ptps_ovf);
308 return (int) (pos - begin);
311 return pt_encode_ip(encoder, pt_opc_fup, &packet->payload.ip);
314 return pt_encode_ip(encoder, pt_opc_tip, &packet->payload.ip);
317 return pt_encode_ip(encoder, pt_opc_tip_pge,
318 &packet->payload.ip);
321 return pt_encode_ip(encoder, pt_opc_tip_pgd,
322 &packet->payload.ip);
327 if (packet->payload.tnt.bit_size >= 7)
328 return -pte_bad_packet;
330 errcode = pt_reserve(encoder, ptps_tnt_8);
334 stop = packet->payload.tnt.bit_size + pt_opm_tnt_8_shr;
336 (packet->payload.tnt.payload << pt_opm_tnt_8_shr);
338 *pos++ = (uint8_t) (opc | (1u << stop));
341 return (int) (pos - begin);
347 errcode = pt_reserve(encoder, ptps_tnt_64);
351 if (packet->payload.tnt.bit_size >= pt_pl_tnt_64_bits)
354 stop = 1ull << packet->payload.tnt.bit_size;
355 tnt = packet->payload.tnt.payload;
357 if (tnt & ~(stop - 1))
361 *pos++ = pt_ext_tnt_64;
362 pos = pt_encode_int(pos, tnt | stop, pt_pl_tnt_64_size);
365 return (int) (pos - begin);
371 errcode = pt_reserve(encoder, ptps_mode);
375 switch (packet->payload.mode.leaf) {
377 return -pte_bad_packet;
382 if (packet->payload.mode.bits.exec.csl)
383 mode |= pt_mob_exec_csl;
385 if (packet->payload.mode.bits.exec.csd)
386 mode |= pt_mob_exec_csd;
392 if (packet->payload.mode.bits.tsx.intx)
393 mode |= pt_mob_tsx_intx;
395 if (packet->payload.mode.bits.tsx.abrt)
396 mode |= pt_mob_tsx_abrt;
400 *pos++ = pt_opc_mode;
404 return (int) (pos - begin);
410 errcode = pt_reserve(encoder, ptps_pip);
414 cr3 = packet->payload.pip.cr3;
415 cr3 >>= pt_pl_pip_shl;
416 cr3 <<= pt_pl_pip_shr;
418 if (packet->payload.pip.nr)
419 cr3 |= (uint64_t) pt_pl_pip_nr;
423 pos = pt_encode_int(pos, cr3, pt_pl_pip_size);
426 return (int) (pos - begin);
430 errcode = pt_reserve(encoder, ptps_tsc);
435 pos = pt_encode_int(pos, packet->payload.tsc.tsc,
439 return (int) (pos - begin);
442 errcode = pt_reserve(encoder, ptps_cbr);
448 *pos++ = packet->payload.cbr.ratio;
452 return (int) (pos - begin);
457 errcode = pt_reserve(encoder, ptps_tma);
461 ctc = packet->payload.tma.ctc;
462 fc = packet->payload.tma.fc;
464 if (fc & ~pt_pl_tma_fc_mask)
465 return -pte_bad_packet;
469 pos = pt_encode_int(pos, ctc, pt_pl_tma_ctc_size);
471 pos = pt_encode_int(pos, fc, pt_pl_tma_fc_size);
474 return (int) (pos - begin);
478 errcode = pt_reserve(encoder, ptps_mtc);
483 *pos++ = packet->payload.mtc.ctc;
486 return (int) (pos - begin);
489 uint8_t byte[pt_pl_cyc_max_size], index, end;
492 ctc = (uint8_t) packet->payload.cyc.value;
493 ctc <<= pt_opm_cyc_shr;
495 byte[0] = pt_opc_cyc;
496 byte[0] |= (uint8_t) ctc;
498 ctc = packet->payload.cyc.value;
499 ctc >>= (8 - pt_opm_cyc_shr);
501 byte[0] |= pt_opm_cyc_ext;
503 for (end = 1; ctc; ++end) {
504 /* Check if the CYC payload is too big. */
505 if (pt_pl_cyc_max_size <= end)
506 return -pte_bad_packet;
508 ctc <<= pt_opm_cycx_shr;
510 byte[end] = (uint8_t) ctc;
514 byte[end] |= pt_opm_cycx_ext;
517 errcode = pt_reserve(encoder, end);
521 for (index = 0; index < end; ++index)
522 *pos++ = byte[index];
525 return (int) (pos - begin);
529 errcode = pt_reserve(encoder, ptps_stop);
534 *pos++ = pt_ext_stop;
537 return (int) (pos - begin);
540 errcode = pt_reserve(encoder, ptps_vmcs);
545 *pos++ = pt_ext_vmcs;
546 pos = pt_encode_int(pos,
547 packet->payload.vmcs.base >> pt_pl_vmcs_shl,
551 return (int) (pos - begin);
554 errcode = pt_reserve(encoder, ptps_mnt);
559 *pos++ = pt_ext_ext2;
560 *pos++ = pt_ext2_mnt;
561 pos = pt_encode_int(pos, packet->payload.mnt.payload,
565 return (int) (pos - begin);
570 errcode = pt_reserve(encoder, ptps_exstop);
574 ext = packet->payload.exstop.ip ?
575 pt_ext_exstop_ip : pt_ext_exstop;
581 return (int) (pos - begin);
585 errcode = pt_reserve(encoder, ptps_mwait);
590 *pos++ = pt_ext_mwait;
591 pos = pt_encode_int(pos, packet->payload.mwait.hints,
592 pt_pl_mwait_hints_size);
593 pos = pt_encode_int(pos, packet->payload.mwait.ext,
594 pt_pl_mwait_ext_size);
597 return (int) (pos - begin);
602 errcode = pt_reserve(encoder, ptps_pwre);
607 payload |= ((uint64_t) packet->payload.pwre.state <<
608 pt_pl_pwre_state_shr) &
609 (uint64_t) pt_pl_pwre_state_mask;
610 payload |= ((uint64_t) packet->payload.pwre.sub_state <<
611 pt_pl_pwre_sub_state_shr) &
612 (uint64_t) pt_pl_pwre_sub_state_mask;
614 if (packet->payload.pwre.hw)
615 payload |= (uint64_t) pt_pl_pwre_hw_mask;
618 *pos++ = pt_ext_pwre;
619 pos = pt_encode_int(pos, payload, pt_pl_pwre_size);
622 return (int) (pos - begin);
628 errcode = pt_reserve(encoder, ptps_pwrx);
633 payload |= ((uint64_t) packet->payload.pwrx.last <<
634 pt_pl_pwrx_last_shr) &
635 (uint64_t) pt_pl_pwrx_last_mask;
636 payload |= ((uint64_t) packet->payload.pwrx.deepest <<
637 pt_pl_pwrx_deepest_shr) &
638 (uint64_t) pt_pl_pwrx_deepest_mask;
640 if (packet->payload.pwrx.interrupt)
641 payload |= (uint64_t) pt_pl_pwrx_wr_int;
642 if (packet->payload.pwrx.store)
643 payload |= (uint64_t) pt_pl_pwrx_wr_store;
644 if (packet->payload.pwrx.autonomous)
645 payload |= (uint64_t) pt_pl_pwrx_wr_hw;
648 *pos++ = pt_ext_pwrx;
649 pos = pt_encode_int(pos, payload, pt_pl_pwrx_size);
652 return (int) (pos - begin);
659 plc = packet->payload.ptw.plc;
661 size = pt_ptw_size(plc);
665 errcode = pt_reserve(encoder,
666 (unsigned int) (pt_opcs_ptw + size));
671 ext |= plc << pt_opm_ptw_pb_shr;
673 if (packet->payload.ptw.ip)
674 ext |= (uint8_t) pt_opm_ptw_ip;
678 pos = pt_encode_int(pos, packet->payload.ptw.payload, size);
681 return (int) (pos - begin);
692 int pt_encode_pad(struct pt_encoder *encoder)
694 struct pt_packet packet;
696 packet.type = ppt_pad;
698 return pt_enc_next(encoder, &packet);
701 int pt_encode_psb(struct pt_encoder *encoder)
703 struct pt_packet packet;
705 packet.type = ppt_psb;
707 return pt_enc_next(encoder, &packet);
710 int pt_encode_psbend(struct pt_encoder *encoder)
712 struct pt_packet packet;
714 packet.type = ppt_psbend;
716 return pt_enc_next(encoder, &packet);
719 int pt_encode_tip(struct pt_encoder *encoder, uint64_t ip,
720 enum pt_ip_compression ipc)
722 struct pt_packet packet;
724 packet.type = ppt_tip;
725 packet.payload.ip.ip = ip;
726 packet.payload.ip.ipc = ipc;
728 return pt_enc_next(encoder, &packet);
731 int pt_encode_tnt_8(struct pt_encoder *encoder, uint8_t tnt, int size)
733 struct pt_packet packet;
735 packet.type = ppt_tnt_8;
736 packet.payload.tnt.bit_size = (uint8_t) size;
737 packet.payload.tnt.payload = tnt;
739 return pt_enc_next(encoder, &packet);
742 int pt_encode_tnt_64(struct pt_encoder *encoder, uint64_t tnt, int size)
744 struct pt_packet packet;
746 packet.type = ppt_tnt_64;
747 packet.payload.tnt.bit_size = (uint8_t) size;
748 packet.payload.tnt.payload = tnt;
750 return pt_enc_next(encoder, &packet);
753 int pt_encode_tip_pge(struct pt_encoder *encoder, uint64_t ip,
754 enum pt_ip_compression ipc)
756 struct pt_packet packet;
758 packet.type = ppt_tip_pge;
759 packet.payload.ip.ip = ip;
760 packet.payload.ip.ipc = ipc;
762 return pt_enc_next(encoder, &packet);
765 int pt_encode_tip_pgd(struct pt_encoder *encoder, uint64_t ip,
766 enum pt_ip_compression ipc)
768 struct pt_packet packet;
770 packet.type = ppt_tip_pgd;
771 packet.payload.ip.ip = ip;
772 packet.payload.ip.ipc = ipc;
774 return pt_enc_next(encoder, &packet);
777 int pt_encode_fup(struct pt_encoder *encoder, uint64_t ip,
778 enum pt_ip_compression ipc)
780 struct pt_packet packet;
782 packet.type = ppt_fup;
783 packet.payload.ip.ip = ip;
784 packet.payload.ip.ipc = ipc;
786 return pt_enc_next(encoder, &packet);
789 int pt_encode_pip(struct pt_encoder *encoder, uint64_t cr3, uint8_t flags)
791 struct pt_packet packet;
793 packet.type = ppt_pip;
794 packet.payload.pip.cr3 = cr3;
795 packet.payload.pip.nr = (flags & pt_pl_pip_nr) != 0;
797 return pt_enc_next(encoder, &packet);
800 int pt_encode_ovf(struct pt_encoder *encoder)
802 struct pt_packet packet;
804 packet.type = ppt_ovf;
806 return pt_enc_next(encoder, &packet);
809 int pt_encode_mode_exec(struct pt_encoder *encoder, enum pt_exec_mode mode)
811 struct pt_packet packet;
813 packet.type = ppt_mode;
814 packet.payload.mode.leaf = pt_mol_exec;
815 packet.payload.mode.bits.exec = pt_set_exec_mode(mode);
817 return pt_enc_next(encoder, &packet);
821 int pt_encode_mode_tsx(struct pt_encoder *encoder, uint8_t bits)
823 struct pt_packet packet;
825 packet.type = ppt_mode;
826 packet.payload.mode.leaf = pt_mol_tsx;
828 if (bits & pt_mob_tsx_intx)
829 packet.payload.mode.bits.tsx.intx = 1;
831 packet.payload.mode.bits.tsx.intx = 0;
833 if (bits & pt_mob_tsx_abrt)
834 packet.payload.mode.bits.tsx.abrt = 1;
836 packet.payload.mode.bits.tsx.abrt = 0;
838 return pt_enc_next(encoder, &packet);
841 int pt_encode_tsc(struct pt_encoder *encoder, uint64_t tsc)
843 struct pt_packet packet;
845 packet.type = ppt_tsc;
846 packet.payload.tsc.tsc = tsc;
848 return pt_enc_next(encoder, &packet);
851 int pt_encode_cbr(struct pt_encoder *encoder, uint8_t cbr)
853 struct pt_packet packet;
855 packet.type = ppt_cbr;
856 packet.payload.cbr.ratio = cbr;
858 return pt_enc_next(encoder, &packet);
861 int pt_encode_tma(struct pt_encoder *encoder, uint16_t ctc, uint16_t fc)
863 struct pt_packet packet;
865 packet.type = ppt_tma;
866 packet.payload.tma.ctc = ctc;
867 packet.payload.tma.fc = fc;
869 return pt_enc_next(encoder, &packet);
872 int pt_encode_mtc(struct pt_encoder *encoder, uint8_t ctc)
874 struct pt_packet packet;
876 packet.type = ppt_mtc;
877 packet.payload.mtc.ctc = ctc;
879 return pt_enc_next(encoder, &packet);
882 int pt_encode_cyc(struct pt_encoder *encoder, uint32_t ctc)
884 struct pt_packet packet;
886 packet.type = ppt_cyc;
887 packet.payload.cyc.value = ctc;
889 return pt_enc_next(encoder, &packet);
892 int pt_encode_stop(struct pt_encoder *encoder)
894 struct pt_packet packet;
896 packet.type = ppt_stop;
898 return pt_enc_next(encoder, &packet);
901 int pt_encode_vmcs(struct pt_encoder *encoder, uint64_t payload)
903 struct pt_packet packet;
905 packet.type = ppt_vmcs;
906 packet.payload.vmcs.base = payload;
908 return pt_enc_next(encoder, &packet);
911 int pt_encode_mnt(struct pt_encoder *encoder, uint64_t payload)
913 struct pt_packet packet;
915 packet.type = ppt_mnt;
916 packet.payload.mnt.payload = payload;
918 return pt_enc_next(encoder, &packet);