174fe6c29SRuslan Bukin /*
285f87cf4SRuslan Bukin  * Copyright (c) 2014-2019, Intel Corporation
374fe6c29SRuslan Bukin  *
474fe6c29SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
574fe6c29SRuslan Bukin  * modification, are permitted provided that the following conditions are met:
674fe6c29SRuslan Bukin  *
774fe6c29SRuslan Bukin  *  * Redistributions of source code must retain the above copyright notice,
874fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer.
974fe6c29SRuslan Bukin  *  * Redistributions in binary form must reproduce the above copyright notice,
1074fe6c29SRuslan Bukin  *    this list of conditions and the following disclaimer in the documentation
1174fe6c29SRuslan Bukin  *    and/or other materials provided with the distribution.
1274fe6c29SRuslan Bukin  *  * Neither the name of Intel Corporation nor the names of its contributors
1374fe6c29SRuslan Bukin  *    may be used to endorse or promote products derived from this software
1474fe6c29SRuslan Bukin  *    without specific prior written permission.
1574fe6c29SRuslan Bukin  *
1674fe6c29SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1774fe6c29SRuslan Bukin  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1874fe6c29SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1974fe6c29SRuslan Bukin  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2074fe6c29SRuslan Bukin  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2174fe6c29SRuslan Bukin  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2274fe6c29SRuslan Bukin  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2374fe6c29SRuslan Bukin  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2474fe6c29SRuslan Bukin  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2574fe6c29SRuslan Bukin  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2674fe6c29SRuslan Bukin  * POSSIBILITY OF SUCH DAMAGE.
2774fe6c29SRuslan Bukin  */
2874fe6c29SRuslan Bukin 
2974fe6c29SRuslan Bukin #include "pt_encoder.h"
3074fe6c29SRuslan Bukin #include "pt_config.h"
3174fe6c29SRuslan Bukin #include "pt_opcodes.h"
3274fe6c29SRuslan Bukin 
3374fe6c29SRuslan Bukin #include <string.h>
3474fe6c29SRuslan Bukin #include <stdlib.h>
3574fe6c29SRuslan Bukin 
3674fe6c29SRuslan Bukin 
pt_encoder_init(struct pt_encoder * encoder,const struct pt_config * config)3774fe6c29SRuslan Bukin int pt_encoder_init(struct pt_encoder *encoder, const struct pt_config *config)
3874fe6c29SRuslan Bukin {
3974fe6c29SRuslan Bukin 	int errcode;
4074fe6c29SRuslan Bukin 
4174fe6c29SRuslan Bukin 	if (!encoder)
4274fe6c29SRuslan Bukin 		return -pte_invalid;
4374fe6c29SRuslan Bukin 
4474fe6c29SRuslan Bukin 	memset(encoder, 0, sizeof(*encoder));
4574fe6c29SRuslan Bukin 
4674fe6c29SRuslan Bukin 	errcode = pt_config_from_user(&encoder->config, config);
4774fe6c29SRuslan Bukin 	if (errcode < 0)
4874fe6c29SRuslan Bukin 		return errcode;
4974fe6c29SRuslan Bukin 
5074fe6c29SRuslan Bukin 	encoder->pos = encoder->config.begin;
5174fe6c29SRuslan Bukin 
5274fe6c29SRuslan Bukin 	return 0;
5374fe6c29SRuslan Bukin }
5474fe6c29SRuslan Bukin 
pt_encoder_fini(struct pt_encoder * encoder)5574fe6c29SRuslan Bukin void pt_encoder_fini(struct pt_encoder *encoder)
5674fe6c29SRuslan Bukin {
5774fe6c29SRuslan Bukin 	(void) encoder;
5874fe6c29SRuslan Bukin 
5974fe6c29SRuslan Bukin 	/* Nothing to do. */
6074fe6c29SRuslan Bukin }
6174fe6c29SRuslan Bukin 
pt_alloc_encoder(const struct pt_config * config)6274fe6c29SRuslan Bukin struct pt_encoder *pt_alloc_encoder(const struct pt_config *config)
6374fe6c29SRuslan Bukin {
6474fe6c29SRuslan Bukin 	struct pt_encoder *encoder;
6574fe6c29SRuslan Bukin 	int errcode;
6674fe6c29SRuslan Bukin 
6774fe6c29SRuslan Bukin 	encoder = malloc(sizeof(*encoder));
6874fe6c29SRuslan Bukin 	if (!encoder)
6974fe6c29SRuslan Bukin 		return NULL;
7074fe6c29SRuslan Bukin 
7174fe6c29SRuslan Bukin 	errcode = pt_encoder_init(encoder, config);
7274fe6c29SRuslan Bukin 	if (errcode < 0) {
7374fe6c29SRuslan Bukin 		free(encoder);
7474fe6c29SRuslan Bukin 		return NULL;
7574fe6c29SRuslan Bukin 	}
7674fe6c29SRuslan Bukin 
7774fe6c29SRuslan Bukin 	return encoder;
7874fe6c29SRuslan Bukin }
7974fe6c29SRuslan Bukin 
pt_free_encoder(struct pt_encoder * encoder)8074fe6c29SRuslan Bukin void pt_free_encoder(struct pt_encoder *encoder)
8174fe6c29SRuslan Bukin {
8274fe6c29SRuslan Bukin 	pt_encoder_fini(encoder);
8374fe6c29SRuslan Bukin 	free(encoder);
8474fe6c29SRuslan Bukin }
8574fe6c29SRuslan Bukin 
pt_enc_sync_set(struct pt_encoder * encoder,uint64_t offset)8674fe6c29SRuslan Bukin int pt_enc_sync_set(struct pt_encoder *encoder, uint64_t offset)
8774fe6c29SRuslan Bukin {
8874fe6c29SRuslan Bukin 	uint8_t *begin, *end, *pos;
8974fe6c29SRuslan Bukin 
9074fe6c29SRuslan Bukin 	if (!encoder)
9174fe6c29SRuslan Bukin 		return -pte_invalid;
9274fe6c29SRuslan Bukin 
9374fe6c29SRuslan Bukin 	begin = encoder->config.begin;
9474fe6c29SRuslan Bukin 	end = encoder->config.end;
9574fe6c29SRuslan Bukin 	pos = begin + offset;
9674fe6c29SRuslan Bukin 
9774fe6c29SRuslan Bukin 	if (end < pos || pos < begin)
9874fe6c29SRuslan Bukin 		return -pte_eos;
9974fe6c29SRuslan Bukin 
10074fe6c29SRuslan Bukin 	encoder->pos = pos;
10174fe6c29SRuslan Bukin 	return 0;
10274fe6c29SRuslan Bukin }
10374fe6c29SRuslan Bukin 
pt_enc_get_offset(const struct pt_encoder * encoder,uint64_t * offset)10474fe6c29SRuslan Bukin int pt_enc_get_offset(const struct pt_encoder *encoder, uint64_t *offset)
10574fe6c29SRuslan Bukin {
10674fe6c29SRuslan Bukin 	const uint8_t *raw, *begin;
10774fe6c29SRuslan Bukin 
10874fe6c29SRuslan Bukin 	if (!encoder || !offset)
10974fe6c29SRuslan Bukin 		return -pte_invalid;
11074fe6c29SRuslan Bukin 
11174fe6c29SRuslan Bukin 	/* The encoder is synchronized at all times. */
11274fe6c29SRuslan Bukin 	raw = encoder->pos;
11374fe6c29SRuslan Bukin 	if (!raw)
11474fe6c29SRuslan Bukin 		return -pte_internal;
11574fe6c29SRuslan Bukin 
11674fe6c29SRuslan Bukin 	begin = encoder->config.begin;
11774fe6c29SRuslan Bukin 	if (!begin)
11874fe6c29SRuslan Bukin 		return -pte_internal;
11974fe6c29SRuslan Bukin 
12085f87cf4SRuslan Bukin 	*offset = (uint64_t) (int64_t) (raw - begin);
12174fe6c29SRuslan Bukin 	return 0;
12274fe6c29SRuslan Bukin }
12374fe6c29SRuslan Bukin 
pt_enc_get_config(const struct pt_encoder * encoder)12474fe6c29SRuslan Bukin const struct pt_config *pt_enc_get_config(const struct pt_encoder *encoder)
12574fe6c29SRuslan Bukin {
12674fe6c29SRuslan Bukin 	if (!encoder)
12774fe6c29SRuslan Bukin 		return NULL;
12874fe6c29SRuslan Bukin 
12974fe6c29SRuslan Bukin 	return &encoder->config;
13074fe6c29SRuslan Bukin }
13174fe6c29SRuslan Bukin 
13274fe6c29SRuslan Bukin /* Check the remaining space.
13374fe6c29SRuslan Bukin  *
13474fe6c29SRuslan Bukin  * Returns zero if there are at least \@size bytes of free space available in
13574fe6c29SRuslan Bukin  * \@encoder's Intel PT buffer.
13674fe6c29SRuslan Bukin  *
13774fe6c29SRuslan Bukin  * Returns -pte_eos if not enough space is available.
13874fe6c29SRuslan Bukin  * Returns -pte_internal if \@encoder is NULL.
13974fe6c29SRuslan Bukin  * Returns -pte_internal if \@encoder is not synchronized.
14074fe6c29SRuslan Bukin  */
pt_reserve(const struct pt_encoder * encoder,unsigned int size)14174fe6c29SRuslan Bukin static int pt_reserve(const struct pt_encoder *encoder, unsigned int size)
14274fe6c29SRuslan Bukin {
14374fe6c29SRuslan Bukin 	const uint8_t *begin, *end, *pos;
14474fe6c29SRuslan Bukin 
14574fe6c29SRuslan Bukin 	if (!encoder)
14674fe6c29SRuslan Bukin 		return -pte_internal;
14774fe6c29SRuslan Bukin 
14874fe6c29SRuslan Bukin 	/* The encoder is synchronized at all times. */
14974fe6c29SRuslan Bukin 	pos = encoder->pos;
15074fe6c29SRuslan Bukin 	if (!pos)
15174fe6c29SRuslan Bukin 		return -pte_internal;
15274fe6c29SRuslan Bukin 
15374fe6c29SRuslan Bukin 	begin = encoder->config.begin;
15474fe6c29SRuslan Bukin 	end = encoder->config.end;
15574fe6c29SRuslan Bukin 
15674fe6c29SRuslan Bukin 	pos += size;
15774fe6c29SRuslan Bukin 	if (pos < begin || end < pos)
15874fe6c29SRuslan Bukin 		return -pte_eos;
15974fe6c29SRuslan Bukin 
16074fe6c29SRuslan Bukin 	return 0;
16174fe6c29SRuslan Bukin }
16274fe6c29SRuslan Bukin 
16374fe6c29SRuslan Bukin /* Return the size of an IP payload based on its IP compression.
16474fe6c29SRuslan Bukin  *
16574fe6c29SRuslan Bukin  * Returns -pte_bad_packet if \@ipc is not a valid IP compression.
16674fe6c29SRuslan Bukin  */
pt_ipc_size(enum pt_ip_compression ipc)16774fe6c29SRuslan Bukin static int pt_ipc_size(enum pt_ip_compression ipc)
16874fe6c29SRuslan Bukin {
16974fe6c29SRuslan Bukin 	switch (ipc) {
17074fe6c29SRuslan Bukin 	case pt_ipc_suppressed:
17174fe6c29SRuslan Bukin 		return 0;
17274fe6c29SRuslan Bukin 
17374fe6c29SRuslan Bukin 	case pt_ipc_update_16:
17474fe6c29SRuslan Bukin 		return pt_pl_ip_upd16_size;
17574fe6c29SRuslan Bukin 
17674fe6c29SRuslan Bukin 	case pt_ipc_update_32:
17774fe6c29SRuslan Bukin 		return pt_pl_ip_upd32_size;
17874fe6c29SRuslan Bukin 
17974fe6c29SRuslan Bukin 	case pt_ipc_update_48:
18074fe6c29SRuslan Bukin 		return pt_pl_ip_upd48_size;
18174fe6c29SRuslan Bukin 
18274fe6c29SRuslan Bukin 	case pt_ipc_sext_48:
18374fe6c29SRuslan Bukin 		return pt_pl_ip_sext48_size;
18474fe6c29SRuslan Bukin 
18574fe6c29SRuslan Bukin 	case pt_ipc_full:
18674fe6c29SRuslan Bukin 		return pt_pl_ip_full_size;
18774fe6c29SRuslan Bukin 	}
18874fe6c29SRuslan Bukin 
18974fe6c29SRuslan Bukin 	return -pte_invalid;
19074fe6c29SRuslan Bukin }
19174fe6c29SRuslan Bukin 
19274fe6c29SRuslan Bukin /* Encode an integer value.
19374fe6c29SRuslan Bukin  *
19474fe6c29SRuslan Bukin  * Writes the \@size least signifficant bytes of \@value starting from \@pos.
19574fe6c29SRuslan Bukin  *
19674fe6c29SRuslan Bukin  * The caller needs to ensure that there is enough space available.
19774fe6c29SRuslan Bukin  *
19874fe6c29SRuslan Bukin  * Returns the updated position.
19974fe6c29SRuslan Bukin  */
pt_encode_int(uint8_t * pos,uint64_t val,int size)20074fe6c29SRuslan Bukin static uint8_t *pt_encode_int(uint8_t *pos, uint64_t val, int size)
20174fe6c29SRuslan Bukin {
20274fe6c29SRuslan Bukin 	for (; size; --size, val >>= 8)
20374fe6c29SRuslan Bukin 		*pos++ = (uint8_t) val;
20474fe6c29SRuslan Bukin 
20574fe6c29SRuslan Bukin 	return pos;
20674fe6c29SRuslan Bukin }
20774fe6c29SRuslan Bukin 
20874fe6c29SRuslan Bukin /* Encode an IP packet.
20974fe6c29SRuslan Bukin  *
21074fe6c29SRuslan Bukin  * Write an IP packet with opcode \@opc and payload from \@packet if there is
21174fe6c29SRuslan Bukin  * enough space in \@encoder's Intel PT buffer.
21274fe6c29SRuslan Bukin  *
21374fe6c29SRuslan Bukin  * Returns the number of bytes written on success.
21474fe6c29SRuslan Bukin  *
21574fe6c29SRuslan Bukin  * Returns -pte_eos if there is not enough space.
21674fe6c29SRuslan Bukin  * Returns -pte_internal if \@encoder or \@packet is NULL.
21774fe6c29SRuslan Bukin  * Returns -pte_invalid if \@packet.ipc is not valid.
21874fe6c29SRuslan Bukin  */
pt_encode_ip(struct pt_encoder * encoder,enum pt_opcode op,const struct pt_packet_ip * packet)21974fe6c29SRuslan Bukin static int pt_encode_ip(struct pt_encoder *encoder, enum pt_opcode op,
22074fe6c29SRuslan Bukin 			const struct pt_packet_ip *packet)
22174fe6c29SRuslan Bukin {
22274fe6c29SRuslan Bukin 	uint8_t *pos;
22374fe6c29SRuslan Bukin 	uint8_t opc, ipc;
22474fe6c29SRuslan Bukin 	int size, errcode;
22574fe6c29SRuslan Bukin 
22674fe6c29SRuslan Bukin 	if (!encoder || !packet)
22774fe6c29SRuslan Bukin 		return pte_internal;
22874fe6c29SRuslan Bukin 
22974fe6c29SRuslan Bukin 	size = pt_ipc_size(packet->ipc);
23074fe6c29SRuslan Bukin 	if (size < 0)
23174fe6c29SRuslan Bukin 		return size;
23274fe6c29SRuslan Bukin 
23385f87cf4SRuslan Bukin 	errcode = pt_reserve(encoder,
23485f87cf4SRuslan Bukin 			     /* opc size = */ 1u + (unsigned int) size);
23574fe6c29SRuslan Bukin 	if (errcode < 0)
23674fe6c29SRuslan Bukin 		return errcode;
23774fe6c29SRuslan Bukin 
23874fe6c29SRuslan Bukin 	/* We already checked the ipc in pt_ipc_size(). */
23974fe6c29SRuslan Bukin 	ipc = (uint8_t) (packet->ipc << pt_opm_ipc_shr);
24074fe6c29SRuslan Bukin 	opc = (uint8_t) op;
24174fe6c29SRuslan Bukin 
24274fe6c29SRuslan Bukin 	pos = encoder->pos;
24374fe6c29SRuslan Bukin 	*pos++ = opc | ipc;
24474fe6c29SRuslan Bukin 
24574fe6c29SRuslan Bukin 	encoder->pos = pt_encode_int(pos, packet->ip, size);
24674fe6c29SRuslan Bukin 	return /* opc size = */ 1 + size;
24774fe6c29SRuslan Bukin }
24874fe6c29SRuslan Bukin 
pt_enc_next(struct pt_encoder * encoder,const struct pt_packet * packet)24974fe6c29SRuslan Bukin int pt_enc_next(struct pt_encoder *encoder, const struct pt_packet *packet)
25074fe6c29SRuslan Bukin {
25174fe6c29SRuslan Bukin 	uint8_t *pos, *begin;
25274fe6c29SRuslan Bukin 	int errcode;
25374fe6c29SRuslan Bukin 
25474fe6c29SRuslan Bukin 	if (!encoder || !packet)
25574fe6c29SRuslan Bukin 		return -pte_invalid;
25674fe6c29SRuslan Bukin 
25774fe6c29SRuslan Bukin 	pos = begin = encoder->pos;
25874fe6c29SRuslan Bukin 	switch (packet->type) {
25974fe6c29SRuslan Bukin 	case ppt_pad:
26074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_pad);
26174fe6c29SRuslan Bukin 		if (errcode < 0)
26274fe6c29SRuslan Bukin 			return errcode;
26374fe6c29SRuslan Bukin 
26474fe6c29SRuslan Bukin 		*pos++ = pt_opc_pad;
26574fe6c29SRuslan Bukin 
26674fe6c29SRuslan Bukin 		encoder->pos = pos;
26774fe6c29SRuslan Bukin 		return (int) (pos - begin);
26874fe6c29SRuslan Bukin 
26974fe6c29SRuslan Bukin 	case ppt_psb: {
27074fe6c29SRuslan Bukin 		uint64_t psb;
27174fe6c29SRuslan Bukin 
27274fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_psb);
27374fe6c29SRuslan Bukin 		if (errcode < 0)
27474fe6c29SRuslan Bukin 			return errcode;
27574fe6c29SRuslan Bukin 
27674fe6c29SRuslan Bukin 		psb = ((uint64_t) pt_psb_hilo << 48 |
27774fe6c29SRuslan Bukin 		       (uint64_t) pt_psb_hilo << 32 |
27874fe6c29SRuslan Bukin 		       (uint64_t) pt_psb_hilo << 16 |
27974fe6c29SRuslan Bukin 		       (uint64_t) pt_psb_hilo);
28074fe6c29SRuslan Bukin 
28174fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, psb, 8);
28274fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, psb, 8);
28374fe6c29SRuslan Bukin 
28474fe6c29SRuslan Bukin 		encoder->pos = pos;
28574fe6c29SRuslan Bukin 		return (int) (pos - begin);
28674fe6c29SRuslan Bukin 	}
28774fe6c29SRuslan Bukin 
28874fe6c29SRuslan Bukin 	case ppt_psbend:
28974fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_psbend);
29074fe6c29SRuslan Bukin 		if (errcode < 0)
29174fe6c29SRuslan Bukin 			return errcode;
29274fe6c29SRuslan Bukin 
29374fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
29474fe6c29SRuslan Bukin 		*pos++ = pt_ext_psbend;
29574fe6c29SRuslan Bukin 
29674fe6c29SRuslan Bukin 		encoder->pos = pos;
29774fe6c29SRuslan Bukin 		return (int) (pos - begin);
29874fe6c29SRuslan Bukin 
29974fe6c29SRuslan Bukin 	case ppt_ovf:
30074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_ovf);
30174fe6c29SRuslan Bukin 		if (errcode < 0)
30274fe6c29SRuslan Bukin 			return errcode;
30374fe6c29SRuslan Bukin 
30474fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
30574fe6c29SRuslan Bukin 		*pos++ = pt_ext_ovf;
30674fe6c29SRuslan Bukin 
30774fe6c29SRuslan Bukin 		encoder->pos = pos;
30874fe6c29SRuslan Bukin 		return (int) (pos - begin);
30974fe6c29SRuslan Bukin 
31074fe6c29SRuslan Bukin 	case ppt_fup:
31174fe6c29SRuslan Bukin 		return pt_encode_ip(encoder, pt_opc_fup, &packet->payload.ip);
31274fe6c29SRuslan Bukin 
31374fe6c29SRuslan Bukin 	case ppt_tip:
31474fe6c29SRuslan Bukin 		return pt_encode_ip(encoder, pt_opc_tip, &packet->payload.ip);
31574fe6c29SRuslan Bukin 
31674fe6c29SRuslan Bukin 	case ppt_tip_pge:
31774fe6c29SRuslan Bukin 		return pt_encode_ip(encoder, pt_opc_tip_pge,
31874fe6c29SRuslan Bukin 				    &packet->payload.ip);
31974fe6c29SRuslan Bukin 
32074fe6c29SRuslan Bukin 	case ppt_tip_pgd:
32174fe6c29SRuslan Bukin 		return pt_encode_ip(encoder, pt_opc_tip_pgd,
32274fe6c29SRuslan Bukin 				    &packet->payload.ip);
32374fe6c29SRuslan Bukin 
32474fe6c29SRuslan Bukin 	case ppt_tnt_8: {
32574fe6c29SRuslan Bukin 		uint8_t opc, stop;
32674fe6c29SRuslan Bukin 
32774fe6c29SRuslan Bukin 		if (packet->payload.tnt.bit_size >= 7)
32874fe6c29SRuslan Bukin 			return -pte_bad_packet;
32974fe6c29SRuslan Bukin 
33074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_tnt_8);
33174fe6c29SRuslan Bukin 		if (errcode < 0)
33274fe6c29SRuslan Bukin 			return errcode;
33374fe6c29SRuslan Bukin 
33474fe6c29SRuslan Bukin 		stop = packet->payload.tnt.bit_size + pt_opm_tnt_8_shr;
33574fe6c29SRuslan Bukin 		opc = (uint8_t)
33674fe6c29SRuslan Bukin 			(packet->payload.tnt.payload << pt_opm_tnt_8_shr);
33774fe6c29SRuslan Bukin 
33874fe6c29SRuslan Bukin 		*pos++ = (uint8_t) (opc | (1u << stop));
33974fe6c29SRuslan Bukin 
34074fe6c29SRuslan Bukin 		encoder->pos = pos;
34174fe6c29SRuslan Bukin 		return (int) (pos - begin);
34274fe6c29SRuslan Bukin 	}
34374fe6c29SRuslan Bukin 
34474fe6c29SRuslan Bukin 	case ppt_tnt_64: {
34574fe6c29SRuslan Bukin 		uint64_t tnt, stop;
34674fe6c29SRuslan Bukin 
34774fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_tnt_64);
34874fe6c29SRuslan Bukin 		if (errcode < 0)
34974fe6c29SRuslan Bukin 			return errcode;
35074fe6c29SRuslan Bukin 
35174fe6c29SRuslan Bukin 		if (packet->payload.tnt.bit_size >= pt_pl_tnt_64_bits)
35274fe6c29SRuslan Bukin 			return -pte_invalid;
35374fe6c29SRuslan Bukin 
35474fe6c29SRuslan Bukin 		stop = 1ull << packet->payload.tnt.bit_size;
35574fe6c29SRuslan Bukin 		tnt = packet->payload.tnt.payload;
35674fe6c29SRuslan Bukin 
35774fe6c29SRuslan Bukin 		if (tnt & ~(stop - 1))
35874fe6c29SRuslan Bukin 			return -pte_invalid;
35974fe6c29SRuslan Bukin 
36074fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
36174fe6c29SRuslan Bukin 		*pos++ = pt_ext_tnt_64;
36274fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, tnt | stop, pt_pl_tnt_64_size);
36374fe6c29SRuslan Bukin 
36474fe6c29SRuslan Bukin 		encoder->pos = pos;
36574fe6c29SRuslan Bukin 		return (int) (pos - begin);
36674fe6c29SRuslan Bukin 	}
36774fe6c29SRuslan Bukin 
36874fe6c29SRuslan Bukin 	case ppt_mode: {
36974fe6c29SRuslan Bukin 		uint8_t mode;
37074fe6c29SRuslan Bukin 
37174fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_mode);
37274fe6c29SRuslan Bukin 		if (errcode < 0)
37374fe6c29SRuslan Bukin 			return errcode;
37474fe6c29SRuslan Bukin 
37574fe6c29SRuslan Bukin 		switch (packet->payload.mode.leaf) {
37674fe6c29SRuslan Bukin 		default:
37774fe6c29SRuslan Bukin 			return -pte_bad_packet;
37874fe6c29SRuslan Bukin 
37974fe6c29SRuslan Bukin 		case pt_mol_exec:
38074fe6c29SRuslan Bukin 			mode = pt_mol_exec;
38174fe6c29SRuslan Bukin 
38274fe6c29SRuslan Bukin 			if (packet->payload.mode.bits.exec.csl)
38374fe6c29SRuslan Bukin 				mode |= pt_mob_exec_csl;
38474fe6c29SRuslan Bukin 
38574fe6c29SRuslan Bukin 			if (packet->payload.mode.bits.exec.csd)
38674fe6c29SRuslan Bukin 				mode |= pt_mob_exec_csd;
38774fe6c29SRuslan Bukin 			break;
38874fe6c29SRuslan Bukin 
38974fe6c29SRuslan Bukin 		case pt_mol_tsx:
39074fe6c29SRuslan Bukin 			mode = pt_mol_tsx;
39174fe6c29SRuslan Bukin 
39274fe6c29SRuslan Bukin 			if (packet->payload.mode.bits.tsx.intx)
39374fe6c29SRuslan Bukin 				mode |= pt_mob_tsx_intx;
39474fe6c29SRuslan Bukin 
39574fe6c29SRuslan Bukin 			if (packet->payload.mode.bits.tsx.abrt)
39674fe6c29SRuslan Bukin 				mode |= pt_mob_tsx_abrt;
39774fe6c29SRuslan Bukin 			break;
39874fe6c29SRuslan Bukin 		}
39974fe6c29SRuslan Bukin 
40074fe6c29SRuslan Bukin 		*pos++ = pt_opc_mode;
40174fe6c29SRuslan Bukin 		*pos++ = mode;
40274fe6c29SRuslan Bukin 
40374fe6c29SRuslan Bukin 		encoder->pos = pos;
40474fe6c29SRuslan Bukin 		return (int) (pos - begin);
40574fe6c29SRuslan Bukin 	}
40674fe6c29SRuslan Bukin 
40774fe6c29SRuslan Bukin 	case ppt_pip: {
40874fe6c29SRuslan Bukin 		uint64_t cr3;
40974fe6c29SRuslan Bukin 
41074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_pip);
41174fe6c29SRuslan Bukin 		if (errcode < 0)
41274fe6c29SRuslan Bukin 			return errcode;
41374fe6c29SRuslan Bukin 
41474fe6c29SRuslan Bukin 		cr3 = packet->payload.pip.cr3;
41574fe6c29SRuslan Bukin 		cr3 >>= pt_pl_pip_shl;
41674fe6c29SRuslan Bukin 		cr3 <<= pt_pl_pip_shr;
41774fe6c29SRuslan Bukin 
41874fe6c29SRuslan Bukin 		if (packet->payload.pip.nr)
41974fe6c29SRuslan Bukin 			cr3 |= (uint64_t) pt_pl_pip_nr;
42074fe6c29SRuslan Bukin 
42174fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
42274fe6c29SRuslan Bukin 		*pos++ = pt_ext_pip;
42374fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, cr3, pt_pl_pip_size);
42474fe6c29SRuslan Bukin 
42574fe6c29SRuslan Bukin 		encoder->pos = pos;
42674fe6c29SRuslan Bukin 		return (int) (pos - begin);
42774fe6c29SRuslan Bukin 	}
42874fe6c29SRuslan Bukin 
42974fe6c29SRuslan Bukin 	case ppt_tsc:
43074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_tsc);
43174fe6c29SRuslan Bukin 		if (errcode < 0)
43274fe6c29SRuslan Bukin 			return errcode;
43374fe6c29SRuslan Bukin 
43474fe6c29SRuslan Bukin 		*pos++ = pt_opc_tsc;
43574fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, packet->payload.tsc.tsc,
43674fe6c29SRuslan Bukin 				    pt_pl_tsc_size);
43774fe6c29SRuslan Bukin 
43874fe6c29SRuslan Bukin 		encoder->pos = pos;
43974fe6c29SRuslan Bukin 		return (int) (pos - begin);
44074fe6c29SRuslan Bukin 
44174fe6c29SRuslan Bukin 	case ppt_cbr:
44274fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_cbr);
44374fe6c29SRuslan Bukin 		if (errcode < 0)
44474fe6c29SRuslan Bukin 			return errcode;
44574fe6c29SRuslan Bukin 
44674fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
44774fe6c29SRuslan Bukin 		*pos++ = pt_ext_cbr;
44874fe6c29SRuslan Bukin 		*pos++ = packet->payload.cbr.ratio;
44974fe6c29SRuslan Bukin 		*pos++ = 0;
45074fe6c29SRuslan Bukin 
45174fe6c29SRuslan Bukin 		encoder->pos = pos;
45274fe6c29SRuslan Bukin 		return (int) (pos - begin);
45374fe6c29SRuslan Bukin 
45474fe6c29SRuslan Bukin 	case ppt_tma: {
45574fe6c29SRuslan Bukin 		uint16_t ctc, fc;
45674fe6c29SRuslan Bukin 
45774fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_tma);
45874fe6c29SRuslan Bukin 		if (errcode < 0)
45974fe6c29SRuslan Bukin 			return errcode;
46074fe6c29SRuslan Bukin 
46174fe6c29SRuslan Bukin 		ctc = packet->payload.tma.ctc;
46274fe6c29SRuslan Bukin 		fc = packet->payload.tma.fc;
46374fe6c29SRuslan Bukin 
46474fe6c29SRuslan Bukin 		if (fc & ~pt_pl_tma_fc_mask)
46574fe6c29SRuslan Bukin 			return -pte_bad_packet;
46674fe6c29SRuslan Bukin 
46774fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
46874fe6c29SRuslan Bukin 		*pos++ = pt_ext_tma;
46974fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, ctc, pt_pl_tma_ctc_size);
47074fe6c29SRuslan Bukin 		*pos++ = 0;
47174fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, fc, pt_pl_tma_fc_size);
47274fe6c29SRuslan Bukin 
47374fe6c29SRuslan Bukin 		encoder->pos = pos;
47474fe6c29SRuslan Bukin 		return (int) (pos - begin);
47574fe6c29SRuslan Bukin 	}
47674fe6c29SRuslan Bukin 
47774fe6c29SRuslan Bukin 	case ppt_mtc:
47874fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_mtc);
47974fe6c29SRuslan Bukin 		if (errcode < 0)
48074fe6c29SRuslan Bukin 			return errcode;
48174fe6c29SRuslan Bukin 
48274fe6c29SRuslan Bukin 		*pos++ = pt_opc_mtc;
48374fe6c29SRuslan Bukin 		*pos++ = packet->payload.mtc.ctc;
48474fe6c29SRuslan Bukin 
48574fe6c29SRuslan Bukin 		encoder->pos = pos;
48674fe6c29SRuslan Bukin 		return (int) (pos - begin);
48774fe6c29SRuslan Bukin 
48874fe6c29SRuslan Bukin 	case ppt_cyc: {
48974fe6c29SRuslan Bukin 		uint8_t byte[pt_pl_cyc_max_size], index, end;
49074fe6c29SRuslan Bukin 		uint64_t ctc;
49174fe6c29SRuslan Bukin 
49274fe6c29SRuslan Bukin 		ctc = (uint8_t) packet->payload.cyc.value;
49374fe6c29SRuslan Bukin 		ctc <<= pt_opm_cyc_shr;
49474fe6c29SRuslan Bukin 
49574fe6c29SRuslan Bukin 		byte[0] = pt_opc_cyc;
49674fe6c29SRuslan Bukin 		byte[0] |= (uint8_t) ctc;
49774fe6c29SRuslan Bukin 
49874fe6c29SRuslan Bukin 		ctc = packet->payload.cyc.value;
49974fe6c29SRuslan Bukin 		ctc >>= (8 - pt_opm_cyc_shr);
50074fe6c29SRuslan Bukin 		if (ctc)
50174fe6c29SRuslan Bukin 			byte[0] |= pt_opm_cyc_ext;
50274fe6c29SRuslan Bukin 
50374fe6c29SRuslan Bukin 		for (end = 1; ctc; ++end) {
50474fe6c29SRuslan Bukin 			/* Check if the CYC payload is too big. */
50574fe6c29SRuslan Bukin 			if (pt_pl_cyc_max_size <= end)
50674fe6c29SRuslan Bukin 				return -pte_bad_packet;
50774fe6c29SRuslan Bukin 
50874fe6c29SRuslan Bukin 			ctc <<= pt_opm_cycx_shr;
50974fe6c29SRuslan Bukin 
51074fe6c29SRuslan Bukin 			byte[end] = (uint8_t) ctc;
51174fe6c29SRuslan Bukin 
51274fe6c29SRuslan Bukin 			ctc >>= 8;
51374fe6c29SRuslan Bukin 			if (ctc)
51474fe6c29SRuslan Bukin 				byte[end] |= pt_opm_cycx_ext;
51574fe6c29SRuslan Bukin 		}
51674fe6c29SRuslan Bukin 
51774fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, end);
51874fe6c29SRuslan Bukin 		if (errcode < 0)
51974fe6c29SRuslan Bukin 			return errcode;
52074fe6c29SRuslan Bukin 
52174fe6c29SRuslan Bukin 		for (index = 0; index < end; ++index)
52274fe6c29SRuslan Bukin 			*pos++ = byte[index];
52374fe6c29SRuslan Bukin 
52474fe6c29SRuslan Bukin 		encoder->pos = pos;
52574fe6c29SRuslan Bukin 		return (int) (pos - begin);
52674fe6c29SRuslan Bukin 	}
52774fe6c29SRuslan Bukin 
52874fe6c29SRuslan Bukin 	case ppt_stop:
52974fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_stop);
53074fe6c29SRuslan Bukin 		if (errcode < 0)
53174fe6c29SRuslan Bukin 			return errcode;
53274fe6c29SRuslan Bukin 
53374fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
53474fe6c29SRuslan Bukin 		*pos++ = pt_ext_stop;
53574fe6c29SRuslan Bukin 
53674fe6c29SRuslan Bukin 		encoder->pos = pos;
53774fe6c29SRuslan Bukin 		return (int) (pos - begin);
53874fe6c29SRuslan Bukin 
53974fe6c29SRuslan Bukin 	case ppt_vmcs:
54074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_vmcs);
54174fe6c29SRuslan Bukin 		if (errcode < 0)
54274fe6c29SRuslan Bukin 			return errcode;
54374fe6c29SRuslan Bukin 
54474fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
54574fe6c29SRuslan Bukin 		*pos++ = pt_ext_vmcs;
54674fe6c29SRuslan Bukin 		pos = pt_encode_int(pos,
54774fe6c29SRuslan Bukin 				    packet->payload.vmcs.base >> pt_pl_vmcs_shl,
54874fe6c29SRuslan Bukin 				    pt_pl_vmcs_size);
54974fe6c29SRuslan Bukin 
55074fe6c29SRuslan Bukin 		encoder->pos = pos;
55174fe6c29SRuslan Bukin 		return (int) (pos - begin);
55274fe6c29SRuslan Bukin 
55374fe6c29SRuslan Bukin 	case ppt_mnt:
55474fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_mnt);
55574fe6c29SRuslan Bukin 		if (errcode < 0)
55674fe6c29SRuslan Bukin 			return errcode;
55774fe6c29SRuslan Bukin 
55874fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
55974fe6c29SRuslan Bukin 		*pos++ = pt_ext_ext2;
56074fe6c29SRuslan Bukin 		*pos++ = pt_ext2_mnt;
56174fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, packet->payload.mnt.payload,
56274fe6c29SRuslan Bukin 				    pt_pl_mnt_size);
56374fe6c29SRuslan Bukin 
56474fe6c29SRuslan Bukin 		encoder->pos = pos;
56574fe6c29SRuslan Bukin 		return (int) (pos - begin);
56674fe6c29SRuslan Bukin 
56774fe6c29SRuslan Bukin 	case ppt_exstop: {
56874fe6c29SRuslan Bukin 		uint8_t ext;
56974fe6c29SRuslan Bukin 
57074fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_exstop);
57174fe6c29SRuslan Bukin 		if (errcode < 0)
57274fe6c29SRuslan Bukin 			return errcode;
57374fe6c29SRuslan Bukin 
57474fe6c29SRuslan Bukin 		ext = packet->payload.exstop.ip ?
57574fe6c29SRuslan Bukin 			pt_ext_exstop_ip : pt_ext_exstop;
57674fe6c29SRuslan Bukin 
57774fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
57874fe6c29SRuslan Bukin 		*pos++ = ext;
57974fe6c29SRuslan Bukin 
58074fe6c29SRuslan Bukin 		encoder->pos = pos;
58174fe6c29SRuslan Bukin 		return (int) (pos - begin);
58274fe6c29SRuslan Bukin 	}
58374fe6c29SRuslan Bukin 
58474fe6c29SRuslan Bukin 	case ppt_mwait:
58574fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_mwait);
58674fe6c29SRuslan Bukin 		if (errcode < 0)
58774fe6c29SRuslan Bukin 			return errcode;
58874fe6c29SRuslan Bukin 
58974fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
59074fe6c29SRuslan Bukin 		*pos++ = pt_ext_mwait;
59174fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, packet->payload.mwait.hints,
59274fe6c29SRuslan Bukin 				    pt_pl_mwait_hints_size);
59374fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, packet->payload.mwait.ext,
59474fe6c29SRuslan Bukin 				    pt_pl_mwait_ext_size);
59574fe6c29SRuslan Bukin 
59674fe6c29SRuslan Bukin 		encoder->pos = pos;
59774fe6c29SRuslan Bukin 		return (int) (pos - begin);
59874fe6c29SRuslan Bukin 
59974fe6c29SRuslan Bukin 	case ppt_pwre: {
60074fe6c29SRuslan Bukin 		uint64_t payload;
60174fe6c29SRuslan Bukin 
60274fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_pwre);
60374fe6c29SRuslan Bukin 		if (errcode < 0)
60474fe6c29SRuslan Bukin 			return errcode;
60574fe6c29SRuslan Bukin 
60674fe6c29SRuslan Bukin 		payload = 0ull;
60774fe6c29SRuslan Bukin 		payload |= ((uint64_t) packet->payload.pwre.state <<
60874fe6c29SRuslan Bukin 			    pt_pl_pwre_state_shr) &
60974fe6c29SRuslan Bukin 			(uint64_t) pt_pl_pwre_state_mask;
61074fe6c29SRuslan Bukin 		payload |= ((uint64_t) packet->payload.pwre.sub_state <<
61174fe6c29SRuslan Bukin 			    pt_pl_pwre_sub_state_shr) &
61274fe6c29SRuslan Bukin 			(uint64_t) pt_pl_pwre_sub_state_mask;
61374fe6c29SRuslan Bukin 
61474fe6c29SRuslan Bukin 		if (packet->payload.pwre.hw)
61574fe6c29SRuslan Bukin 			payload |= (uint64_t) pt_pl_pwre_hw_mask;
61674fe6c29SRuslan Bukin 
61774fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
61874fe6c29SRuslan Bukin 		*pos++ = pt_ext_pwre;
61974fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, payload, pt_pl_pwre_size);
62074fe6c29SRuslan Bukin 
62174fe6c29SRuslan Bukin 		encoder->pos = pos;
62274fe6c29SRuslan Bukin 		return (int) (pos - begin);
62374fe6c29SRuslan Bukin 	}
62474fe6c29SRuslan Bukin 
62574fe6c29SRuslan Bukin 	case ppt_pwrx: {
62674fe6c29SRuslan Bukin 		uint64_t payload;
62774fe6c29SRuslan Bukin 
62874fe6c29SRuslan Bukin 		errcode = pt_reserve(encoder, ptps_pwrx);
62974fe6c29SRuslan Bukin 		if (errcode < 0)
63074fe6c29SRuslan Bukin 			return errcode;
63174fe6c29SRuslan Bukin 
63274fe6c29SRuslan Bukin 		payload = 0ull;
63374fe6c29SRuslan Bukin 		payload |= ((uint64_t) packet->payload.pwrx.last <<
63474fe6c29SRuslan Bukin 			    pt_pl_pwrx_last_shr) &
63574fe6c29SRuslan Bukin 			(uint64_t) pt_pl_pwrx_last_mask;
63674fe6c29SRuslan Bukin 		payload |= ((uint64_t) packet->payload.pwrx.deepest <<
63774fe6c29SRuslan Bukin 			    pt_pl_pwrx_deepest_shr) &
63874fe6c29SRuslan Bukin 			(uint64_t) pt_pl_pwrx_deepest_mask;
63974fe6c29SRuslan Bukin 
64074fe6c29SRuslan Bukin 		if (packet->payload.pwrx.interrupt)
64174fe6c29SRuslan Bukin 			payload |= (uint64_t) pt_pl_pwrx_wr_int;
64274fe6c29SRuslan Bukin 		if (packet->payload.pwrx.store)
64374fe6c29SRuslan Bukin 			payload |= (uint64_t) pt_pl_pwrx_wr_store;
64474fe6c29SRuslan Bukin 		if (packet->payload.pwrx.autonomous)
64574fe6c29SRuslan Bukin 			payload |= (uint64_t) pt_pl_pwrx_wr_hw;
64674fe6c29SRuslan Bukin 
64774fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
64874fe6c29SRuslan Bukin 		*pos++ = pt_ext_pwrx;
64974fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, payload, pt_pl_pwrx_size);
65074fe6c29SRuslan Bukin 
65174fe6c29SRuslan Bukin 		encoder->pos = pos;
65274fe6c29SRuslan Bukin 		return (int) (pos - begin);
65374fe6c29SRuslan Bukin 	}
65474fe6c29SRuslan Bukin 
65574fe6c29SRuslan Bukin 	case ppt_ptw: {
65674fe6c29SRuslan Bukin 		uint8_t plc, ext;
65774fe6c29SRuslan Bukin 		int size;
65874fe6c29SRuslan Bukin 
65974fe6c29SRuslan Bukin 		plc = packet->payload.ptw.plc;
66074fe6c29SRuslan Bukin 
66174fe6c29SRuslan Bukin 		size = pt_ptw_size(plc);
66274fe6c29SRuslan Bukin 		if (size < 0)
66374fe6c29SRuslan Bukin 			return size;
66474fe6c29SRuslan Bukin 
66585f87cf4SRuslan Bukin 		errcode = pt_reserve(encoder,
66685f87cf4SRuslan Bukin 				     (unsigned int) (pt_opcs_ptw + size));
66774fe6c29SRuslan Bukin 		if (errcode < 0)
66874fe6c29SRuslan Bukin 			return errcode;
66974fe6c29SRuslan Bukin 
67074fe6c29SRuslan Bukin 		ext = pt_ext_ptw;
67174fe6c29SRuslan Bukin 		ext |= plc << pt_opm_ptw_pb_shr;
67274fe6c29SRuslan Bukin 
67374fe6c29SRuslan Bukin 		if (packet->payload.ptw.ip)
67474fe6c29SRuslan Bukin 			ext |= (uint8_t) pt_opm_ptw_ip;
67574fe6c29SRuslan Bukin 
67674fe6c29SRuslan Bukin 		*pos++ = pt_opc_ext;
67774fe6c29SRuslan Bukin 		*pos++ = ext;
67874fe6c29SRuslan Bukin 		pos = pt_encode_int(pos, packet->payload.ptw.payload, size);
67974fe6c29SRuslan Bukin 
68074fe6c29SRuslan Bukin 		encoder->pos = pos;
68174fe6c29SRuslan Bukin 		return (int) (pos - begin);
68274fe6c29SRuslan Bukin 	}
68374fe6c29SRuslan Bukin 
68474fe6c29SRuslan Bukin 	case ppt_unknown:
68574fe6c29SRuslan Bukin 	case ppt_invalid:
68674fe6c29SRuslan Bukin 		return -pte_bad_opc;
68774fe6c29SRuslan Bukin 	}
68874fe6c29SRuslan Bukin 
68974fe6c29SRuslan Bukin 	return -pte_bad_opc;
69074fe6c29SRuslan Bukin }
69174fe6c29SRuslan Bukin 
pt_encode_pad(struct pt_encoder * encoder)69274fe6c29SRuslan Bukin int pt_encode_pad(struct pt_encoder *encoder)
69374fe6c29SRuslan Bukin {
69474fe6c29SRuslan Bukin 	struct pt_packet packet;
69574fe6c29SRuslan Bukin 
69674fe6c29SRuslan Bukin 	packet.type = ppt_pad;
69774fe6c29SRuslan Bukin 
69874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
69974fe6c29SRuslan Bukin }
70074fe6c29SRuslan Bukin 
pt_encode_psb(struct pt_encoder * encoder)70174fe6c29SRuslan Bukin int pt_encode_psb(struct pt_encoder *encoder)
70274fe6c29SRuslan Bukin {
70374fe6c29SRuslan Bukin 	struct pt_packet packet;
70474fe6c29SRuslan Bukin 
70574fe6c29SRuslan Bukin 	packet.type = ppt_psb;
70674fe6c29SRuslan Bukin 
70774fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
70874fe6c29SRuslan Bukin }
70974fe6c29SRuslan Bukin 
pt_encode_psbend(struct pt_encoder * encoder)71074fe6c29SRuslan Bukin int pt_encode_psbend(struct pt_encoder *encoder)
71174fe6c29SRuslan Bukin {
71274fe6c29SRuslan Bukin 	struct pt_packet packet;
71374fe6c29SRuslan Bukin 
71474fe6c29SRuslan Bukin 	packet.type = ppt_psbend;
71574fe6c29SRuslan Bukin 
71674fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
71774fe6c29SRuslan Bukin }
71874fe6c29SRuslan Bukin 
pt_encode_tip(struct pt_encoder * encoder,uint64_t ip,enum pt_ip_compression ipc)71974fe6c29SRuslan Bukin int pt_encode_tip(struct pt_encoder *encoder, uint64_t ip,
72074fe6c29SRuslan Bukin 		  enum pt_ip_compression ipc)
72174fe6c29SRuslan Bukin {
72274fe6c29SRuslan Bukin 	struct pt_packet packet;
72374fe6c29SRuslan Bukin 
72474fe6c29SRuslan Bukin 	packet.type = ppt_tip;
72574fe6c29SRuslan Bukin 	packet.payload.ip.ip = ip;
72674fe6c29SRuslan Bukin 	packet.payload.ip.ipc = ipc;
72774fe6c29SRuslan Bukin 
72874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
72974fe6c29SRuslan Bukin }
73074fe6c29SRuslan Bukin 
pt_encode_tnt_8(struct pt_encoder * encoder,uint8_t tnt,int size)73174fe6c29SRuslan Bukin int pt_encode_tnt_8(struct pt_encoder *encoder, uint8_t tnt, int size)
73274fe6c29SRuslan Bukin {
73374fe6c29SRuslan Bukin 	struct pt_packet packet;
73474fe6c29SRuslan Bukin 
73574fe6c29SRuslan Bukin 	packet.type = ppt_tnt_8;
73674fe6c29SRuslan Bukin 	packet.payload.tnt.bit_size = (uint8_t) size;
73774fe6c29SRuslan Bukin 	packet.payload.tnt.payload = tnt;
73874fe6c29SRuslan Bukin 
73974fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
74074fe6c29SRuslan Bukin }
74174fe6c29SRuslan Bukin 
pt_encode_tnt_64(struct pt_encoder * encoder,uint64_t tnt,int size)74274fe6c29SRuslan Bukin int pt_encode_tnt_64(struct pt_encoder *encoder, uint64_t tnt, int size)
74374fe6c29SRuslan Bukin {
74474fe6c29SRuslan Bukin 	struct pt_packet packet;
74574fe6c29SRuslan Bukin 
74674fe6c29SRuslan Bukin 	packet.type = ppt_tnt_64;
74774fe6c29SRuslan Bukin 	packet.payload.tnt.bit_size = (uint8_t) size;
74874fe6c29SRuslan Bukin 	packet.payload.tnt.payload = tnt;
74974fe6c29SRuslan Bukin 
75074fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
75174fe6c29SRuslan Bukin }
75274fe6c29SRuslan Bukin 
pt_encode_tip_pge(struct pt_encoder * encoder,uint64_t ip,enum pt_ip_compression ipc)75374fe6c29SRuslan Bukin int pt_encode_tip_pge(struct pt_encoder *encoder, uint64_t ip,
75474fe6c29SRuslan Bukin 		      enum pt_ip_compression ipc)
75574fe6c29SRuslan Bukin {
75674fe6c29SRuslan Bukin 	struct pt_packet packet;
75774fe6c29SRuslan Bukin 
75874fe6c29SRuslan Bukin 	packet.type = ppt_tip_pge;
75974fe6c29SRuslan Bukin 	packet.payload.ip.ip = ip;
76074fe6c29SRuslan Bukin 	packet.payload.ip.ipc = ipc;
76174fe6c29SRuslan Bukin 
76274fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
76374fe6c29SRuslan Bukin }
76474fe6c29SRuslan Bukin 
pt_encode_tip_pgd(struct pt_encoder * encoder,uint64_t ip,enum pt_ip_compression ipc)76574fe6c29SRuslan Bukin int pt_encode_tip_pgd(struct pt_encoder *encoder, uint64_t ip,
76674fe6c29SRuslan Bukin 		      enum pt_ip_compression ipc)
76774fe6c29SRuslan Bukin {
76874fe6c29SRuslan Bukin 	struct pt_packet packet;
76974fe6c29SRuslan Bukin 
77074fe6c29SRuslan Bukin 	packet.type = ppt_tip_pgd;
77174fe6c29SRuslan Bukin 	packet.payload.ip.ip = ip;
77274fe6c29SRuslan Bukin 	packet.payload.ip.ipc = ipc;
77374fe6c29SRuslan Bukin 
77474fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
77574fe6c29SRuslan Bukin }
77674fe6c29SRuslan Bukin 
pt_encode_fup(struct pt_encoder * encoder,uint64_t ip,enum pt_ip_compression ipc)77774fe6c29SRuslan Bukin int pt_encode_fup(struct pt_encoder *encoder, uint64_t ip,
77874fe6c29SRuslan Bukin 		  enum pt_ip_compression ipc)
77974fe6c29SRuslan Bukin {
78074fe6c29SRuslan Bukin 	struct pt_packet packet;
78174fe6c29SRuslan Bukin 
78274fe6c29SRuslan Bukin 	packet.type = ppt_fup;
78374fe6c29SRuslan Bukin 	packet.payload.ip.ip = ip;
78474fe6c29SRuslan Bukin 	packet.payload.ip.ipc = ipc;
78574fe6c29SRuslan Bukin 
78674fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
78774fe6c29SRuslan Bukin }
78874fe6c29SRuslan Bukin 
pt_encode_pip(struct pt_encoder * encoder,uint64_t cr3,uint8_t flags)78974fe6c29SRuslan Bukin int pt_encode_pip(struct pt_encoder *encoder, uint64_t cr3, uint8_t flags)
79074fe6c29SRuslan Bukin {
79174fe6c29SRuslan Bukin 	struct pt_packet packet;
79274fe6c29SRuslan Bukin 
79374fe6c29SRuslan Bukin 	packet.type = ppt_pip;
79474fe6c29SRuslan Bukin 	packet.payload.pip.cr3 = cr3;
79574fe6c29SRuslan Bukin 	packet.payload.pip.nr = (flags & pt_pl_pip_nr) != 0;
79674fe6c29SRuslan Bukin 
79774fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
79874fe6c29SRuslan Bukin }
79974fe6c29SRuslan Bukin 
pt_encode_ovf(struct pt_encoder * encoder)80074fe6c29SRuslan Bukin int pt_encode_ovf(struct pt_encoder *encoder)
80174fe6c29SRuslan Bukin {
80274fe6c29SRuslan Bukin 	struct pt_packet packet;
80374fe6c29SRuslan Bukin 
80474fe6c29SRuslan Bukin 	packet.type = ppt_ovf;
80574fe6c29SRuslan Bukin 
80674fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
80774fe6c29SRuslan Bukin }
80874fe6c29SRuslan Bukin 
pt_encode_mode_exec(struct pt_encoder * encoder,enum pt_exec_mode mode)80974fe6c29SRuslan Bukin int pt_encode_mode_exec(struct pt_encoder *encoder, enum pt_exec_mode mode)
81074fe6c29SRuslan Bukin {
81174fe6c29SRuslan Bukin 	struct pt_packet packet;
81274fe6c29SRuslan Bukin 
81374fe6c29SRuslan Bukin 	packet.type = ppt_mode;
81474fe6c29SRuslan Bukin 	packet.payload.mode.leaf = pt_mol_exec;
81574fe6c29SRuslan Bukin 	packet.payload.mode.bits.exec = pt_set_exec_mode(mode);
81674fe6c29SRuslan Bukin 
81774fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
81874fe6c29SRuslan Bukin }
81974fe6c29SRuslan Bukin 
82074fe6c29SRuslan Bukin 
pt_encode_mode_tsx(struct pt_encoder * encoder,uint8_t bits)82174fe6c29SRuslan Bukin int pt_encode_mode_tsx(struct pt_encoder *encoder, uint8_t bits)
82274fe6c29SRuslan Bukin {
82374fe6c29SRuslan Bukin 	struct pt_packet packet;
82474fe6c29SRuslan Bukin 
82574fe6c29SRuslan Bukin 	packet.type = ppt_mode;
82674fe6c29SRuslan Bukin 	packet.payload.mode.leaf = pt_mol_tsx;
82774fe6c29SRuslan Bukin 
82874fe6c29SRuslan Bukin 	if (bits & pt_mob_tsx_intx)
82974fe6c29SRuslan Bukin 		packet.payload.mode.bits.tsx.intx = 1;
83074fe6c29SRuslan Bukin 	else
83174fe6c29SRuslan Bukin 		packet.payload.mode.bits.tsx.intx = 0;
83274fe6c29SRuslan Bukin 
83374fe6c29SRuslan Bukin 	if (bits & pt_mob_tsx_abrt)
83474fe6c29SRuslan Bukin 		packet.payload.mode.bits.tsx.abrt = 1;
83574fe6c29SRuslan Bukin 	else
83674fe6c29SRuslan Bukin 		packet.payload.mode.bits.tsx.abrt = 0;
83774fe6c29SRuslan Bukin 
83874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
83974fe6c29SRuslan Bukin }
84074fe6c29SRuslan Bukin 
pt_encode_tsc(struct pt_encoder * encoder,uint64_t tsc)84174fe6c29SRuslan Bukin int pt_encode_tsc(struct pt_encoder *encoder, uint64_t tsc)
84274fe6c29SRuslan Bukin {
84374fe6c29SRuslan Bukin 	struct pt_packet packet;
84474fe6c29SRuslan Bukin 
84574fe6c29SRuslan Bukin 	packet.type = ppt_tsc;
84674fe6c29SRuslan Bukin 	packet.payload.tsc.tsc = tsc;
84774fe6c29SRuslan Bukin 
84874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
84974fe6c29SRuslan Bukin }
85074fe6c29SRuslan Bukin 
pt_encode_cbr(struct pt_encoder * encoder,uint8_t cbr)85174fe6c29SRuslan Bukin int pt_encode_cbr(struct pt_encoder *encoder, uint8_t cbr)
85274fe6c29SRuslan Bukin {
85374fe6c29SRuslan Bukin 	struct pt_packet packet;
85474fe6c29SRuslan Bukin 
85574fe6c29SRuslan Bukin 	packet.type = ppt_cbr;
85674fe6c29SRuslan Bukin 	packet.payload.cbr.ratio = cbr;
85774fe6c29SRuslan Bukin 
85874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
85974fe6c29SRuslan Bukin }
86074fe6c29SRuslan Bukin 
pt_encode_tma(struct pt_encoder * encoder,uint16_t ctc,uint16_t fc)86174fe6c29SRuslan Bukin int pt_encode_tma(struct pt_encoder *encoder, uint16_t ctc, uint16_t fc)
86274fe6c29SRuslan Bukin {
86374fe6c29SRuslan Bukin 	struct pt_packet packet;
86474fe6c29SRuslan Bukin 
86574fe6c29SRuslan Bukin 	packet.type = ppt_tma;
86674fe6c29SRuslan Bukin 	packet.payload.tma.ctc = ctc;
86774fe6c29SRuslan Bukin 	packet.payload.tma.fc = fc;
86874fe6c29SRuslan Bukin 
86974fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
87074fe6c29SRuslan Bukin }
87174fe6c29SRuslan Bukin 
pt_encode_mtc(struct pt_encoder * encoder,uint8_t ctc)87274fe6c29SRuslan Bukin int pt_encode_mtc(struct pt_encoder *encoder, uint8_t ctc)
87374fe6c29SRuslan Bukin {
87474fe6c29SRuslan Bukin 	struct pt_packet packet;
87574fe6c29SRuslan Bukin 
87674fe6c29SRuslan Bukin 	packet.type = ppt_mtc;
87774fe6c29SRuslan Bukin 	packet.payload.mtc.ctc = ctc;
87874fe6c29SRuslan Bukin 
87974fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
88074fe6c29SRuslan Bukin }
88174fe6c29SRuslan Bukin 
pt_encode_cyc(struct pt_encoder * encoder,uint32_t ctc)88274fe6c29SRuslan Bukin int pt_encode_cyc(struct pt_encoder *encoder, uint32_t ctc)
88374fe6c29SRuslan Bukin {
88474fe6c29SRuslan Bukin 	struct pt_packet packet;
88574fe6c29SRuslan Bukin 
88674fe6c29SRuslan Bukin 	packet.type = ppt_cyc;
88774fe6c29SRuslan Bukin 	packet.payload.cyc.value = ctc;
88874fe6c29SRuslan Bukin 
88974fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
89074fe6c29SRuslan Bukin }
89174fe6c29SRuslan Bukin 
pt_encode_stop(struct pt_encoder * encoder)89274fe6c29SRuslan Bukin int pt_encode_stop(struct pt_encoder *encoder)
89374fe6c29SRuslan Bukin {
89474fe6c29SRuslan Bukin 	struct pt_packet packet;
89574fe6c29SRuslan Bukin 
89674fe6c29SRuslan Bukin 	packet.type = ppt_stop;
89774fe6c29SRuslan Bukin 
89874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
89974fe6c29SRuslan Bukin }
90074fe6c29SRuslan Bukin 
pt_encode_vmcs(struct pt_encoder * encoder,uint64_t payload)90174fe6c29SRuslan Bukin int pt_encode_vmcs(struct pt_encoder *encoder, uint64_t payload)
90274fe6c29SRuslan Bukin {
90374fe6c29SRuslan Bukin 	struct pt_packet packet;
90474fe6c29SRuslan Bukin 
90574fe6c29SRuslan Bukin 	packet.type = ppt_vmcs;
90674fe6c29SRuslan Bukin 	packet.payload.vmcs.base = payload;
90774fe6c29SRuslan Bukin 
90874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
90974fe6c29SRuslan Bukin }
91074fe6c29SRuslan Bukin 
pt_encode_mnt(struct pt_encoder * encoder,uint64_t payload)91174fe6c29SRuslan Bukin int pt_encode_mnt(struct pt_encoder *encoder, uint64_t payload)
91274fe6c29SRuslan Bukin {
91374fe6c29SRuslan Bukin 	struct pt_packet packet;
91474fe6c29SRuslan Bukin 
91574fe6c29SRuslan Bukin 	packet.type = ppt_mnt;
91674fe6c29SRuslan Bukin 	packet.payload.mnt.payload = payload;
91774fe6c29SRuslan Bukin 
91874fe6c29SRuslan Bukin 	return pt_enc_next(encoder, &packet);
91974fe6c29SRuslan Bukin }
920