xref: /freebsd/contrib/processor-trace/libipt/src/pt_decoder_function.c (revision 3078531de10dcae44b253a35125c949ff4235284)
1 /*
2  * Copyright (c) 2013-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_decoder_function.h"
30 #include "pt_packet_decoder.h"
31 #include "pt_query_decoder.h"
32 #include "pt_opcodes.h"
33 
34 #include "intel-pt.h"
35 
36 
37 const struct pt_decoder_function pt_decode_unknown = {
38 	/* .packet = */ pt_pkt_decode_unknown,
39 	/* .decode = */ pt_qry_decode_unknown,
40 	/* .header = */ pt_qry_decode_unknown,
41 	/* .flags =  */ pdff_unknown
42 };
43 
44 const struct pt_decoder_function pt_decode_pad = {
45 	/* .packet = */ pt_pkt_decode_pad,
46 	/* .decode = */ pt_qry_decode_pad,
47 	/* .header = */ pt_qry_decode_pad,
48 	/* .flags =  */ pdff_pad
49 };
50 
51 const struct pt_decoder_function pt_decode_psb = {
52 	/* .packet = */ pt_pkt_decode_psb,
53 	/* .decode = */ pt_qry_decode_psb,
54 	/* .header = */ NULL,
55 	/* .flags =  */ 0
56 };
57 
58 const struct pt_decoder_function pt_decode_tip = {
59 	/* .packet = */ pt_pkt_decode_tip,
60 	/* .decode = */ pt_qry_decode_tip,
61 	/* .header = */ NULL,
62 	/* .flags =  */ pdff_tip
63 };
64 
65 const struct pt_decoder_function pt_decode_tnt_8 = {
66 	/* .packet = */ pt_pkt_decode_tnt_8,
67 	/* .decode = */ pt_qry_decode_tnt_8,
68 	/* .header = */ NULL,
69 	/* .flags =  */ pdff_tnt
70 };
71 
72 const struct pt_decoder_function pt_decode_tnt_64 = {
73 	/* .packet = */ pt_pkt_decode_tnt_64,
74 	/* .decode = */ pt_qry_decode_tnt_64,
75 	/* .header = */ NULL,
76 	/* .flags =  */ pdff_tnt
77 };
78 
79 const struct pt_decoder_function pt_decode_tip_pge = {
80 	/* .packet = */ pt_pkt_decode_tip_pge,
81 	/* .decode = */ pt_qry_decode_tip_pge,
82 	/* .header = */ NULL,
83 	/* .flags =  */ pdff_event
84 };
85 
86 const struct pt_decoder_function pt_decode_tip_pgd = {
87 	/* .packet = */ pt_pkt_decode_tip_pgd,
88 	/* .decode = */ pt_qry_decode_tip_pgd,
89 	/* .header = */ NULL,
90 	/* .flags =  */ pdff_event
91 };
92 
93 const struct pt_decoder_function pt_decode_fup = {
94 	/* .packet = */ pt_pkt_decode_fup,
95 	/* .decode = */ pt_qry_decode_fup,
96 	/* .header = */ pt_qry_header_fup,
97 	/* .flags =  */ pdff_fup
98 };
99 
100 const struct pt_decoder_function pt_decode_pip = {
101 	/* .packet = */ pt_pkt_decode_pip,
102 	/* .decode = */ pt_qry_decode_pip,
103 	/* .header = */ pt_qry_header_pip,
104 	/* .flags =  */ pdff_event
105 };
106 
107 const struct pt_decoder_function pt_decode_ovf = {
108 	/* .packet = */ pt_pkt_decode_ovf,
109 	/* .decode = */ pt_qry_decode_ovf,
110 	/* .header = */ NULL,
111 	/* .flags =  */ pdff_psbend | pdff_event
112 };
113 
114 const struct pt_decoder_function pt_decode_mode = {
115 	/* .packet = */ pt_pkt_decode_mode,
116 	/* .decode = */ pt_qry_decode_mode,
117 	/* .header = */ pt_qry_header_mode,
118 	/* .flags =  */ pdff_event
119 };
120 
121 const struct pt_decoder_function pt_decode_psbend = {
122 	/* .packet = */ pt_pkt_decode_psbend,
123 	/* .decode = */ pt_qry_decode_psbend,
124 	/* .header = */ NULL,
125 	/* .flags =  */ pdff_psbend
126 };
127 
128 const struct pt_decoder_function pt_decode_tsc = {
129 	/* .packet = */ pt_pkt_decode_tsc,
130 	/* .decode = */ pt_qry_decode_tsc,
131 	/* .header = */ pt_qry_header_tsc,
132 	/* .flags =  */ pdff_timing
133 };
134 
135 const struct pt_decoder_function pt_decode_cbr = {
136 	/* .packet = */ pt_pkt_decode_cbr,
137 	/* .decode = */ pt_qry_decode_cbr,
138 	/* .header = */ pt_qry_header_cbr,
139 	/* .flags =  */ pdff_timing | pdff_event
140 };
141 
142 const struct pt_decoder_function pt_decode_tma = {
143 	/* .packet = */ pt_pkt_decode_tma,
144 	/* .decode = */ pt_qry_decode_tma,
145 	/* .header = */ pt_qry_decode_tma,
146 	/* .flags =  */ pdff_timing
147 };
148 
149 const struct pt_decoder_function pt_decode_mtc = {
150 	/* .packet = */ pt_pkt_decode_mtc,
151 	/* .decode = */ pt_qry_decode_mtc,
152 	/* .header = */ pt_qry_decode_mtc,
153 	/* .flags =  */ pdff_timing
154 };
155 
156 const struct pt_decoder_function pt_decode_cyc = {
157 	/* .packet = */ pt_pkt_decode_cyc,
158 	/* .decode = */ pt_qry_decode_cyc,
159 	/* .header = */ pt_qry_decode_cyc,
160 	/* .flags =  */ pdff_timing
161 };
162 
163 const struct pt_decoder_function pt_decode_stop = {
164 	/* .packet = */ pt_pkt_decode_stop,
165 	/* .decode = */ pt_qry_decode_stop,
166 	/* .header = */ NULL,
167 	/* .flags =  */ pdff_event
168 };
169 
170 const struct pt_decoder_function pt_decode_vmcs = {
171 	/* .packet = */ pt_pkt_decode_vmcs,
172 	/* .decode = */ pt_qry_decode_vmcs,
173 	/* .header = */ pt_qry_header_vmcs,
174 	/* .flags =  */ pdff_event
175 };
176 
177 const struct pt_decoder_function pt_decode_mnt = {
178 	/* .packet = */ pt_pkt_decode_mnt,
179 	/* .decode = */ pt_qry_decode_mnt,
180 	/* .header = */ pt_qry_header_mnt,
181 	/* .flags =  */ pdff_event
182 };
183 
184 const struct pt_decoder_function pt_decode_exstop = {
185 	/* .packet = */ pt_pkt_decode_exstop,
186 	/* .decode = */ pt_qry_decode_exstop,
187 	/* .header = */ NULL,
188 	/* .flags =  */ pdff_event
189 };
190 
191 const struct pt_decoder_function pt_decode_mwait = {
192 	/* .packet = */ pt_pkt_decode_mwait,
193 	/* .decode = */ pt_qry_decode_mwait,
194 	/* .header = */ NULL,
195 	/* .flags =  */ pdff_event
196 };
197 
198 const struct pt_decoder_function pt_decode_pwre = {
199 	/* .packet = */ pt_pkt_decode_pwre,
200 	/* .decode = */ pt_qry_decode_pwre,
201 	/* .header = */ NULL,
202 	/* .flags =  */ pdff_event
203 };
204 
205 const struct pt_decoder_function pt_decode_pwrx = {
206 	/* .packet = */ pt_pkt_decode_pwrx,
207 	/* .decode = */ pt_qry_decode_pwrx,
208 	/* .header = */ NULL,
209 	/* .flags =  */ pdff_event
210 };
211 
212 const struct pt_decoder_function pt_decode_ptw = {
213 	/* .packet = */ pt_pkt_decode_ptw,
214 	/* .decode = */ pt_qry_decode_ptw,
215 	/* .header = */ NULL,
216 	/* .flags =  */ pdff_event
217 };
218 
219 
220 int pt_df_fetch(const struct pt_decoder_function **dfun, const uint8_t *pos,
221 		const struct pt_config *config)
222 {
223 	const uint8_t *begin, *end;
224 	uint8_t opc, ext, ext2;
225 
226 	if (!dfun || !config)
227 		return -pte_internal;
228 
229 	/* Clear the decode function in case of errors. */
230 	*dfun = NULL;
231 
232 	begin = config->begin;
233 	end = config->end;
234 
235 	if (!pos || (pos < begin) || (end < pos))
236 		return -pte_nosync;
237 
238 	if (pos == end)
239 		return -pte_eos;
240 
241 	opc = *pos++;
242 	switch (opc) {
243 	default:
244 		/* Check opcodes that require masking. */
245 		if ((opc & pt_opm_tnt_8) == pt_opc_tnt_8) {
246 			*dfun = &pt_decode_tnt_8;
247 			return 0;
248 		}
249 
250 		if ((opc & pt_opm_cyc) == pt_opc_cyc) {
251 			*dfun = &pt_decode_cyc;
252 			return 0;
253 		}
254 
255 		if ((opc & pt_opm_tip) == pt_opc_tip) {
256 			*dfun = &pt_decode_tip;
257 			return 0;
258 		}
259 
260 		if ((opc & pt_opm_fup) == pt_opc_fup) {
261 			*dfun = &pt_decode_fup;
262 			return 0;
263 		}
264 
265 		if ((opc & pt_opm_tip) == pt_opc_tip_pge) {
266 			*dfun = &pt_decode_tip_pge;
267 			return 0;
268 		}
269 
270 		if ((opc & pt_opm_tip) == pt_opc_tip_pgd) {
271 			*dfun = &pt_decode_tip_pgd;
272 			return 0;
273 		}
274 
275 		*dfun = &pt_decode_unknown;
276 		return 0;
277 
278 	case pt_opc_pad:
279 		*dfun = &pt_decode_pad;
280 		return 0;
281 
282 	case pt_opc_mode:
283 		*dfun = &pt_decode_mode;
284 		return 0;
285 
286 	case pt_opc_tsc:
287 		*dfun = &pt_decode_tsc;
288 		return 0;
289 
290 	case pt_opc_mtc:
291 		*dfun = &pt_decode_mtc;
292 		return 0;
293 
294 	case pt_opc_ext:
295 		if (pos == end)
296 			return -pte_eos;
297 
298 		ext = *pos++;
299 		switch (ext) {
300 		default:
301 			/* Check opcodes that require masking. */
302 			if ((ext & pt_opm_ptw) == pt_ext_ptw) {
303 				*dfun = &pt_decode_ptw;
304 				return 0;
305 			}
306 
307 			*dfun = &pt_decode_unknown;
308 			return 0;
309 
310 		case pt_ext_psb:
311 			*dfun = &pt_decode_psb;
312 			return 0;
313 
314 		case pt_ext_ovf:
315 			*dfun = &pt_decode_ovf;
316 			return 0;
317 
318 		case pt_ext_tnt_64:
319 			*dfun = &pt_decode_tnt_64;
320 			return 0;
321 
322 		case pt_ext_psbend:
323 			*dfun = &pt_decode_psbend;
324 			return 0;
325 
326 		case pt_ext_cbr:
327 			*dfun = &pt_decode_cbr;
328 			return 0;
329 
330 		case pt_ext_pip:
331 			*dfun = &pt_decode_pip;
332 			return 0;
333 
334 		case pt_ext_tma:
335 			*dfun = &pt_decode_tma;
336 			return 0;
337 
338 		case pt_ext_stop:
339 			*dfun = &pt_decode_stop;
340 			return 0;
341 
342 		case pt_ext_vmcs:
343 			*dfun = &pt_decode_vmcs;
344 			return 0;
345 
346 		case pt_ext_exstop:
347 		case pt_ext_exstop_ip:
348 			*dfun = &pt_decode_exstop;
349 			return 0;
350 
351 		case pt_ext_mwait:
352 			*dfun = &pt_decode_mwait;
353 			return 0;
354 
355 		case pt_ext_pwre:
356 			*dfun = &pt_decode_pwre;
357 			return 0;
358 
359 		case pt_ext_pwrx:
360 			*dfun = &pt_decode_pwrx;
361 			return 0;
362 
363 		case pt_ext_ext2:
364 			if (pos == end)
365 				return -pte_eos;
366 
367 			ext2 = *pos++;
368 			switch (ext2) {
369 			default:
370 				*dfun = &pt_decode_unknown;
371 				return 0;
372 
373 			case pt_ext2_mnt:
374 				*dfun = &pt_decode_mnt;
375 				return 0;
376 			}
377 		}
378 	}
379 }
380