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
37const 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
44const 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
51const 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
58const 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
65const 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
72const 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
79const 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
86const 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
93const 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
100const 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
107const 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
114const 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
121const 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
128const 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
135const 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
142const 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
149const 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
156const 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
163const 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
170const 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
177const 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
184const 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
191const 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
198const 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
205const 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
212const 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
220int 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