1/*
2 * Copyright (c) 2014-2019, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
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.
15 *
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.
27 */
28
29#include "pt_packet_decoder.h"
30#include "pt_decoder_function.h"
31#include "pt_packet.h"
32#include "pt_sync.h"
33#include "pt_config.h"
34#include "pt_opcodes.h"
35
36#include <string.h>
37#include <stdlib.h>
38#include <stddef.h>
39
40
41int pt_pkt_decoder_init(struct pt_packet_decoder *decoder,
42			const struct pt_config *config)
43{
44	int errcode;
45
46	if (!decoder || !config)
47		return -pte_invalid;
48
49	memset(decoder, 0, sizeof(*decoder));
50
51	errcode = pt_config_from_user(&decoder->config, config);
52	if (errcode < 0)
53		return errcode;
54
55	return 0;
56}
57
58struct pt_packet_decoder *pt_pkt_alloc_decoder(const struct pt_config *config)
59{
60	struct pt_packet_decoder *decoder;
61	int errcode;
62
63	decoder = malloc(sizeof(*decoder));
64	if (!decoder)
65		return NULL;
66
67	errcode = pt_pkt_decoder_init(decoder, config);
68	if (errcode < 0) {
69		free(decoder);
70		return NULL;
71	}
72
73	return decoder;
74}
75
76void pt_pkt_decoder_fini(struct pt_packet_decoder *decoder)
77{
78	(void) decoder;
79
80	/* Nothing to do. */
81}
82
83void pt_pkt_free_decoder(struct pt_packet_decoder *decoder)
84{
85	pt_pkt_decoder_fini(decoder);
86	free(decoder);
87}
88
89int pt_pkt_sync_forward(struct pt_packet_decoder *decoder)
90{
91	const uint8_t *pos, *sync, *begin;
92	ptrdiff_t space;
93	int errcode;
94
95	if (!decoder)
96		return -pte_invalid;
97
98	begin = decoder->config.begin;
99	sync = decoder->sync;
100	pos = decoder->pos;
101	if (!pos)
102		pos = begin;
103
104	if (pos == sync)
105		pos += ptps_psb;
106
107	if (pos < begin)
108		return -pte_internal;
109
110	/* Start a bit earlier so we find PSB that have been partially consumed
111	 * by a preceding packet.
112	 */
113	space = pos - begin;
114	if (ptps_psb <= space)
115		space = ptps_psb - 1;
116
117	pos -= space;
118
119	errcode = pt_sync_forward(&sync, pos, &decoder->config);
120	if (errcode < 0)
121		return errcode;
122
123	decoder->sync = sync;
124	decoder->pos = sync;
125
126	return 0;
127}
128
129int pt_pkt_sync_backward(struct pt_packet_decoder *decoder)
130{
131	const uint8_t *pos, *sync;
132	int errcode;
133
134	if (!decoder)
135		return -pte_invalid;
136
137	pos = decoder->pos;
138	if (!pos)
139		pos = decoder->config.end;
140
141	errcode = pt_sync_backward(&sync, pos, &decoder->config);
142	if (errcode < 0)
143		return errcode;
144
145	decoder->sync = sync;
146	decoder->pos = sync;
147
148	return 0;
149}
150
151int pt_pkt_sync_set(struct pt_packet_decoder *decoder, uint64_t offset)
152{
153	const uint8_t *begin, *end, *pos;
154
155	if (!decoder)
156		return -pte_invalid;
157
158	begin = decoder->config.begin;
159	end = decoder->config.end;
160	pos = begin + offset;
161
162	if (end < pos || pos < begin)
163		return -pte_eos;
164
165	decoder->sync = pos;
166	decoder->pos = pos;
167
168	return 0;
169}
170
171int pt_pkt_get_offset(const struct pt_packet_decoder *decoder, uint64_t *offset)
172{
173	const uint8_t *begin, *pos;
174
175	if (!decoder || !offset)
176		return -pte_invalid;
177
178	begin = decoder->config.begin;
179	pos = decoder->pos;
180
181	if (!pos)
182		return -pte_nosync;
183
184	*offset = (uint64_t) (int64_t) (pos - begin);
185	return 0;
186}
187
188int pt_pkt_get_sync_offset(const struct pt_packet_decoder *decoder,
189			   uint64_t *offset)
190{
191	const uint8_t *begin, *sync;
192
193	if (!decoder || !offset)
194		return -pte_invalid;
195
196	begin = decoder->config.begin;
197	sync = decoder->sync;
198
199	if (!sync)
200		return -pte_nosync;
201
202	*offset = (uint64_t) (int64_t) (sync - begin);
203	return 0;
204}
205
206const struct pt_config *
207pt_pkt_get_config(const struct pt_packet_decoder *decoder)
208{
209	if (!decoder)
210		return NULL;
211
212	return &decoder->config;
213}
214
215static inline int pkt_to_user(struct pt_packet *upkt, size_t size,
216			      const struct pt_packet *pkt)
217{
218	if (!upkt || !pkt)
219		return -pte_internal;
220
221	if (upkt == pkt)
222		return 0;
223
224	/* Zero out any unknown bytes. */
225	if (sizeof(*pkt) < size) {
226		memset(upkt + sizeof(*pkt), 0, size - sizeof(*pkt));
227
228		size = sizeof(*pkt);
229	}
230
231	memcpy(upkt, pkt, size);
232
233	return 0;
234}
235
236int pt_pkt_next(struct pt_packet_decoder *decoder, struct pt_packet *packet,
237		size_t psize)
238{
239	const struct pt_decoder_function *dfun;
240	struct pt_packet pkt, *ppkt;
241	int errcode, size;
242
243	if (!packet || !decoder)
244		return -pte_invalid;
245
246	ppkt = psize == sizeof(pkt) ? packet : &pkt;
247
248	errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
249	if (errcode < 0)
250		return errcode;
251
252	if (!dfun)
253		return -pte_internal;
254
255	if (!dfun->packet)
256		return -pte_internal;
257
258	size = dfun->packet(decoder, ppkt);
259	if (size < 0)
260		return size;
261
262	errcode = pkt_to_user(packet, psize, ppkt);
263	if (errcode < 0)
264		return errcode;
265
266	decoder->pos += size;
267
268	return size;
269}
270
271int pt_pkt_decode_unknown(struct pt_packet_decoder *decoder,
272			  struct pt_packet *packet)
273{
274	int size;
275
276	if (!decoder)
277		return -pte_internal;
278
279	size = pt_pkt_read_unknown(packet, decoder->pos, &decoder->config);
280	if (size < 0)
281		return size;
282
283	return size;
284}
285
286int pt_pkt_decode_pad(struct pt_packet_decoder *decoder,
287		      struct pt_packet *packet)
288{
289	(void) decoder;
290
291	if (!packet)
292		return -pte_internal;
293
294	packet->type = ppt_pad;
295	packet->size = ptps_pad;
296
297	return ptps_pad;
298}
299
300int pt_pkt_decode_psb(struct pt_packet_decoder *decoder,
301		      struct pt_packet *packet)
302{
303	int size;
304
305	if (!decoder)
306		return -pte_internal;
307
308	size = pt_pkt_read_psb(decoder->pos, &decoder->config);
309	if (size < 0)
310		return size;
311
312	packet->type = ppt_psb;
313	packet->size = (uint8_t) size;
314
315	return size;
316}
317
318int pt_pkt_decode_tip(struct pt_packet_decoder *decoder,
319		      struct pt_packet *packet)
320{
321	int size;
322
323	if (!decoder || !packet)
324		return -pte_internal;
325
326	size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
327			      &decoder->config);
328	if (size < 0)
329		return size;
330
331	packet->type = ppt_tip;
332	packet->size = (uint8_t) size;
333
334	return size;
335}
336
337int pt_pkt_decode_tnt_8(struct pt_packet_decoder *decoder,
338			struct pt_packet *packet)
339{
340	int size;
341
342	if (!decoder || !packet)
343		return -pte_internal;
344
345	size = pt_pkt_read_tnt_8(&packet->payload.tnt, decoder->pos,
346				 &decoder->config);
347	if (size < 0)
348		return size;
349
350	packet->type = ppt_tnt_8;
351	packet->size = (uint8_t) size;
352
353	return size;
354}
355
356int pt_pkt_decode_tnt_64(struct pt_packet_decoder *decoder,
357			 struct pt_packet *packet)
358{
359	int size;
360
361	if (!decoder || !packet)
362		return -pte_internal;
363
364	size = pt_pkt_read_tnt_64(&packet->payload.tnt, decoder->pos,
365				  &decoder->config);
366	if (size < 0)
367		return size;
368
369	packet->type = ppt_tnt_64;
370	packet->size = (uint8_t) size;
371
372	return size;
373}
374
375int pt_pkt_decode_tip_pge(struct pt_packet_decoder *decoder,
376			  struct pt_packet *packet)
377{
378	int size;
379
380	if (!decoder || !packet)
381		return -pte_internal;
382
383	size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
384			      &decoder->config);
385	if (size < 0)
386		return size;
387
388	packet->type = ppt_tip_pge;
389	packet->size = (uint8_t) size;
390
391	return size;
392}
393
394int pt_pkt_decode_tip_pgd(struct pt_packet_decoder *decoder,
395			  struct pt_packet *packet)
396{
397	int size;
398
399	if (!decoder || !packet)
400		return -pte_internal;
401
402	size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
403			      &decoder->config);
404	if (size < 0)
405		return size;
406
407	packet->type = ppt_tip_pgd;
408	packet->size = (uint8_t) size;
409
410	return size;
411}
412
413int pt_pkt_decode_fup(struct pt_packet_decoder *decoder,
414		      struct pt_packet *packet)
415{
416	int size;
417
418	if (!decoder || !packet)
419		return -pte_internal;
420
421	size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
422			      &decoder->config);
423	if (size < 0)
424		return size;
425
426	packet->type = ppt_fup;
427	packet->size = (uint8_t) size;
428
429	return size;
430}
431
432int pt_pkt_decode_pip(struct pt_packet_decoder *decoder,
433		      struct pt_packet *packet)
434{
435	int size;
436
437	if (!decoder || !packet)
438		return -pte_internal;
439
440	size = pt_pkt_read_pip(&packet->payload.pip, decoder->pos,
441			       &decoder->config);
442	if (size < 0)
443		return size;
444
445	packet->type = ppt_pip;
446	packet->size = (uint8_t) size;
447
448	return size;
449}
450
451int pt_pkt_decode_ovf(struct pt_packet_decoder *decoder,
452		      struct pt_packet *packet)
453{
454	(void) decoder;
455
456	if (!packet)
457		return -pte_internal;
458
459	packet->type = ppt_ovf;
460	packet->size = ptps_ovf;
461
462	return ptps_ovf;
463}
464
465int pt_pkt_decode_mode(struct pt_packet_decoder *decoder,
466		       struct pt_packet *packet)
467{
468	int size;
469
470	if (!decoder || !packet)
471		return -pte_internal;
472
473	size = pt_pkt_read_mode(&packet->payload.mode, decoder->pos,
474				&decoder->config);
475	if (size < 0)
476		return size;
477
478	packet->type = ppt_mode;
479	packet->size = (uint8_t) size;
480
481	return size;
482}
483
484int pt_pkt_decode_psbend(struct pt_packet_decoder *decoder,
485			 struct pt_packet *packet)
486{
487	(void) decoder;
488
489	if (!packet)
490		return -pte_internal;
491
492	packet->type = ppt_psbend;
493	packet->size = ptps_psbend;
494
495	return ptps_psbend;
496}
497
498int pt_pkt_decode_tsc(struct pt_packet_decoder *decoder,
499		      struct pt_packet *packet)
500{
501	int size;
502
503	if (!decoder || !packet)
504		return -pte_internal;
505
506	size = pt_pkt_read_tsc(&packet->payload.tsc, decoder->pos,
507			       &decoder->config);
508	if (size < 0)
509		return size;
510
511	packet->type = ppt_tsc;
512	packet->size = (uint8_t) size;
513
514	return size;
515}
516
517int pt_pkt_decode_cbr(struct pt_packet_decoder *decoder,
518		      struct pt_packet *packet)
519{
520	int size;
521
522	if (!decoder || !packet)
523		return -pte_internal;
524
525	size = pt_pkt_read_cbr(&packet->payload.cbr, decoder->pos,
526			       &decoder->config);
527	if (size < 0)
528		return size;
529
530	packet->type = ppt_cbr;
531	packet->size = (uint8_t) size;
532
533	return size;
534}
535
536int pt_pkt_decode_tma(struct pt_packet_decoder *decoder,
537		      struct pt_packet *packet)
538{
539	int size;
540
541	if (!decoder || !packet)
542		return -pte_internal;
543
544	size = pt_pkt_read_tma(&packet->payload.tma, decoder->pos,
545			       &decoder->config);
546	if (size < 0)
547		return size;
548
549	packet->type = ppt_tma;
550	packet->size = (uint8_t) size;
551
552	return size;
553}
554
555int pt_pkt_decode_mtc(struct pt_packet_decoder *decoder,
556		      struct pt_packet *packet)
557{
558	int size;
559
560	if (!decoder || !packet)
561		return -pte_internal;
562
563	size = pt_pkt_read_mtc(&packet->payload.mtc, decoder->pos,
564			       &decoder->config);
565	if (size < 0)
566		return size;
567
568	packet->type = ppt_mtc;
569	packet->size = (uint8_t) size;
570
571	return size;
572}
573
574int pt_pkt_decode_cyc(struct pt_packet_decoder *decoder,
575		      struct pt_packet *packet)
576{
577	int size;
578
579	if (!decoder || !packet)
580		return -pte_internal;
581
582	size = pt_pkt_read_cyc(&packet->payload.cyc, decoder->pos,
583			       &decoder->config);
584	if (size < 0)
585		return size;
586
587	packet->type = ppt_cyc;
588	packet->size = (uint8_t) size;
589
590	return size;
591}
592
593int pt_pkt_decode_stop(struct pt_packet_decoder *decoder,
594		       struct pt_packet *packet)
595{
596	(void) decoder;
597
598	if (!packet)
599		return -pte_internal;
600
601	packet->type = ppt_stop;
602	packet->size = ptps_stop;
603
604	return ptps_stop;
605}
606
607int pt_pkt_decode_vmcs(struct pt_packet_decoder *decoder,
608		       struct pt_packet *packet)
609{
610	int size;
611
612	if (!decoder || !packet)
613		return -pte_internal;
614
615	size = pt_pkt_read_vmcs(&packet->payload.vmcs, decoder->pos,
616			       &decoder->config);
617	if (size < 0)
618		return size;
619
620	packet->type = ppt_vmcs;
621	packet->size = (uint8_t) size;
622
623	return size;
624}
625
626int pt_pkt_decode_mnt(struct pt_packet_decoder *decoder,
627		      struct pt_packet *packet)
628{
629	int size;
630
631	if (!decoder || !packet)
632		return -pte_internal;
633
634	size = pt_pkt_read_mnt(&packet->payload.mnt, decoder->pos,
635			       &decoder->config);
636	if (size < 0)
637		return size;
638
639	packet->type = ppt_mnt;
640	packet->size = (uint8_t) size;
641
642	return size;
643}
644
645int pt_pkt_decode_exstop(struct pt_packet_decoder *decoder,
646			 struct pt_packet *packet)
647{
648	int size;
649
650	if (!decoder || !packet)
651		return -pte_internal;
652
653	size = pt_pkt_read_exstop(&packet->payload.exstop, decoder->pos,
654				  &decoder->config);
655	if (size < 0)
656		return size;
657
658	packet->type = ppt_exstop;
659	packet->size = (uint8_t) size;
660
661	return size;
662}
663
664int pt_pkt_decode_mwait(struct pt_packet_decoder *decoder,
665			struct pt_packet *packet)
666{
667	int size;
668
669	if (!decoder || !packet)
670		return -pte_internal;
671
672	size = pt_pkt_read_mwait(&packet->payload.mwait, decoder->pos,
673				 &decoder->config);
674	if (size < 0)
675		return size;
676
677	packet->type = ppt_mwait;
678	packet->size = (uint8_t) size;
679
680	return size;
681}
682
683int pt_pkt_decode_pwre(struct pt_packet_decoder *decoder,
684		       struct pt_packet *packet)
685{
686	int size;
687
688	if (!decoder || !packet)
689		return -pte_internal;
690
691	size = pt_pkt_read_pwre(&packet->payload.pwre, decoder->pos,
692				&decoder->config);
693	if (size < 0)
694		return size;
695
696	packet->type = ppt_pwre;
697	packet->size = (uint8_t) size;
698
699	return size;
700}
701
702int pt_pkt_decode_pwrx(struct pt_packet_decoder *decoder,
703		       struct pt_packet *packet)
704{
705	int size;
706
707	if (!decoder || !packet)
708		return -pte_internal;
709
710	size = pt_pkt_read_pwrx(&packet->payload.pwrx, decoder->pos,
711				&decoder->config);
712	if (size < 0)
713		return size;
714
715	packet->type = ppt_pwrx;
716	packet->size = (uint8_t) size;
717
718	return size;
719}
720
721int pt_pkt_decode_ptw(struct pt_packet_decoder *decoder,
722		      struct pt_packet *packet)
723{
724	int size;
725
726	if (!decoder || !packet)
727		return -pte_internal;
728
729	size = pt_pkt_read_ptw(&packet->payload.ptw, decoder->pos,
730			       &decoder->config);
731	if (size < 0)
732		return size;
733
734	packet->type = ppt_ptw;
735	packet->size = (uint8_t) size;
736
737	return size;
738}
739