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
from_user_null(void)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
from_user_default(void)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
from_user_small(void)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
from_user_big(void)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
from_user(void)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
from_user_cr3(void)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
to_user_null(void)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
to_user_too_small(void)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
to_user_small(void)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
to_user_big(void)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
to_user(void)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
to_user_cr3(void)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
match_null(void)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
match_default(void)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
match_default_mixed(void)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
match_cr3(void)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
match_vmcs(void)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
match(void)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
match_cr3_false(void)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
match_vmcs_false(void)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
main(int argc,char ** argv)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