2 * Copyright (c) 2014-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_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 = 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, /* opc size = */ 1 + size);
237 /* We already checked the ipc in pt_ipc_size(). */
238 ipc = (uint8_t) (packet->ipc << pt_opm_ipc_shr);
244 encoder->pos = pt_encode_int(pos, packet->ip, size);
245 return /* opc size = */ 1 + size;
248 int pt_enc_next(struct pt_encoder *encoder, const struct pt_packet *packet)
250 uint8_t *pos, *begin;
253 if (!encoder || !packet)
256 pos = begin = encoder->pos;
257 switch (packet->type) {
259 errcode = pt_reserve(encoder, ptps_pad);
266 return (int) (pos - begin);
271 errcode = pt_reserve(encoder, ptps_psb);
275 psb = ((uint64_t) pt_psb_hilo << 48 |
276 (uint64_t) pt_psb_hilo << 32 |
277 (uint64_t) pt_psb_hilo << 16 |
278 (uint64_t) pt_psb_hilo);
280 pos = pt_encode_int(pos, psb, 8);
281 pos = pt_encode_int(pos, psb, 8);
284 return (int) (pos - begin);
288 errcode = pt_reserve(encoder, ptps_psbend);
293 *pos++ = pt_ext_psbend;
296 return (int) (pos - begin);
299 errcode = pt_reserve(encoder, ptps_ovf);
307 return (int) (pos - begin);
310 return pt_encode_ip(encoder, pt_opc_fup, &packet->payload.ip);
313 return pt_encode_ip(encoder, pt_opc_tip, &packet->payload.ip);
316 return pt_encode_ip(encoder, pt_opc_tip_pge,
317 &packet->payload.ip);
320 return pt_encode_ip(encoder, pt_opc_tip_pgd,
321 &packet->payload.ip);
326 if (packet->payload.tnt.bit_size >= 7)
327 return -pte_bad_packet;
329 errcode = pt_reserve(encoder, ptps_tnt_8);
333 stop = packet->payload.tnt.bit_size + pt_opm_tnt_8_shr;
335 (packet->payload.tnt.payload << pt_opm_tnt_8_shr);
337 *pos++ = (uint8_t) (opc | (1u << stop));
340 return (int) (pos - begin);
346 errcode = pt_reserve(encoder, ptps_tnt_64);
350 if (packet->payload.tnt.bit_size >= pt_pl_tnt_64_bits)
353 stop = 1ull << packet->payload.tnt.bit_size;
354 tnt = packet->payload.tnt.payload;
356 if (tnt & ~(stop - 1))
360 *pos++ = pt_ext_tnt_64;
361 pos = pt_encode_int(pos, tnt | stop, pt_pl_tnt_64_size);
364 return (int) (pos - begin);
370 errcode = pt_reserve(encoder, ptps_mode);
374 switch (packet->payload.mode.leaf) {
376 return -pte_bad_packet;
381 if (packet->payload.mode.bits.exec.csl)
382 mode |= pt_mob_exec_csl;
384 if (packet->payload.mode.bits.exec.csd)
385 mode |= pt_mob_exec_csd;
391 if (packet->payload.mode.bits.tsx.intx)
392 mode |= pt_mob_tsx_intx;
394 if (packet->payload.mode.bits.tsx.abrt)
395 mode |= pt_mob_tsx_abrt;
399 *pos++ = pt_opc_mode;
403 return (int) (pos - begin);
409 errcode = pt_reserve(encoder, ptps_pip);
413 cr3 = packet->payload.pip.cr3;
414 cr3 >>= pt_pl_pip_shl;
415 cr3 <<= pt_pl_pip_shr;
417 if (packet->payload.pip.nr)
418 cr3 |= (uint64_t) pt_pl_pip_nr;
422 pos = pt_encode_int(pos, cr3, pt_pl_pip_size);
425 return (int) (pos - begin);
429 errcode = pt_reserve(encoder, ptps_tsc);
434 pos = pt_encode_int(pos, packet->payload.tsc.tsc,
438 return (int) (pos - begin);
441 errcode = pt_reserve(encoder, ptps_cbr);
447 *pos++ = packet->payload.cbr.ratio;
451 return (int) (pos - begin);
456 errcode = pt_reserve(encoder, ptps_tma);
460 ctc = packet->payload.tma.ctc;
461 fc = packet->payload.tma.fc;
463 if (fc & ~pt_pl_tma_fc_mask)
464 return -pte_bad_packet;
468 pos = pt_encode_int(pos, ctc, pt_pl_tma_ctc_size);
470 pos = pt_encode_int(pos, fc, pt_pl_tma_fc_size);
473 return (int) (pos - begin);
477 errcode = pt_reserve(encoder, ptps_mtc);
482 *pos++ = packet->payload.mtc.ctc;
485 return (int) (pos - begin);
488 uint8_t byte[pt_pl_cyc_max_size], index, end;
491 ctc = (uint8_t) packet->payload.cyc.value;
492 ctc <<= pt_opm_cyc_shr;
494 byte[0] = pt_opc_cyc;
495 byte[0] |= (uint8_t) ctc;
497 ctc = packet->payload.cyc.value;
498 ctc >>= (8 - pt_opm_cyc_shr);
500 byte[0] |= pt_opm_cyc_ext;
502 for (end = 1; ctc; ++end) {
503 /* Check if the CYC payload is too big. */
504 if (pt_pl_cyc_max_size <= end)
505 return -pte_bad_packet;
507 ctc <<= pt_opm_cycx_shr;
509 byte[end] = (uint8_t) ctc;
513 byte[end] |= pt_opm_cycx_ext;
516 errcode = pt_reserve(encoder, end);
520 for (index = 0; index < end; ++index)
521 *pos++ = byte[index];
524 return (int) (pos - begin);
528 errcode = pt_reserve(encoder, ptps_stop);
533 *pos++ = pt_ext_stop;
536 return (int) (pos - begin);
539 errcode = pt_reserve(encoder, ptps_vmcs);
544 *pos++ = pt_ext_vmcs;
545 pos = pt_encode_int(pos,
546 packet->payload.vmcs.base >> pt_pl_vmcs_shl,
550 return (int) (pos - begin);
553 errcode = pt_reserve(encoder, ptps_mnt);
558 *pos++ = pt_ext_ext2;
559 *pos++ = pt_ext2_mnt;
560 pos = pt_encode_int(pos, packet->payload.mnt.payload,
564 return (int) (pos - begin);
569 errcode = pt_reserve(encoder, ptps_exstop);
573 ext = packet->payload.exstop.ip ?
574 pt_ext_exstop_ip : pt_ext_exstop;
580 return (int) (pos - begin);
584 errcode = pt_reserve(encoder, ptps_mwait);
589 *pos++ = pt_ext_mwait;
590 pos = pt_encode_int(pos, packet->payload.mwait.hints,
591 pt_pl_mwait_hints_size);
592 pos = pt_encode_int(pos, packet->payload.mwait.ext,
593 pt_pl_mwait_ext_size);
596 return (int) (pos - begin);
601 errcode = pt_reserve(encoder, ptps_pwre);
606 payload |= ((uint64_t) packet->payload.pwre.state <<
607 pt_pl_pwre_state_shr) &
608 (uint64_t) pt_pl_pwre_state_mask;
609 payload |= ((uint64_t) packet->payload.pwre.sub_state <<
610 pt_pl_pwre_sub_state_shr) &
611 (uint64_t) pt_pl_pwre_sub_state_mask;
613 if (packet->payload.pwre.hw)
614 payload |= (uint64_t) pt_pl_pwre_hw_mask;
617 *pos++ = pt_ext_pwre;
618 pos = pt_encode_int(pos, payload, pt_pl_pwre_size);
621 return (int) (pos - begin);
627 errcode = pt_reserve(encoder, ptps_pwrx);
632 payload |= ((uint64_t) packet->payload.pwrx.last <<
633 pt_pl_pwrx_last_shr) &
634 (uint64_t) pt_pl_pwrx_last_mask;
635 payload |= ((uint64_t) packet->payload.pwrx.deepest <<
636 pt_pl_pwrx_deepest_shr) &
637 (uint64_t) pt_pl_pwrx_deepest_mask;
639 if (packet->payload.pwrx.interrupt)
640 payload |= (uint64_t) pt_pl_pwrx_wr_int;
641 if (packet->payload.pwrx.store)
642 payload |= (uint64_t) pt_pl_pwrx_wr_store;
643 if (packet->payload.pwrx.autonomous)
644 payload |= (uint64_t) pt_pl_pwrx_wr_hw;
647 *pos++ = pt_ext_pwrx;
648 pos = pt_encode_int(pos, payload, pt_pl_pwrx_size);
651 return (int) (pos - begin);
658 plc = packet->payload.ptw.plc;
660 size = pt_ptw_size(plc);
664 errcode = pt_reserve(encoder, pt_opcs_ptw + size);
669 ext |= plc << pt_opm_ptw_pb_shr;
671 if (packet->payload.ptw.ip)
672 ext |= (uint8_t) pt_opm_ptw_ip;
676 pos = pt_encode_int(pos, packet->payload.ptw.payload, size);
679 return (int) (pos - begin);
690 int pt_encode_pad(struct pt_encoder *encoder)
692 struct pt_packet packet;
694 packet.type = ppt_pad;
696 return pt_enc_next(encoder, &packet);
699 int pt_encode_psb(struct pt_encoder *encoder)
701 struct pt_packet packet;
703 packet.type = ppt_psb;
705 return pt_enc_next(encoder, &packet);
708 int pt_encode_psbend(struct pt_encoder *encoder)
710 struct pt_packet packet;
712 packet.type = ppt_psbend;
714 return pt_enc_next(encoder, &packet);
717 int pt_encode_tip(struct pt_encoder *encoder, uint64_t ip,
718 enum pt_ip_compression ipc)
720 struct pt_packet packet;
722 packet.type = ppt_tip;
723 packet.payload.ip.ip = ip;
724 packet.payload.ip.ipc = ipc;
726 return pt_enc_next(encoder, &packet);
729 int pt_encode_tnt_8(struct pt_encoder *encoder, uint8_t tnt, int size)
731 struct pt_packet packet;
733 packet.type = ppt_tnt_8;
734 packet.payload.tnt.bit_size = (uint8_t) size;
735 packet.payload.tnt.payload = tnt;
737 return pt_enc_next(encoder, &packet);
740 int pt_encode_tnt_64(struct pt_encoder *encoder, uint64_t tnt, int size)
742 struct pt_packet packet;
744 packet.type = ppt_tnt_64;
745 packet.payload.tnt.bit_size = (uint8_t) size;
746 packet.payload.tnt.payload = tnt;
748 return pt_enc_next(encoder, &packet);
751 int pt_encode_tip_pge(struct pt_encoder *encoder, uint64_t ip,
752 enum pt_ip_compression ipc)
754 struct pt_packet packet;
756 packet.type = ppt_tip_pge;
757 packet.payload.ip.ip = ip;
758 packet.payload.ip.ipc = ipc;
760 return pt_enc_next(encoder, &packet);
763 int pt_encode_tip_pgd(struct pt_encoder *encoder, uint64_t ip,
764 enum pt_ip_compression ipc)
766 struct pt_packet packet;
768 packet.type = ppt_tip_pgd;
769 packet.payload.ip.ip = ip;
770 packet.payload.ip.ipc = ipc;
772 return pt_enc_next(encoder, &packet);
775 int pt_encode_fup(struct pt_encoder *encoder, uint64_t ip,
776 enum pt_ip_compression ipc)
778 struct pt_packet packet;
780 packet.type = ppt_fup;
781 packet.payload.ip.ip = ip;
782 packet.payload.ip.ipc = ipc;
784 return pt_enc_next(encoder, &packet);
787 int pt_encode_pip(struct pt_encoder *encoder, uint64_t cr3, uint8_t flags)
789 struct pt_packet packet;
791 packet.type = ppt_pip;
792 packet.payload.pip.cr3 = cr3;
793 packet.payload.pip.nr = (flags & pt_pl_pip_nr) != 0;
795 return pt_enc_next(encoder, &packet);
798 int pt_encode_ovf(struct pt_encoder *encoder)
800 struct pt_packet packet;
802 packet.type = ppt_ovf;
804 return pt_enc_next(encoder, &packet);
807 int pt_encode_mode_exec(struct pt_encoder *encoder, enum pt_exec_mode mode)
809 struct pt_packet packet;
811 packet.type = ppt_mode;
812 packet.payload.mode.leaf = pt_mol_exec;
813 packet.payload.mode.bits.exec = pt_set_exec_mode(mode);
815 return pt_enc_next(encoder, &packet);
819 int pt_encode_mode_tsx(struct pt_encoder *encoder, uint8_t bits)
821 struct pt_packet packet;
823 packet.type = ppt_mode;
824 packet.payload.mode.leaf = pt_mol_tsx;
826 if (bits & pt_mob_tsx_intx)
827 packet.payload.mode.bits.tsx.intx = 1;
829 packet.payload.mode.bits.tsx.intx = 0;
831 if (bits & pt_mob_tsx_abrt)
832 packet.payload.mode.bits.tsx.abrt = 1;
834 packet.payload.mode.bits.tsx.abrt = 0;
836 return pt_enc_next(encoder, &packet);
839 int pt_encode_tsc(struct pt_encoder *encoder, uint64_t tsc)
841 struct pt_packet packet;
843 packet.type = ppt_tsc;
844 packet.payload.tsc.tsc = tsc;
846 return pt_enc_next(encoder, &packet);
849 int pt_encode_cbr(struct pt_encoder *encoder, uint8_t cbr)
851 struct pt_packet packet;
853 packet.type = ppt_cbr;
854 packet.payload.cbr.ratio = cbr;
856 return pt_enc_next(encoder, &packet);
859 int pt_encode_tma(struct pt_encoder *encoder, uint16_t ctc, uint16_t fc)
861 struct pt_packet packet;
863 packet.type = ppt_tma;
864 packet.payload.tma.ctc = ctc;
865 packet.payload.tma.fc = fc;
867 return pt_enc_next(encoder, &packet);
870 int pt_encode_mtc(struct pt_encoder *encoder, uint8_t ctc)
872 struct pt_packet packet;
874 packet.type = ppt_mtc;
875 packet.payload.mtc.ctc = ctc;
877 return pt_enc_next(encoder, &packet);
880 int pt_encode_cyc(struct pt_encoder *encoder, uint32_t ctc)
882 struct pt_packet packet;
884 packet.type = ppt_cyc;
885 packet.payload.cyc.value = ctc;
887 return pt_enc_next(encoder, &packet);
890 int pt_encode_stop(struct pt_encoder *encoder)
892 struct pt_packet packet;
894 packet.type = ppt_stop;
896 return pt_enc_next(encoder, &packet);
899 int pt_encode_vmcs(struct pt_encoder *encoder, uint64_t payload)
901 struct pt_packet packet;
903 packet.type = ppt_vmcs;
904 packet.payload.vmcs.base = payload;
906 return pt_enc_next(encoder, &packet);
909 int pt_encode_mnt(struct pt_encoder *encoder, uint64_t payload)
911 struct pt_packet packet;
913 packet.type = ppt_mnt;
914 packet.payload.mnt.payload = payload;
916 return pt_enc_next(encoder, &packet);