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 "ptunit.h"
30
31#include "pt_last_ip.h"
32
33#include "intel-pt.h"
34
35#include <string.h>
36
37
38static struct ptunit_result init(void)
39{
40	struct pt_last_ip last_ip;
41
42	memset(&last_ip, 0xcd, sizeof(last_ip));
43
44	pt_last_ip_init(&last_ip);
45
46	ptu_uint_eq(last_ip.ip, 0ull);
47	ptu_uint_eq(last_ip.have_ip, 0);
48	ptu_uint_eq(last_ip.suppressed, 0);
49
50	return ptu_passed();
51}
52
53static struct ptunit_result init_null(void)
54{
55	pt_last_ip_init(NULL);
56
57	return ptu_passed();
58}
59
60static struct ptunit_result status_initial(void)
61{
62	struct pt_last_ip last_ip;
63	int errcode;
64
65	pt_last_ip_init(&last_ip);
66
67	errcode = pt_last_ip_query(NULL, &last_ip);
68	ptu_int_eq(errcode, -pte_noip);
69
70	return ptu_passed();
71}
72
73static struct ptunit_result status(void)
74{
75	struct pt_last_ip last_ip;
76	int errcode;
77
78	last_ip.have_ip = 1;
79	last_ip.suppressed = 0;
80
81	errcode = pt_last_ip_query(NULL, &last_ip);
82	ptu_int_eq(errcode, 0);
83
84	return ptu_passed();
85}
86
87static struct ptunit_result status_null(void)
88{
89	int errcode;
90
91	errcode = pt_last_ip_query(NULL, NULL);
92	ptu_int_eq(errcode, -pte_internal);
93
94	return ptu_passed();
95}
96
97static struct ptunit_result status_noip(void)
98{
99	struct pt_last_ip last_ip;
100	int errcode;
101
102	last_ip.have_ip = 0;
103	last_ip.suppressed = 0;
104
105	errcode = pt_last_ip_query(NULL, &last_ip);
106	ptu_int_eq(errcode, -pte_noip);
107
108	return ptu_passed();
109}
110
111static struct ptunit_result status_suppressed(void)
112{
113	struct pt_last_ip last_ip;
114	int errcode;
115
116	last_ip.have_ip = 1;
117	last_ip.suppressed = 1;
118
119	errcode = pt_last_ip_query(NULL, &last_ip);
120	ptu_int_eq(errcode, -pte_ip_suppressed);
121
122	return ptu_passed();
123}
124
125static struct ptunit_result query_initial(void)
126{
127	struct pt_last_ip last_ip;
128	uint64_t ip;
129	int errcode;
130
131	pt_last_ip_init(&last_ip);
132
133	errcode = pt_last_ip_query(&ip, &last_ip);
134	ptu_int_eq(errcode, -pte_noip);
135
136	return ptu_passed();
137}
138
139static struct ptunit_result query(void)
140{
141	struct pt_last_ip last_ip;
142	uint64_t ip, exp = 42ull;
143	int errcode;
144
145	last_ip.ip = 42ull;
146	last_ip.have_ip = 1;
147	last_ip.suppressed = 0;
148
149	errcode = pt_last_ip_query(&ip, &last_ip);
150	ptu_int_eq(errcode, 0);
151	ptu_uint_eq(last_ip.ip, exp);
152
153	return ptu_passed();
154}
155
156static struct ptunit_result query_null(void)
157{
158	uint64_t ip = 13ull;
159	int errcode;
160
161	errcode = pt_last_ip_query(&ip, NULL);
162	ptu_int_eq(errcode, -pte_internal);
163	ptu_uint_eq(ip, 13ull);
164
165	return ptu_passed();
166}
167
168static struct ptunit_result query_noip(void)
169{
170	struct pt_last_ip last_ip;
171	uint64_t ip = 13ull;
172	int errcode;
173
174	last_ip.ip = 42ull;
175	last_ip.have_ip = 0;
176	last_ip.suppressed = 0;
177
178	errcode = pt_last_ip_query(&ip, &last_ip);
179	ptu_int_eq(errcode, -pte_noip);
180	ptu_uint_eq(ip, 0ull);
181
182	return ptu_passed();
183}
184
185static struct ptunit_result query_suppressed(void)
186{
187	struct pt_last_ip last_ip;
188	uint64_t ip = 13ull;
189	int errcode;
190
191	last_ip.ip = 42ull;
192	last_ip.have_ip = 1;
193	last_ip.suppressed = 1;
194
195	errcode = pt_last_ip_query(&ip, &last_ip);
196	ptu_int_eq(errcode, -pte_ip_suppressed);
197	ptu_uint_eq(ip, 0ull);
198
199	return ptu_passed();
200}
201
202static struct ptunit_result update_ip_suppressed(uint32_t have_ip)
203{
204	struct pt_last_ip last_ip;
205	struct pt_packet_ip packet;
206	int errcode;
207
208	last_ip.ip = 42ull;
209	last_ip.have_ip = have_ip;
210	last_ip.suppressed = 0;
211
212	packet.ipc = pt_ipc_suppressed;
213	packet.ip = 13ull;
214
215	errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
216	ptu_int_eq(errcode, 0);
217	ptu_uint_eq(last_ip.ip, 42ull);
218	ptu_uint_eq(last_ip.have_ip, have_ip);
219	ptu_uint_eq(last_ip.suppressed, 1);
220
221	return ptu_passed();
222}
223
224static struct ptunit_result update_ip_upd16(uint32_t have_ip)
225{
226	struct pt_last_ip last_ip;
227	struct pt_packet_ip packet;
228	int errcode;
229
230	last_ip.ip = 0xff0042ull;
231	last_ip.have_ip = have_ip;
232	last_ip.suppressed = 0;
233
234	packet.ipc = pt_ipc_update_16;
235	packet.ip = 0xccc013ull;
236
237	errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
238	ptu_int_eq(errcode, 0);
239	ptu_uint_eq(last_ip.ip, 0xffc013ull);
240	ptu_uint_eq(last_ip.have_ip, 1);
241	ptu_uint_eq(last_ip.suppressed, 0);
242
243	return ptu_passed();
244}
245
246static struct ptunit_result update_ip_upd32(uint32_t have_ip)
247{
248	struct pt_last_ip last_ip;
249	struct pt_packet_ip packet;
250	int errcode;
251
252	last_ip.ip = 0xff00000420ull;
253	last_ip.have_ip = have_ip;
254	last_ip.suppressed = 0;
255
256	packet.ipc = pt_ipc_update_32;
257	packet.ip = 0xcc0000c013ull;
258
259	errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
260	ptu_int_eq(errcode, 0);
261	ptu_uint_eq(last_ip.ip, 0xff0000c013ull);
262	ptu_uint_eq(last_ip.have_ip, 1);
263	ptu_uint_eq(last_ip.suppressed, 0);
264
265	return ptu_passed();
266}
267
268static struct ptunit_result update_ip_sext48(uint32_t have_ip)
269{
270	struct pt_last_ip last_ip;
271	struct pt_packet_ip packet;
272	int errcode;
273
274	last_ip.ip = 0x7fffffffffffffffull;
275	last_ip.have_ip = have_ip;
276	last_ip.suppressed = 0;
277
278	packet.ipc = pt_ipc_sext_48;
279	packet.ip = 0xff00000000ffull;
280
281	errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
282	ptu_int_eq(errcode, 0);
283	ptu_uint_eq(last_ip.ip, 0xffffff00000000ffull);
284	ptu_uint_eq(last_ip.have_ip, 1);
285	ptu_uint_eq(last_ip.suppressed, 0);
286
287	return ptu_passed();
288}
289
290static struct ptunit_result update_ip_bad_packet(uint32_t have_ip)
291{
292	struct pt_last_ip last_ip;
293	struct pt_packet_ip packet;
294	int errcode;
295
296	last_ip.ip = 0x7fffffffffffffffull;
297	last_ip.have_ip = have_ip;
298	last_ip.suppressed = 0;
299
300	packet.ipc = (enum pt_ip_compression) 0xff;
301	packet.ip = 0ull;
302
303	errcode = pt_last_ip_update_ip(&last_ip, &packet, NULL);
304	ptu_int_eq(errcode, -pte_bad_packet);
305	ptu_uint_eq(last_ip.ip, 0x7fffffffffffffffull);
306	ptu_uint_eq(last_ip.have_ip, have_ip);
307	ptu_uint_eq(last_ip.suppressed, 0);
308
309	return ptu_passed();
310}
311
312static struct ptunit_result update_ip_null_ip(void)
313{
314	struct pt_packet_ip packet;
315	int errcode;
316
317	errcode = pt_last_ip_update_ip(NULL, &packet, NULL);
318	ptu_int_eq(errcode, -pte_internal);
319
320	return ptu_passed();
321}
322
323static struct ptunit_result update_ip_null_packet(uint32_t have_ip)
324{
325	struct pt_last_ip last_ip;
326	int errcode;
327
328	last_ip.ip = 0x7fffffffffffffffull;
329	last_ip.have_ip = have_ip;
330	last_ip.suppressed = 0;
331
332	errcode = pt_last_ip_update_ip(&last_ip, NULL, NULL);
333	ptu_int_eq(errcode, -pte_internal);
334	ptu_uint_eq(last_ip.ip, 0x7fffffffffffffffull);
335	ptu_uint_eq(last_ip.have_ip, have_ip);
336	ptu_uint_eq(last_ip.suppressed, 0);
337
338	return ptu_passed();
339}
340
341int main(int argc, char **argv)
342{
343	struct ptunit_suite suite;
344
345	suite = ptunit_mk_suite(argc, argv);
346
347	ptu_run(suite, init);
348	ptu_run(suite, init_null);
349	ptu_run(suite, status_initial);
350	ptu_run(suite, status);
351	ptu_run(suite, status_null);
352	ptu_run(suite, status_noip);
353	ptu_run(suite, status_suppressed);
354	ptu_run(suite, query_initial);
355	ptu_run(suite, query);
356	ptu_run(suite, query_null);
357	ptu_run(suite, query_noip);
358	ptu_run(suite, query_suppressed);
359	ptu_run_p(suite, update_ip_suppressed, 0);
360	ptu_run_p(suite, update_ip_suppressed, 1);
361	ptu_run_p(suite, update_ip_upd16, 0);
362	ptu_run_p(suite, update_ip_upd16, 1);
363	ptu_run_p(suite, update_ip_upd32, 0);
364	ptu_run_p(suite, update_ip_upd32, 1);
365	ptu_run_p(suite, update_ip_sext48, 0);
366	ptu_run_p(suite, update_ip_sext48, 1);
367	ptu_run_p(suite, update_ip_bad_packet, 0);
368	ptu_run_p(suite, update_ip_bad_packet, 1);
369	ptu_run(suite, update_ip_null_ip);
370	ptu_run_p(suite, update_ip_null_packet, 0);
371	ptu_run_p(suite, update_ip_null_packet, 1);
372
373	return ptunit_report(&suite);
374}
375