1 /*
2  * Copyright (c) 2014-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_asid.h"
32 
33 #include "intel-pt.h"
34 
35 #include <stddef.h>
36 
37 
38 static struct ptunit_result from_user_null(void)
39 {
40 	struct pt_asid user;
41 	int errcode;
42 
43 	pt_asid_init(&user);
44 
45 	errcode = pt_asid_from_user(NULL, NULL);
46 	ptu_int_eq(errcode, -pte_internal);
47 
48 	errcode = pt_asid_from_user(NULL, &user);
49 	ptu_int_eq(errcode, -pte_internal);
50 
51 	return ptu_passed();
52 }
53 
54 static struct ptunit_result from_user_default(void)
55 {
56 	struct pt_asid asid;
57 	int errcode;
58 
59 	errcode = pt_asid_from_user(&asid, NULL);
60 	ptu_int_eq(errcode, 0);
61 	ptu_uint_eq(asid.size, sizeof(asid));
62 	ptu_uint_eq(asid.cr3, pt_asid_no_cr3);
63 	ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
64 
65 	return ptu_passed();
66 }
67 
68 static struct ptunit_result from_user_small(void)
69 {
70 	struct pt_asid asid, user;
71 	int errcode;
72 
73 	user.size = sizeof(user.size);
74 
75 	errcode = pt_asid_from_user(&asid, &user);
76 	ptu_int_eq(errcode, 0);
77 	ptu_uint_eq(asid.size, sizeof(asid));
78 	ptu_uint_eq(asid.cr3, pt_asid_no_cr3);
79 	ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
80 
81 	return ptu_passed();
82 }
83 
84 static struct ptunit_result from_user_big(void)
85 {
86 	struct pt_asid asid, user;
87 	int errcode;
88 
89 	user.size = sizeof(user) + 4;
90 	user.cr3 = 0x4200ull;
91 	user.vmcs = 0x23000ull;
92 
93 	errcode = pt_asid_from_user(&asid, &user);
94 	ptu_int_eq(errcode, 0);
95 	ptu_uint_eq(asid.size, sizeof(asid));
96 	ptu_uint_eq(asid.cr3, 0x4200ull);
97 	ptu_uint_eq(asid.vmcs, 0x23000ull);
98 
99 	return ptu_passed();
100 }
101 
102 static struct ptunit_result from_user(void)
103 {
104 	struct pt_asid asid, user;
105 	int errcode;
106 
107 	user.size = sizeof(user);
108 	user.cr3 = 0x4200ull;
109 	user.vmcs = 0x23000ull;
110 
111 	errcode = pt_asid_from_user(&asid, &user);
112 	ptu_int_eq(errcode, 0);
113 	ptu_uint_eq(asid.size, sizeof(asid));
114 	ptu_uint_eq(asid.cr3, 0x4200ull);
115 	ptu_uint_eq(asid.vmcs, 0x23000ull);
116 
117 	return ptu_passed();
118 }
119 
120 static struct ptunit_result from_user_cr3(void)
121 {
122 	struct pt_asid asid, user;
123 	int errcode;
124 
125 	user.size = offsetof(struct pt_asid, vmcs);
126 	user.cr3 = 0x4200ull;
127 	user.vmcs = 0x23000ull;
128 
129 	errcode = pt_asid_from_user(&asid, &user);
130 	ptu_int_eq(errcode, 0);
131 	ptu_uint_eq(asid.size, sizeof(asid));
132 	ptu_uint_eq(asid.cr3, 0x4200ull);
133 	ptu_uint_eq(asid.vmcs, pt_asid_no_vmcs);
134 
135 	return ptu_passed();
136 }
137 
138 static struct ptunit_result to_user_null(void)
139 {
140 	struct pt_asid asid;
141 	int errcode;
142 
143 	pt_asid_init(&asid);
144 
145 	errcode = pt_asid_to_user(NULL, NULL, sizeof(asid));
146 	ptu_int_eq(errcode, -pte_internal);
147 
148 	errcode = pt_asid_to_user(NULL, &asid, sizeof(asid));
149 	ptu_int_eq(errcode, -pte_internal);
150 
151 	return ptu_passed();
152 }
153 
154 static struct ptunit_result to_user_too_small(void)
155 {
156 	struct pt_asid asid, user;
157 	int errcode;
158 
159 	pt_asid_init(&asid);
160 
161 	errcode = pt_asid_to_user(&user, &asid, 0);
162 	ptu_int_eq(errcode, -pte_invalid);
163 
164 	errcode = pt_asid_to_user(&user, &asid, sizeof(user.size) - 1);
165 	ptu_int_eq(errcode, -pte_invalid);
166 
167 	return ptu_passed();
168 }
169 
170 static struct ptunit_result to_user_small(void)
171 {
172 	struct pt_asid asid, user;
173 	int errcode;
174 
175 	memset(&user, 0xcc, sizeof(user));
176 	pt_asid_init(&asid);
177 
178 	errcode = pt_asid_to_user(&user, &asid, sizeof(user.size));
179 	ptu_int_eq(errcode, 0);
180 	ptu_uint_eq(user.size, sizeof(user.size));
181 	ptu_uint_eq(user.cr3, 0xccccccccccccccccull);
182 	ptu_uint_eq(user.vmcs, 0xccccccccccccccccull);
183 
184 	return ptu_passed();
185 }
186 
187 static struct ptunit_result to_user_big(void)
188 {
189 	struct pt_asid asid, user;
190 	int errcode;
191 
192 	memset(&user, 0xcc, sizeof(user));
193 	pt_asid_init(&asid);
194 	asid.cr3 = 0x4200ull;
195 	asid.vmcs = 0x23000ull;
196 
197 	errcode = pt_asid_to_user(&user, &asid, sizeof(user) + 8);
198 	ptu_int_eq(errcode, 0);
199 	ptu_uint_eq(user.size, sizeof(asid));
200 	ptu_uint_eq(user.cr3, 0x4200ull);
201 	ptu_uint_eq(user.vmcs, 0x23000ull);
202 
203 	return ptu_passed();
204 }
205 
206 static struct ptunit_result to_user(void)
207 {
208 	struct pt_asid asid, user;
209 	int errcode;
210 
211 	memset(&user, 0xcc, sizeof(user));
212 	pt_asid_init(&asid);
213 	asid.cr3 = 0x4200ull;
214 	asid.vmcs = 0x23000ull;
215 
216 	errcode = pt_asid_to_user(&user, &asid, sizeof(user));
217 	ptu_int_eq(errcode, 0);
218 	ptu_uint_eq(user.size, sizeof(asid));
219 	ptu_uint_eq(user.cr3, 0x4200ull);
220 	ptu_uint_eq(user.vmcs, 0x23000ull);
221 
222 	return ptu_passed();
223 }
224 
225 static struct ptunit_result to_user_cr3(void)
226 {
227 	struct pt_asid asid, user;
228 	int errcode;
229 
230 	memset(&user, 0xcc, sizeof(user));
231 	pt_asid_init(&asid);
232 	asid.cr3 = 0x4200ull;
233 
234 	errcode = pt_asid_to_user(&user, &asid, offsetof(struct pt_asid, vmcs));
235 	ptu_int_eq(errcode, 0);
236 	ptu_uint_eq(user.size, offsetof(struct pt_asid, vmcs));
237 	ptu_uint_eq(user.cr3, 0x4200ull);
238 	ptu_uint_eq(user.vmcs, 0xccccccccccccccccull);
239 
240 	return ptu_passed();
241 }
242 
243 static struct ptunit_result match_null(void)
244 {
245 	struct pt_asid asid;
246 	int errcode;
247 
248 	pt_asid_init(&asid);
249 
250 	errcode = pt_asid_match(NULL, NULL);
251 	ptu_int_eq(errcode, -pte_internal);
252 
253 	errcode = pt_asid_match(NULL, &asid);
254 	ptu_int_eq(errcode, -pte_internal);
255 
256 	errcode = pt_asid_match(&asid, NULL);
257 	ptu_int_eq(errcode, -pte_internal);
258 
259 	return ptu_passed();
260 }
261 
262 static struct ptunit_result match_default(void)
263 {
264 	struct pt_asid lhs, rhs;
265 	int errcode;
266 
267 	pt_asid_init(&lhs);
268 	pt_asid_init(&rhs);
269 
270 	errcode = pt_asid_match(&lhs, &rhs);
271 	ptu_int_eq(errcode, 1);
272 
273 	lhs.cr3 = 0x2300ull;
274 	lhs.vmcs = 0x42000ull;
275 
276 	errcode = pt_asid_match(&lhs, &rhs);
277 	ptu_int_eq(errcode, 1);
278 
279 	errcode = pt_asid_match(&rhs, &lhs);
280 	ptu_int_eq(errcode, 1);
281 
282 	return ptu_passed();
283 }
284 
285 static struct ptunit_result match_default_mixed(void)
286 {
287 	struct pt_asid lhs, rhs;
288 	int errcode;
289 
290 	pt_asid_init(&lhs);
291 	pt_asid_init(&rhs);
292 
293 	errcode = pt_asid_match(&lhs, &rhs);
294 	ptu_int_eq(errcode, 1);
295 
296 	lhs.cr3 = 0x2300ull;
297 	rhs.vmcs = 0x42000ull;
298 
299 	errcode = pt_asid_match(&lhs, &rhs);
300 	ptu_int_eq(errcode, 1);
301 
302 	errcode = pt_asid_match(&rhs, &lhs);
303 	ptu_int_eq(errcode, 1);
304 
305 	return ptu_passed();
306 }
307 
308 static struct ptunit_result match_cr3(void)
309 {
310 	struct pt_asid lhs, rhs;
311 	int errcode;
312 
313 	pt_asid_init(&lhs);
314 	pt_asid_init(&rhs);
315 
316 	lhs.cr3 = 0x2300ull;
317 	rhs.cr3 = 0x2300ull;
318 
319 	errcode = pt_asid_match(&lhs, &rhs);
320 	ptu_int_eq(errcode, 1);
321 
322 	return ptu_passed();
323 }
324 
325 static struct ptunit_result match_vmcs(void)
326 {
327 	struct pt_asid lhs, rhs;
328 	int errcode;
329 
330 	pt_asid_init(&lhs);
331 	pt_asid_init(&rhs);
332 
333 	lhs.vmcs = 0x23000ull;
334 	rhs.vmcs = 0x23000ull;
335 
336 	errcode = pt_asid_match(&lhs, &rhs);
337 	ptu_int_eq(errcode, 1);
338 
339 	return ptu_passed();
340 }
341 
342 static struct ptunit_result match(void)
343 {
344 	struct pt_asid lhs, rhs;
345 	int errcode;
346 
347 	pt_asid_init(&lhs);
348 	pt_asid_init(&rhs);
349 
350 	lhs.cr3 = 0x2300ull;
351 	rhs.cr3 = 0x2300ull;
352 	lhs.vmcs = 0x23000ull;
353 	rhs.vmcs = 0x23000ull;
354 
355 	errcode = pt_asid_match(&lhs, &rhs);
356 	ptu_int_eq(errcode, 1);
357 
358 	return ptu_passed();
359 }
360 
361 static struct ptunit_result match_cr3_false(void)
362 {
363 	struct pt_asid lhs, rhs;
364 	int errcode;
365 
366 	pt_asid_init(&lhs);
367 	pt_asid_init(&rhs);
368 
369 	lhs.cr3 = 0x4200ull;
370 	rhs.cr3 = 0x2300ull;
371 
372 	errcode = pt_asid_match(&lhs, &rhs);
373 	ptu_int_eq(errcode, 0);
374 
375 	return ptu_passed();
376 }
377 
378 static struct ptunit_result match_vmcs_false(void)
379 {
380 	struct pt_asid lhs, rhs;
381 	int errcode;
382 
383 	pt_asid_init(&lhs);
384 	pt_asid_init(&rhs);
385 
386 	lhs.vmcs = 0x42000ull;
387 	rhs.vmcs = 0x23000ull;
388 
389 	errcode = pt_asid_match(&lhs, &rhs);
390 	ptu_int_eq(errcode, 0);
391 
392 	return ptu_passed();
393 }
394 
395 int main(int argc, char **argv)
396 {
397 	struct ptunit_suite suite;
398 
399 	suite = ptunit_mk_suite(argc, argv);
400 
401 	ptu_run(suite, from_user_null);
402 	ptu_run(suite, from_user_default);
403 	ptu_run(suite, from_user_small);
404 	ptu_run(suite, from_user_big);
405 	ptu_run(suite, from_user);
406 	ptu_run(suite, from_user_cr3);
407 
408 	ptu_run(suite, to_user_null);
409 	ptu_run(suite, to_user_too_small);
410 	ptu_run(suite, to_user_small);
411 	ptu_run(suite, to_user_big);
412 	ptu_run(suite, to_user);
413 	ptu_run(suite, to_user_cr3);
414 
415 	ptu_run(suite, match_null);
416 	ptu_run(suite, match_default);
417 	ptu_run(suite, match_default_mixed);
418 	ptu_run(suite, match_cr3);
419 	ptu_run(suite, match_vmcs);
420 	ptu_run(suite, match);
421 	ptu_run(suite, match_cr3_false);
422 	ptu_run(suite, match_vmcs_false);
423 
424 	return ptunit_report(&suite);
425 }
426