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