1 /*
2  * Copyright (c) 2013-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 "ptunit.h"
30 
31 #include "pt_last_ip.h"
32 
33 #include "intel-pt.h"
34 
35 #include <string.h>
36 
37 
38 static 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 
53 static struct ptunit_result init_null(void)
54 {
55 	pt_last_ip_init(NULL);
56 
57 	return ptu_passed();
58 }
59 
60 static 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 
73 static 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 
87 static 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 
97 static 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 
111 static 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 
125 static 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 
139 static 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 
156 static 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 
168 static 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 
185 static 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 
202 static 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 
224 static 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 
246 static 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 
268 static 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 
290 static 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 
312 static 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 
323 static 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 
341 int 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