1 /*
2 * Copyright (c) 2016-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_image_section_cache.h"
30
31 #include "ptunit_threads.h"
32
33 #include "intel-pt.h"
34
35 #include <stdlib.h>
36
37
38 struct pt_section {
39 /* The filename. We only support string literals for testing. */
40 const char *filename;
41
42 /* The file offset and size. */
43 uint64_t offset;
44 uint64_t size;
45
46 /* The bcache size. */
47 uint64_t bcsize;
48
49 /* The iscache back link. */
50 struct pt_image_section_cache *iscache;
51
52 /* The file content. */
53 uint8_t content[0x10];
54
55 /* The use count. */
56 int ucount;
57
58 /* The attach count. */
59 int acount;
60
61 /* The map count. */
62 int mcount;
63
64 #if defined(FEATURE_THREADS)
65 /* A lock protecting this section. */
66 mtx_t lock;
67 /* A lock protecting the iscache and acount fields. */
68 mtx_t alock;
69 #endif /* defined(FEATURE_THREADS) */
70 };
71
72 extern int pt_mk_section(struct pt_section **psection, const char *filename,
73 uint64_t offset, uint64_t size);
74
75 extern int pt_section_get(struct pt_section *section);
76 extern int pt_section_put(struct pt_section *section);
77 extern int pt_section_attach(struct pt_section *section,
78 struct pt_image_section_cache *iscache);
79 extern int pt_section_detach(struct pt_section *section,
80 struct pt_image_section_cache *iscache);
81
82 extern int pt_section_map(struct pt_section *section);
83 extern int pt_section_map_share(struct pt_section *section);
84 extern int pt_section_unmap(struct pt_section *section);
85 extern int pt_section_request_bcache(struct pt_section *section);
86
87 extern const char *pt_section_filename(const struct pt_section *section);
88 extern uint64_t pt_section_offset(const struct pt_section *section);
89 extern uint64_t pt_section_size(const struct pt_section *section);
90 extern int pt_section_memsize(struct pt_section *section, uint64_t *size);
91
92 extern int pt_section_read(const struct pt_section *section, uint8_t *buffer,
93 uint16_t size, uint64_t offset);
94
95
pt_mk_section(struct pt_section ** psection,const char * filename,uint64_t offset,uint64_t size)96 int pt_mk_section(struct pt_section **psection, const char *filename,
97 uint64_t offset, uint64_t size)
98 {
99 struct pt_section *section;
100 uint8_t idx;
101
102 section = malloc(sizeof(*section));
103 if (!section)
104 return -pte_nomem;
105
106 memset(section, 0, sizeof(*section));
107 section->filename = filename;
108 section->offset = offset;
109 section->size = size;
110 section->ucount = 1;
111
112 for (idx = 0; idx < sizeof(section->content); ++idx)
113 section->content[idx] = idx;
114
115 #if defined(FEATURE_THREADS)
116 {
117 int errcode;
118
119 errcode = mtx_init(§ion->lock, mtx_plain);
120 if (errcode != thrd_success) {
121 free(section);
122 return -pte_bad_lock;
123 }
124
125 errcode = mtx_init(§ion->alock, mtx_plain);
126 if (errcode != thrd_success) {
127 mtx_destroy(§ion->lock);
128 free(section);
129 return -pte_bad_lock;
130 }
131 }
132 #endif /* defined(FEATURE_THREADS) */
133
134 *psection = section;
135
136 return 0;
137 }
138
pt_section_lock(struct pt_section * section)139 static int pt_section_lock(struct pt_section *section)
140 {
141 if (!section)
142 return -pte_internal;
143
144 #if defined(FEATURE_THREADS)
145 {
146 int errcode;
147
148 errcode = mtx_lock(§ion->lock);
149 if (errcode != thrd_success)
150 return -pte_bad_lock;
151 }
152 #endif /* defined(FEATURE_THREADS) */
153
154 return 0;
155 }
156
pt_section_unlock(struct pt_section * section)157 static int pt_section_unlock(struct pt_section *section)
158 {
159 if (!section)
160 return -pte_internal;
161
162 #if defined(FEATURE_THREADS)
163 {
164 int errcode;
165
166 errcode = mtx_unlock(§ion->lock);
167 if (errcode != thrd_success)
168 return -pte_bad_lock;
169 }
170 #endif /* defined(FEATURE_THREADS) */
171
172 return 0;
173 }
174
pt_section_lock_attach(struct pt_section * section)175 static int pt_section_lock_attach(struct pt_section *section)
176 {
177 if (!section)
178 return -pte_internal;
179
180 #if defined(FEATURE_THREADS)
181 {
182 int errcode;
183
184 errcode = mtx_lock(§ion->alock);
185 if (errcode != thrd_success)
186 return -pte_bad_lock;
187 }
188 #endif /* defined(FEATURE_THREADS) */
189
190 return 0;
191 }
192
pt_section_unlock_attach(struct pt_section * section)193 static int pt_section_unlock_attach(struct pt_section *section)
194 {
195 if (!section)
196 return -pte_internal;
197
198 #if defined(FEATURE_THREADS)
199 {
200 int errcode;
201
202 errcode = mtx_unlock(§ion->alock);
203 if (errcode != thrd_success)
204 return -pte_bad_lock;
205 }
206 #endif /* defined(FEATURE_THREADS) */
207
208 return 0;
209 }
210
pt_section_get(struct pt_section * section)211 int pt_section_get(struct pt_section *section)
212 {
213 int errcode, ucount;
214
215 if (!section)
216 return -pte_internal;
217
218 errcode = pt_section_lock(section);
219 if (errcode < 0)
220 return errcode;
221
222 ucount = ++section->ucount;
223
224 errcode = pt_section_unlock(section);
225 if (errcode < 0)
226 return errcode;
227
228 if (!ucount)
229 return -pte_internal;
230
231 return 0;
232 }
233
pt_section_put(struct pt_section * section)234 int pt_section_put(struct pt_section *section)
235 {
236 int errcode, ucount;
237
238 if (!section)
239 return -pte_internal;
240
241 errcode = pt_section_lock(section);
242 if (errcode < 0)
243 return errcode;
244
245 ucount = --section->ucount;
246
247 errcode = pt_section_unlock(section);
248 if (errcode < 0)
249 return errcode;
250
251 if (!ucount) {
252 #if defined(FEATURE_THREADS)
253 mtx_destroy(§ion->alock);
254 mtx_destroy(§ion->lock);
255 #endif /* defined(FEATURE_THREADS) */
256 free(section);
257 }
258
259 return 0;
260 }
261
pt_section_attach(struct pt_section * section,struct pt_image_section_cache * iscache)262 int pt_section_attach(struct pt_section *section,
263 struct pt_image_section_cache *iscache)
264 {
265 int errcode, ucount, acount;
266
267 if (!section || !iscache)
268 return -pte_internal;
269
270 errcode = pt_section_lock_attach(section);
271 if (errcode < 0)
272 return errcode;
273
274 ucount = section->ucount;
275 acount = section->acount;
276 if (!acount) {
277 if (section->iscache || !ucount)
278 goto out_unlock;
279
280 section->iscache = iscache;
281 section->acount = 1;
282
283 return pt_section_unlock_attach(section);
284 }
285
286 acount += 1;
287 if (!acount) {
288 (void) pt_section_unlock_attach(section);
289 return -pte_overflow;
290 }
291
292 if (ucount < acount)
293 goto out_unlock;
294
295 if (section->iscache != iscache)
296 goto out_unlock;
297
298 section->acount = acount;
299
300 return pt_section_unlock_attach(section);
301
302 out_unlock:
303 (void) pt_section_unlock_attach(section);
304 return -pte_internal;
305 }
306
pt_section_detach(struct pt_section * section,struct pt_image_section_cache * iscache)307 int pt_section_detach(struct pt_section *section,
308 struct pt_image_section_cache *iscache)
309 {
310 int errcode, ucount, acount;
311
312 if (!section || !iscache)
313 return -pte_internal;
314
315 errcode = pt_section_lock_attach(section);
316 if (errcode < 0)
317 return errcode;
318
319 if (section->iscache != iscache)
320 goto out_unlock;
321
322 acount = section->acount;
323 if (!acount)
324 goto out_unlock;
325
326 acount -= 1;
327 ucount = section->ucount;
328 if (ucount < acount)
329 goto out_unlock;
330
331 section->acount = acount;
332 if (!acount)
333 section->iscache = NULL;
334
335 return pt_section_unlock_attach(section);
336
337 out_unlock:
338 (void) pt_section_unlock_attach(section);
339 return -pte_internal;
340 }
341
pt_section_map(struct pt_section * section)342 int pt_section_map(struct pt_section *section)
343 {
344 struct pt_image_section_cache *iscache;
345 int errcode, status;
346
347 if (!section)
348 return -pte_internal;
349
350 errcode = pt_section_map_share(section);
351 if (errcode < 0)
352 return errcode;
353
354 errcode = pt_section_lock_attach(section);
355 if (errcode < 0)
356 return errcode;
357
358 status = 0;
359 iscache = section->iscache;
360 if (iscache)
361 status = pt_iscache_notify_map(iscache, section);
362
363 errcode = pt_section_unlock_attach(section);
364
365 return (status < 0) ? status : errcode;
366 }
367
pt_section_map_share(struct pt_section * section)368 int pt_section_map_share(struct pt_section *section)
369 {
370 int errcode, mcount;
371
372 if (!section)
373 return -pte_internal;
374
375 errcode = pt_section_lock(section);
376 if (errcode < 0)
377 return errcode;
378
379 mcount = ++section->mcount;
380
381 errcode = pt_section_unlock(section);
382 if (errcode < 0)
383 return errcode;
384
385 if (mcount <= 0)
386 return -pte_internal;
387
388 return 0;
389 }
390
pt_section_unmap(struct pt_section * section)391 int pt_section_unmap(struct pt_section *section)
392 {
393 int errcode, mcount;
394
395 if (!section)
396 return -pte_internal;
397
398 errcode = pt_section_lock(section);
399 if (errcode < 0)
400 return errcode;
401
402 section->bcsize = 0ull;
403 mcount = --section->mcount;
404
405 errcode = pt_section_unlock(section);
406 if (errcode < 0)
407 return errcode;
408
409 if (mcount < 0)
410 return -pte_internal;
411
412 return 0;
413 }
414
pt_section_request_bcache(struct pt_section * section)415 int pt_section_request_bcache(struct pt_section *section)
416 {
417 struct pt_image_section_cache *iscache;
418 uint64_t memsize;
419 int errcode;
420
421 if (!section)
422 return -pte_internal;
423
424 errcode = pt_section_lock_attach(section);
425 if (errcode < 0)
426 return errcode;
427
428 errcode = pt_section_lock(section);
429 if (errcode < 0)
430 goto out_alock;
431
432 if (section->bcsize)
433 goto out_lock;
434
435 section->bcsize = section->size * 3;
436 memsize = section->size + section->bcsize;
437
438 errcode = pt_section_unlock(section);
439 if (errcode < 0)
440 goto out_alock;
441
442 iscache = section->iscache;
443 if (iscache) {
444 errcode = pt_iscache_notify_resize(iscache, section, memsize);
445 if (errcode < 0)
446 goto out_alock;
447 }
448
449 return pt_section_unlock_attach(section);
450
451
452 out_lock:
453 (void) pt_section_unlock(section);
454
455 out_alock:
456 (void) pt_section_unlock_attach(section);
457 return errcode;
458 }
459
pt_section_filename(const struct pt_section * section)460 const char *pt_section_filename(const struct pt_section *section)
461 {
462 if (!section)
463 return NULL;
464
465 return section->filename;
466 }
467
pt_section_offset(const struct pt_section * section)468 uint64_t pt_section_offset(const struct pt_section *section)
469 {
470 if (!section)
471 return 0ull;
472
473 return section->offset;
474 }
475
pt_section_size(const struct pt_section * section)476 uint64_t pt_section_size(const struct pt_section *section)
477 {
478 if (!section)
479 return 0ull;
480
481 return section->size;
482 }
483
pt_section_memsize(struct pt_section * section,uint64_t * size)484 int pt_section_memsize(struct pt_section *section, uint64_t *size)
485 {
486 if (!section || !size)
487 return -pte_internal;
488
489 *size = section->mcount ? section->size + section->bcsize : 0ull;
490
491 return 0;
492 }
493
pt_section_read(const struct pt_section * section,uint8_t * buffer,uint16_t size,uint64_t offset)494 int pt_section_read(const struct pt_section *section, uint8_t *buffer,
495 uint16_t size, uint64_t offset)
496 {
497 uint64_t begin, end, max;
498
499 if (!section || !buffer)
500 return -pte_internal;
501
502 begin = offset;
503 end = begin + size;
504 max = sizeof(section->content);
505
506 if (max <= begin)
507 return -pte_nomap;
508
509 if (max < end)
510 end = max;
511
512 if (end <= begin)
513 return -pte_invalid;
514
515 memcpy(buffer, §ion->content[begin], (size_t) (end - begin));
516 return (int) (end - begin);
517 }
518
519 enum {
520 /* The number of test sections. */
521 num_sections = 8,
522
523 #if defined(FEATURE_THREADS)
524
525 num_threads = 8,
526
527 #endif /* defined(FEATURE_THREADS) */
528
529 num_iterations = 0x1000
530 };
531
532 struct iscache_fixture {
533 /* Threading support. */
534 struct ptunit_thrd_fixture thrd;
535
536 /* The image section cache under test. */
537 struct pt_image_section_cache iscache;
538
539 /* A bunch of test sections. */
540 struct pt_section *section[num_sections];
541
542 /* The test fixture initialization and finalization functions. */
543 struct ptunit_result (*init)(struct iscache_fixture *);
544 struct ptunit_result (*fini)(struct iscache_fixture *);
545 };
546
dfix_init(struct iscache_fixture * cfix)547 static struct ptunit_result dfix_init(struct iscache_fixture *cfix)
548 {
549 int idx;
550
551 ptu_test(ptunit_thrd_init, &cfix->thrd);
552
553 memset(cfix->section, 0, sizeof(cfix->section));
554
555 for (idx = 0; idx < num_sections; ++idx) {
556 struct pt_section *section;
557 int errcode;
558
559 errcode = pt_mk_section(§ion, "some-filename",
560 idx % 3 == 0 ? 0x1000 : 0x2000,
561 idx % 2 == 0 ? 0x1000 : 0x2000);
562 ptu_int_eq(errcode, 0);
563 ptu_ptr(section);
564
565 cfix->section[idx] = section;
566 }
567
568 return ptu_passed();
569 }
570
cfix_init(struct iscache_fixture * cfix)571 static struct ptunit_result cfix_init(struct iscache_fixture *cfix)
572 {
573 int errcode;
574
575 ptu_test(dfix_init, cfix);
576
577 errcode = pt_iscache_init(&cfix->iscache, NULL);
578 ptu_int_eq(errcode, 0);
579
580 return ptu_passed();
581 }
582
sfix_init(struct iscache_fixture * cfix)583 static struct ptunit_result sfix_init(struct iscache_fixture *cfix)
584 {
585 int status, idx;
586
587 ptu_test(cfix_init, cfix);
588
589 cfix->iscache.limit = 0x7800;
590
591 for (idx = 0; idx < num_sections; ++idx) {
592 status = pt_iscache_add(&cfix->iscache, cfix->section[idx],
593 0ull);
594 ptu_int_ge(status, 0);
595 }
596
597 return ptu_passed();
598 }
599
cfix_fini(struct iscache_fixture * cfix)600 static struct ptunit_result cfix_fini(struct iscache_fixture *cfix)
601 {
602 int idx, errcode;
603
604 ptu_test(ptunit_thrd_fini, &cfix->thrd);
605
606 for (idx = 0; idx < cfix->thrd.nthreads; ++idx)
607 ptu_int_eq(cfix->thrd.result[idx], 0);
608
609 pt_iscache_fini(&cfix->iscache);
610
611 for (idx = 0; idx < num_sections; ++idx) {
612 ptu_int_eq(cfix->section[idx]->ucount, 1);
613 ptu_int_eq(cfix->section[idx]->acount, 0);
614 ptu_int_eq(cfix->section[idx]->mcount, 0);
615 ptu_null(cfix->section[idx]->iscache);
616
617 errcode = pt_section_put(cfix->section[idx]);
618 ptu_int_eq(errcode, 0);
619 }
620
621 return ptu_passed();
622 }
623
624
init_null(void)625 static struct ptunit_result init_null(void)
626 {
627 int errcode;
628
629 errcode = pt_iscache_init(NULL, NULL);
630 ptu_int_eq(errcode, -pte_internal);
631
632 return ptu_passed();
633 }
634
fini_null(void)635 static struct ptunit_result fini_null(void)
636 {
637 pt_iscache_fini(NULL);
638
639 return ptu_passed();
640 }
641
name_null(void)642 static struct ptunit_result name_null(void)
643 {
644 const char *name;
645
646 name = pt_iscache_name(NULL);
647 ptu_null(name);
648
649 return ptu_passed();
650 }
651
add_null(void)652 static struct ptunit_result add_null(void)
653 {
654 struct pt_image_section_cache iscache;
655 struct pt_section section;
656 int errcode;
657
658 errcode = pt_iscache_add(NULL, §ion, 0ull);
659 ptu_int_eq(errcode, -pte_internal);
660
661 errcode = pt_iscache_add(&iscache, NULL, 0ull);
662 ptu_int_eq(errcode, -pte_internal);
663
664 return ptu_passed();
665 }
666
find_null(void)667 static struct ptunit_result find_null(void)
668 {
669 int errcode;
670
671 errcode = pt_iscache_find(NULL, "filename", 0ull, 0ull, 0ull);
672 ptu_int_eq(errcode, -pte_internal);
673
674 return ptu_passed();
675 }
676
lookup_null(void)677 static struct ptunit_result lookup_null(void)
678 {
679 struct pt_image_section_cache iscache;
680 struct pt_section *section;
681 uint64_t laddr;
682 int errcode;
683
684 errcode = pt_iscache_lookup(NULL, §ion, &laddr, 0);
685 ptu_int_eq(errcode, -pte_internal);
686
687 errcode = pt_iscache_lookup(&iscache, NULL, &laddr, 0);
688 ptu_int_eq(errcode, -pte_internal);
689
690 errcode = pt_iscache_lookup(&iscache, §ion, NULL, 0);
691 ptu_int_eq(errcode, -pte_internal);
692
693 return ptu_passed();
694 }
695
clear_null(void)696 static struct ptunit_result clear_null(void)
697 {
698 int errcode;
699
700 errcode = pt_iscache_clear(NULL);
701 ptu_int_eq(errcode, -pte_internal);
702
703 return ptu_passed();
704 }
705
free_null(void)706 static struct ptunit_result free_null(void)
707 {
708 pt_iscache_free(NULL);
709
710 return ptu_passed();
711 }
712
add_file_null(void)713 static struct ptunit_result add_file_null(void)
714 {
715 struct pt_image_section_cache iscache;
716 int errcode;
717
718 errcode = pt_iscache_add_file(NULL, "filename", 0ull, 0ull, 0ull);
719 ptu_int_eq(errcode, -pte_invalid);
720
721 errcode = pt_iscache_add_file(&iscache, NULL, 0ull, 0ull, 0ull);
722 ptu_int_eq(errcode, -pte_invalid);
723
724 return ptu_passed();
725 }
726
read_null(void)727 static struct ptunit_result read_null(void)
728 {
729 struct pt_image_section_cache iscache;
730 uint8_t buffer;
731 int errcode;
732
733 errcode = pt_iscache_read(NULL, &buffer, sizeof(buffer), 1ull, 0ull);
734 ptu_int_eq(errcode, -pte_invalid);
735
736 errcode = pt_iscache_read(&iscache, NULL, sizeof(buffer), 1ull, 0ull);
737 ptu_int_eq(errcode, -pte_invalid);
738
739 errcode = pt_iscache_read(&iscache, &buffer, 0ull, 1, 0ull);
740 ptu_int_eq(errcode, -pte_invalid);
741
742 return ptu_passed();
743 }
744
init_fini(struct iscache_fixture * cfix)745 static struct ptunit_result init_fini(struct iscache_fixture *cfix)
746 {
747 (void) cfix;
748
749 /* The actual init and fini calls are in cfix_init() and cfix_fini(). */
750 return ptu_passed();
751 }
752
name(struct iscache_fixture * cfix)753 static struct ptunit_result name(struct iscache_fixture *cfix)
754 {
755 const char *name;
756
757 pt_iscache_init(&cfix->iscache, "iscache-name");
758
759 name = pt_iscache_name(&cfix->iscache);
760 ptu_str_eq(name, "iscache-name");
761
762 return ptu_passed();
763 }
764
name_none(struct iscache_fixture * cfix)765 static struct ptunit_result name_none(struct iscache_fixture *cfix)
766 {
767 const char *name;
768
769 pt_iscache_init(&cfix->iscache, NULL);
770
771 name = pt_iscache_name(&cfix->iscache);
772 ptu_null(name);
773
774 return ptu_passed();
775 }
776
add(struct iscache_fixture * cfix)777 static struct ptunit_result add(struct iscache_fixture *cfix)
778 {
779 int isid;
780
781 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
782 ptu_int_gt(isid, 0);
783
784 /* The cache attaches and gets a reference on success. */
785 ptu_int_eq(cfix->section[0]->ucount, 2);
786 ptu_int_eq(cfix->section[0]->acount, 1);
787
788 /* The added section must be implicitly put in pt_iscache_fini. */
789 return ptu_passed();
790 }
791
add_no_name(struct iscache_fixture * cfix)792 static struct ptunit_result add_no_name(struct iscache_fixture *cfix)
793 {
794 struct pt_section section;
795 int errcode;
796
797 memset(§ion, 0, sizeof(section));
798
799 errcode = pt_iscache_add(&cfix->iscache, §ion, 0ull);
800 ptu_int_eq(errcode, -pte_internal);
801
802 return ptu_passed();
803 }
804
add_file(struct iscache_fixture * cfix)805 static struct ptunit_result add_file(struct iscache_fixture *cfix)
806 {
807 int isid;
808
809 isid = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull);
810 ptu_int_gt(isid, 0);
811
812 return ptu_passed();
813 }
814
find(struct iscache_fixture * cfix)815 static struct ptunit_result find(struct iscache_fixture *cfix)
816 {
817 struct pt_section *section;
818 int found, isid;
819
820 section = cfix->section[0];
821 ptu_ptr(section);
822
823 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
824 ptu_int_gt(isid, 0);
825
826 found = pt_iscache_find(&cfix->iscache, section->filename,
827 section->offset, section->size, 0ull);
828 ptu_int_eq(found, isid);
829
830 return ptu_passed();
831 }
832
find_empty(struct iscache_fixture * cfix)833 static struct ptunit_result find_empty(struct iscache_fixture *cfix)
834 {
835 struct pt_section *section;
836 int found;
837
838 section = cfix->section[0];
839 ptu_ptr(section);
840
841 found = pt_iscache_find(&cfix->iscache, section->filename,
842 section->offset, section->size, 0ull);
843 ptu_int_eq(found, 0);
844
845 return ptu_passed();
846 }
847
find_bad_filename(struct iscache_fixture * cfix)848 static struct ptunit_result find_bad_filename(struct iscache_fixture *cfix)
849 {
850 struct pt_section *section;
851 int found, isid;
852
853 section = cfix->section[0];
854 ptu_ptr(section);
855
856 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
857 ptu_int_gt(isid, 0);
858
859 found = pt_iscache_find(&cfix->iscache, "bad-filename",
860 section->offset, section->size, 0ull);
861 ptu_int_eq(found, 0);
862
863 return ptu_passed();
864 }
865
find_null_filename(struct iscache_fixture * cfix)866 static struct ptunit_result find_null_filename(struct iscache_fixture *cfix)
867 {
868 int errcode;
869
870 errcode = pt_iscache_find(&cfix->iscache, NULL, 0ull, 0ull, 0ull);
871 ptu_int_eq(errcode, -pte_internal);
872
873 return ptu_passed();
874 }
875
find_bad_offset(struct iscache_fixture * cfix)876 static struct ptunit_result find_bad_offset(struct iscache_fixture *cfix)
877 {
878 struct pt_section *section;
879 int found, isid;
880
881 section = cfix->section[0];
882 ptu_ptr(section);
883
884 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
885 ptu_int_gt(isid, 0);
886
887 found = pt_iscache_find(&cfix->iscache, section->filename, 0ull,
888 section->size, 0ull);
889 ptu_int_eq(found, 0);
890
891 return ptu_passed();
892 }
893
find_bad_size(struct iscache_fixture * cfix)894 static struct ptunit_result find_bad_size(struct iscache_fixture *cfix)
895 {
896 struct pt_section *section;
897 int found, isid;
898
899 section = cfix->section[0];
900 ptu_ptr(section);
901
902 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
903 ptu_int_gt(isid, 0);
904
905 found = pt_iscache_find(&cfix->iscache, section->filename,
906 section->offset, 0ull, 0ull);
907 ptu_int_eq(found, 0);
908
909 return ptu_passed();
910 }
911
find_bad_laddr(struct iscache_fixture * cfix)912 static struct ptunit_result find_bad_laddr(struct iscache_fixture *cfix)
913 {
914 struct pt_section *section;
915 int found, isid;
916
917 section = cfix->section[0];
918 ptu_ptr(section);
919
920 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
921 ptu_int_gt(isid, 0);
922
923 found = pt_iscache_find(&cfix->iscache, section->filename,
924 section->offset, section->size, 1ull);
925 ptu_int_eq(found, 0);
926
927 return ptu_passed();
928 }
929
lookup(struct iscache_fixture * cfix)930 static struct ptunit_result lookup(struct iscache_fixture *cfix)
931 {
932 struct pt_section *section;
933 uint64_t laddr;
934 int errcode, isid;
935
936 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
937 ptu_int_gt(isid, 0);
938
939 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid);
940 ptu_int_eq(errcode, 0);
941 ptu_ptr_eq(section, cfix->section[0]);
942 ptu_uint_eq(laddr, 0ull);
943
944 errcode = pt_section_put(section);
945 ptu_int_eq(errcode, 0);
946
947 return ptu_passed();
948 }
949
lookup_bad_isid(struct iscache_fixture * cfix)950 static struct ptunit_result lookup_bad_isid(struct iscache_fixture *cfix)
951 {
952 struct pt_section *section;
953 uint64_t laddr;
954 int errcode, isid;
955
956 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
957 ptu_int_gt(isid, 0);
958
959 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, 0);
960 ptu_int_eq(errcode, -pte_bad_image);
961
962 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, -isid);
963 ptu_int_eq(errcode, -pte_bad_image);
964
965 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid + 1);
966 ptu_int_eq(errcode, -pte_bad_image);
967
968 return ptu_passed();
969 }
970
clear_empty(struct iscache_fixture * cfix)971 static struct ptunit_result clear_empty(struct iscache_fixture *cfix)
972 {
973 int errcode;
974
975 errcode = pt_iscache_clear(&cfix->iscache);
976 ptu_int_eq(errcode, 0);
977
978 return ptu_passed();
979 }
980
clear_find(struct iscache_fixture * cfix)981 static struct ptunit_result clear_find(struct iscache_fixture *cfix)
982 {
983 struct pt_section *section;
984 int errcode, found, isid;
985
986 section = cfix->section[0];
987 ptu_ptr(section);
988
989 isid = pt_iscache_add(&cfix->iscache, section, 0ull);
990 ptu_int_gt(isid, 0);
991
992 errcode = pt_iscache_clear(&cfix->iscache);
993 ptu_int_eq(errcode, 0);
994
995
996 found = pt_iscache_find(&cfix->iscache, section->filename,
997 section->offset, section->size, 0ull);
998 ptu_int_eq(found, 0);
999
1000 return ptu_passed();
1001 }
1002
clear_lookup(struct iscache_fixture * cfix)1003 static struct ptunit_result clear_lookup(struct iscache_fixture *cfix)
1004 {
1005 struct pt_section *section;
1006 uint64_t laddr;
1007 int errcode, isid;
1008
1009 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1010 ptu_int_gt(isid, 0);
1011
1012 errcode = pt_iscache_clear(&cfix->iscache);
1013 ptu_int_eq(errcode, 0);
1014
1015 errcode = pt_iscache_lookup(&cfix->iscache, §ion, &laddr, isid);
1016 ptu_int_eq(errcode, -pte_bad_image);
1017
1018 return ptu_passed();
1019 }
1020
add_twice(struct iscache_fixture * cfix)1021 static struct ptunit_result add_twice(struct iscache_fixture *cfix)
1022 {
1023 int isid[2];
1024
1025 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1026 ptu_int_gt(isid[0], 0);
1027
1028 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1029 ptu_int_gt(isid[1], 0);
1030
1031 /* The second add should be ignored. */
1032 ptu_int_eq(isid[1], isid[0]);
1033
1034 return ptu_passed();
1035 }
1036
add_same(struct iscache_fixture * cfix)1037 static struct ptunit_result add_same(struct iscache_fixture *cfix)
1038 {
1039 int isid[2];
1040
1041 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1042 ptu_int_gt(isid[0], 0);
1043
1044 cfix->section[1]->offset = cfix->section[0]->offset;
1045 cfix->section[1]->size = cfix->section[0]->size;
1046
1047 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 0ull);
1048 ptu_int_gt(isid[1], 0);
1049
1050 /* The second add should be ignored. */
1051 ptu_int_eq(isid[1], isid[0]);
1052
1053 return ptu_passed();
1054 }
1055
1056 static struct ptunit_result
add_twice_different_laddr(struct iscache_fixture * cfix)1057 add_twice_different_laddr(struct iscache_fixture *cfix)
1058 {
1059 int isid[2];
1060
1061 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1062 ptu_int_gt(isid[0], 0);
1063
1064 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[0], 1ull);
1065 ptu_int_gt(isid[1], 0);
1066
1067 /* We must get different identifiers. */
1068 ptu_int_ne(isid[1], isid[0]);
1069
1070 /* We attach twice and take two references - one for each entry. */
1071 ptu_int_eq(cfix->section[0]->ucount, 3);
1072 ptu_int_eq(cfix->section[0]->acount, 2);
1073
1074 return ptu_passed();
1075 }
1076
1077 static struct ptunit_result
add_same_different_laddr(struct iscache_fixture * cfix)1078 add_same_different_laddr(struct iscache_fixture *cfix)
1079 {
1080 int isid[2];
1081
1082 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1083 ptu_int_gt(isid[0], 0);
1084
1085 cfix->section[1]->offset = cfix->section[0]->offset;
1086 cfix->section[1]->size = cfix->section[0]->size;
1087
1088 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 1ull);
1089 ptu_int_gt(isid[1], 0);
1090
1091 /* We must get different identifiers. */
1092 ptu_int_ne(isid[1], isid[0]);
1093
1094 return ptu_passed();
1095 }
1096
1097 static struct ptunit_result
add_different_same_laddr(struct iscache_fixture * cfix)1098 add_different_same_laddr(struct iscache_fixture *cfix)
1099 {
1100 int isid[2];
1101
1102 isid[0] = pt_iscache_add(&cfix->iscache, cfix->section[0], 0ull);
1103 ptu_int_gt(isid[0], 0);
1104
1105 isid[1] = pt_iscache_add(&cfix->iscache, cfix->section[1], 0ull);
1106 ptu_int_gt(isid[1], 0);
1107
1108 /* We must get different identifiers. */
1109 ptu_int_ne(isid[1], isid[0]);
1110
1111 return ptu_passed();
1112 }
1113
add_file_same(struct iscache_fixture * cfix)1114 static struct ptunit_result add_file_same(struct iscache_fixture *cfix)
1115 {
1116 int isid[2];
1117
1118 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull);
1119 ptu_int_gt(isid[0], 0);
1120
1121 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull);
1122 ptu_int_gt(isid[1], 0);
1123
1124 /* The second add should be ignored. */
1125 ptu_int_eq(isid[1], isid[0]);
1126
1127 return ptu_passed();
1128 }
1129
1130 static struct ptunit_result
add_file_same_different_laddr(struct iscache_fixture * cfix)1131 add_file_same_different_laddr(struct iscache_fixture *cfix)
1132 {
1133 int isid[2];
1134
1135 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull);
1136 ptu_int_gt(isid[0], 0);
1137
1138 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 1ull);
1139 ptu_int_gt(isid[1], 0);
1140
1141 /* We must get different identifiers. */
1142 ptu_int_ne(isid[1], isid[0]);
1143
1144 return ptu_passed();
1145 }
1146
1147 static struct ptunit_result
add_file_different_same_laddr(struct iscache_fixture * cfix)1148 add_file_different_same_laddr(struct iscache_fixture *cfix)
1149 {
1150 int isid[2];
1151
1152 isid[0] = pt_iscache_add_file(&cfix->iscache, "name", 0ull, 1ull, 0ull);
1153 ptu_int_gt(isid[0], 0);
1154
1155 isid[1] = pt_iscache_add_file(&cfix->iscache, "name", 1ull, 1ull, 0ull);
1156 ptu_int_gt(isid[1], 0);
1157
1158 /* We must get different identifiers. */
1159 ptu_int_ne(isid[1], isid[0]);
1160
1161 return ptu_passed();
1162 }
1163
read(struct iscache_fixture * cfix)1164 static struct ptunit_result read(struct iscache_fixture *cfix)
1165 {
1166 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1167 int status, isid;
1168
1169 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1170 ptu_int_gt(isid, 0);
1171
1172 status = pt_iscache_read(&cfix->iscache, buffer, 2ull, isid, 0xa008ull);
1173 ptu_int_eq(status, 2);
1174 ptu_uint_eq(buffer[0], 0x8);
1175 ptu_uint_eq(buffer[1], 0x9);
1176 ptu_uint_eq(buffer[2], 0xcc);
1177
1178 return ptu_passed();
1179 }
1180
read_truncate(struct iscache_fixture * cfix)1181 static struct ptunit_result read_truncate(struct iscache_fixture *cfix)
1182 {
1183 uint8_t buffer[] = { 0xcc, 0xcc };
1184 int status, isid;
1185
1186 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1187 ptu_int_gt(isid, 0);
1188
1189 status = pt_iscache_read(&cfix->iscache, buffer, sizeof(buffer), isid,
1190 0xa00full);
1191 ptu_int_eq(status, 1);
1192 ptu_uint_eq(buffer[0], 0xf);
1193 ptu_uint_eq(buffer[1], 0xcc);
1194
1195 return ptu_passed();
1196 }
1197
read_bad_vaddr(struct iscache_fixture * cfix)1198 static struct ptunit_result read_bad_vaddr(struct iscache_fixture *cfix)
1199 {
1200 uint8_t buffer[] = { 0xcc };
1201 int status, isid;
1202
1203 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1204 ptu_int_gt(isid, 0);
1205
1206 status = pt_iscache_read(&cfix->iscache, buffer, 1ull, isid, 0xb000ull);
1207 ptu_int_eq(status, -pte_nomap);
1208 ptu_uint_eq(buffer[0], 0xcc);
1209
1210 return ptu_passed();
1211 }
1212
read_bad_isid(struct iscache_fixture * cfix)1213 static struct ptunit_result read_bad_isid(struct iscache_fixture *cfix)
1214 {
1215 uint8_t buffer[] = { 0xcc };
1216 int status, isid;
1217
1218 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1219 ptu_int_gt(isid, 0);
1220
1221 status = pt_iscache_read(&cfix->iscache, buffer, 1ull, isid + 1,
1222 0xa000ull);
1223 ptu_int_eq(status, -pte_bad_image);
1224 ptu_uint_eq(buffer[0], 0xcc);
1225
1226 return ptu_passed();
1227 }
1228
lru_map(struct iscache_fixture * cfix)1229 static struct ptunit_result lru_map(struct iscache_fixture *cfix)
1230 {
1231 int status, isid;
1232
1233 cfix->iscache.limit = cfix->section[0]->size;
1234 ptu_uint_eq(cfix->iscache.used, 0ull);
1235 ptu_null(cfix->iscache.lru);
1236
1237 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1238 ptu_int_gt(isid, 0);
1239
1240 status = pt_section_map(cfix->section[0]);
1241 ptu_int_eq(status, 0);
1242
1243 status = pt_section_unmap(cfix->section[0]);
1244 ptu_int_eq(status, 0);
1245
1246 ptu_ptr(cfix->iscache.lru);
1247 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]);
1248 ptu_null(cfix->iscache.lru->next);
1249 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size);
1250
1251 return ptu_passed();
1252 }
1253
lru_read(struct iscache_fixture * cfix)1254 static struct ptunit_result lru_read(struct iscache_fixture *cfix)
1255 {
1256 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1257 int status, isid;
1258
1259 cfix->iscache.limit = cfix->section[0]->size;
1260 ptu_uint_eq(cfix->iscache.used, 0ull);
1261 ptu_null(cfix->iscache.lru);
1262
1263 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1264 ptu_int_gt(isid, 0);
1265
1266 status = pt_iscache_read(&cfix->iscache, buffer, 2ull, isid, 0xa008ull);
1267 ptu_int_eq(status, 2);
1268
1269 ptu_ptr(cfix->iscache.lru);
1270 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]);
1271 ptu_null(cfix->iscache.lru->next);
1272 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size);
1273
1274 return ptu_passed();
1275 }
1276
lru_map_nodup(struct iscache_fixture * cfix)1277 static struct ptunit_result lru_map_nodup(struct iscache_fixture *cfix)
1278 {
1279 int status, isid;
1280
1281 cfix->iscache.limit = 2 * cfix->section[0]->size;
1282 ptu_uint_eq(cfix->iscache.used, 0ull);
1283 ptu_null(cfix->iscache.lru);
1284
1285 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1286 ptu_int_gt(isid, 0);
1287
1288 status = pt_section_map(cfix->section[0]);
1289 ptu_int_eq(status, 0);
1290
1291 status = pt_section_unmap(cfix->section[0]);
1292 ptu_int_eq(status, 0);
1293
1294 status = pt_section_map(cfix->section[0]);
1295 ptu_int_eq(status, 0);
1296
1297 status = pt_section_unmap(cfix->section[0]);
1298 ptu_int_eq(status, 0);
1299
1300 ptu_ptr(cfix->iscache.lru);
1301 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]);
1302 ptu_null(cfix->iscache.lru->next);
1303 ptu_uint_eq(cfix->iscache.used, cfix->section[0]->size);
1304
1305 return ptu_passed();
1306 }
1307
lru_map_too_big(struct iscache_fixture * cfix)1308 static struct ptunit_result lru_map_too_big(struct iscache_fixture *cfix)
1309 {
1310 int status, isid;
1311
1312 cfix->iscache.limit = cfix->section[0]->size - 1;
1313 ptu_uint_eq(cfix->iscache.used, 0ull);
1314 ptu_null(cfix->iscache.lru);
1315
1316 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1317 ptu_int_gt(isid, 0);
1318
1319 status = pt_section_map(cfix->section[0]);
1320 ptu_int_eq(status, 0);
1321
1322 status = pt_section_unmap(cfix->section[0]);
1323 ptu_int_eq(status, 0);
1324
1325 ptu_null(cfix->iscache.lru);
1326 ptu_uint_eq(cfix->iscache.used, 0ull);
1327
1328 return ptu_passed();
1329 }
1330
lru_map_add_front(struct iscache_fixture * cfix)1331 static struct ptunit_result lru_map_add_front(struct iscache_fixture *cfix)
1332 {
1333 int status, isid;
1334
1335 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size;
1336 ptu_uint_eq(cfix->iscache.used, 0ull);
1337 ptu_null(cfix->iscache.lru);
1338
1339 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1340 ptu_int_gt(isid, 0);
1341
1342 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1343 ptu_int_gt(isid, 0);
1344
1345 status = pt_section_map(cfix->section[0]);
1346 ptu_int_eq(status, 0);
1347
1348 status = pt_section_unmap(cfix->section[0]);
1349 ptu_int_eq(status, 0);
1350
1351 status = pt_section_map(cfix->section[1]);
1352 ptu_int_eq(status, 0);
1353
1354 status = pt_section_unmap(cfix->section[1]);
1355 ptu_int_eq(status, 0);
1356
1357 ptu_ptr(cfix->iscache.lru);
1358 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]);
1359 ptu_ptr(cfix->iscache.lru->next);
1360 ptu_ptr_eq(cfix->iscache.lru->next->section, cfix->section[0]);
1361 ptu_null(cfix->iscache.lru->next->next);
1362 ptu_uint_eq(cfix->iscache.used,
1363 cfix->section[0]->size + cfix->section[1]->size);
1364
1365 return ptu_passed();
1366 }
1367
lru_map_move_front(struct iscache_fixture * cfix)1368 static struct ptunit_result lru_map_move_front(struct iscache_fixture *cfix)
1369 {
1370 int status, isid;
1371
1372 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size;
1373 ptu_uint_eq(cfix->iscache.used, 0ull);
1374 ptu_null(cfix->iscache.lru);
1375
1376 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1377 ptu_int_gt(isid, 0);
1378
1379 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1380 ptu_int_gt(isid, 0);
1381
1382 status = pt_section_map(cfix->section[0]);
1383 ptu_int_eq(status, 0);
1384
1385 status = pt_section_unmap(cfix->section[0]);
1386 ptu_int_eq(status, 0);
1387
1388 status = pt_section_map(cfix->section[1]);
1389 ptu_int_eq(status, 0);
1390
1391 status = pt_section_unmap(cfix->section[1]);
1392 ptu_int_eq(status, 0);
1393
1394 status = pt_section_map(cfix->section[0]);
1395 ptu_int_eq(status, 0);
1396
1397 status = pt_section_unmap(cfix->section[0]);
1398 ptu_int_eq(status, 0);
1399
1400 ptu_ptr(cfix->iscache.lru);
1401 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]);
1402 ptu_ptr(cfix->iscache.lru->next);
1403 ptu_ptr_eq(cfix->iscache.lru->next->section, cfix->section[1]);
1404 ptu_null(cfix->iscache.lru->next->next);
1405 ptu_uint_eq(cfix->iscache.used,
1406 cfix->section[0]->size + cfix->section[1]->size);
1407
1408 return ptu_passed();
1409 }
1410
lru_map_evict(struct iscache_fixture * cfix)1411 static struct ptunit_result lru_map_evict(struct iscache_fixture *cfix)
1412 {
1413 int status, isid;
1414
1415 cfix->iscache.limit = cfix->section[0]->size +
1416 cfix->section[1]->size - 1;
1417 ptu_uint_eq(cfix->iscache.used, 0ull);
1418 ptu_null(cfix->iscache.lru);
1419
1420 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1421 ptu_int_gt(isid, 0);
1422
1423 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1424 ptu_int_gt(isid, 0);
1425
1426 status = pt_section_map(cfix->section[0]);
1427 ptu_int_eq(status, 0);
1428
1429 status = pt_section_unmap(cfix->section[0]);
1430 ptu_int_eq(status, 0);
1431
1432 status = pt_section_map(cfix->section[1]);
1433 ptu_int_eq(status, 0);
1434
1435 status = pt_section_unmap(cfix->section[1]);
1436 ptu_int_eq(status, 0);
1437
1438 ptu_ptr(cfix->iscache.lru);
1439 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]);
1440 ptu_null(cfix->iscache.lru->next);
1441 ptu_uint_eq(cfix->iscache.used, cfix->section[1]->size);
1442
1443 return ptu_passed();
1444 }
1445
lru_bcache_evict(struct iscache_fixture * cfix)1446 static struct ptunit_result lru_bcache_evict(struct iscache_fixture *cfix)
1447 {
1448 int status, isid;
1449
1450 cfix->iscache.limit = 4 * cfix->section[0]->size +
1451 cfix->section[1]->size - 1;
1452 ptu_uint_eq(cfix->iscache.used, 0ull);
1453 ptu_null(cfix->iscache.lru);
1454
1455 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1456 ptu_int_gt(isid, 0);
1457
1458 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1459 ptu_int_gt(isid, 0);
1460
1461 status = pt_section_map(cfix->section[0]);
1462 ptu_int_eq(status, 0);
1463
1464 status = pt_section_unmap(cfix->section[0]);
1465 ptu_int_eq(status, 0);
1466
1467 status = pt_section_map(cfix->section[1]);
1468 ptu_int_eq(status, 0);
1469
1470 status = pt_section_unmap(cfix->section[1]);
1471 ptu_int_eq(status, 0);
1472
1473 status = pt_section_request_bcache(cfix->section[0]);
1474 ptu_int_eq(status, 0);
1475
1476 ptu_ptr(cfix->iscache.lru);
1477 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[0]);
1478 ptu_null(cfix->iscache.lru->next);
1479 ptu_uint_eq(cfix->iscache.used, 4 * cfix->section[0]->size);
1480
1481 return ptu_passed();
1482 }
1483
lru_bcache_clear(struct iscache_fixture * cfix)1484 static struct ptunit_result lru_bcache_clear(struct iscache_fixture *cfix)
1485 {
1486 int status, isid;
1487
1488 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size;
1489 ptu_uint_eq(cfix->iscache.used, 0ull);
1490 ptu_null(cfix->iscache.lru);
1491
1492 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1493 ptu_int_gt(isid, 0);
1494
1495 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1496 ptu_int_gt(isid, 0);
1497
1498 status = pt_section_map(cfix->section[0]);
1499 ptu_int_eq(status, 0);
1500
1501 status = pt_section_unmap(cfix->section[0]);
1502 ptu_int_eq(status, 0);
1503
1504 status = pt_section_map(cfix->section[1]);
1505 ptu_int_eq(status, 0);
1506
1507 status = pt_section_unmap(cfix->section[1]);
1508 ptu_int_eq(status, 0);
1509
1510 status = pt_section_request_bcache(cfix->section[0]);
1511 ptu_int_eq(status, 0);
1512
1513 ptu_null(cfix->iscache.lru);
1514 ptu_uint_eq(cfix->iscache.used, 0ull);
1515
1516 return ptu_passed();
1517 }
1518
lru_limit_evict(struct iscache_fixture * cfix)1519 static struct ptunit_result lru_limit_evict(struct iscache_fixture *cfix)
1520 {
1521 int status, isid;
1522
1523 cfix->iscache.limit = cfix->section[0]->size + cfix->section[1]->size;
1524 ptu_uint_eq(cfix->iscache.used, 0ull);
1525 ptu_null(cfix->iscache.lru);
1526
1527 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1528 ptu_int_gt(isid, 0);
1529
1530 isid = pt_iscache_add(&cfix->iscache, cfix->section[1], 0xa000ull);
1531 ptu_int_gt(isid, 0);
1532
1533 status = pt_section_map(cfix->section[0]);
1534 ptu_int_eq(status, 0);
1535
1536 status = pt_section_unmap(cfix->section[0]);
1537 ptu_int_eq(status, 0);
1538
1539 status = pt_section_map(cfix->section[1]);
1540 ptu_int_eq(status, 0);
1541
1542 status = pt_section_unmap(cfix->section[1]);
1543 ptu_int_eq(status, 0);
1544
1545 status = pt_iscache_set_limit(&cfix->iscache,
1546 cfix->section[0]->size +
1547 cfix->section[1]->size - 1);
1548 ptu_int_eq(status, 0);
1549
1550 ptu_ptr(cfix->iscache.lru);
1551 ptu_ptr_eq(cfix->iscache.lru->section, cfix->section[1]);
1552 ptu_null(cfix->iscache.lru->next);
1553 ptu_uint_eq(cfix->iscache.used, cfix->section[1]->size);
1554
1555 return ptu_passed();
1556 }
1557
lru_clear(struct iscache_fixture * cfix)1558 static struct ptunit_result lru_clear(struct iscache_fixture *cfix)
1559 {
1560 int status, isid;
1561
1562 cfix->iscache.limit = cfix->section[0]->size;
1563 ptu_uint_eq(cfix->iscache.used, 0ull);
1564 ptu_null(cfix->iscache.lru);
1565
1566 isid = pt_iscache_add(&cfix->iscache, cfix->section[0], 0xa000ull);
1567 ptu_int_gt(isid, 0);
1568
1569 status = pt_section_map(cfix->section[0]);
1570 ptu_int_eq(status, 0);
1571
1572 status = pt_section_unmap(cfix->section[0]);
1573 ptu_int_eq(status, 0);
1574
1575 status = pt_iscache_clear(&cfix->iscache);
1576 ptu_int_eq(status, 0);
1577
1578 ptu_null(cfix->iscache.lru);
1579 ptu_uint_eq(cfix->iscache.used, 0ull);
1580
1581 return ptu_passed();
1582 }
1583
worker_add(void * arg)1584 static int worker_add(void *arg)
1585 {
1586 struct iscache_fixture *cfix;
1587 int it;
1588
1589 cfix = arg;
1590 if (!cfix)
1591 return -pte_internal;
1592
1593 for (it = 0; it < num_iterations; ++it) {
1594 uint64_t laddr;
1595 int sec;
1596
1597 laddr = 0x1000ull * (it % 23);
1598
1599 for (sec = 0; sec < num_sections; ++sec) {
1600 struct pt_section *section;
1601 uint64_t addr;
1602 int isid, errcode;
1603
1604 isid = pt_iscache_add(&cfix->iscache,
1605 cfix->section[sec], laddr);
1606 if (isid < 0)
1607 return isid;
1608
1609 errcode = pt_iscache_lookup(&cfix->iscache, §ion,
1610 &addr, isid);
1611 if (errcode < 0)
1612 return errcode;
1613
1614 if (laddr != addr)
1615 return -pte_noip;
1616
1617 /* We may not get the image we added but the image we
1618 * get must have similar attributes.
1619 *
1620 * We're using the same filename string literal for all
1621 * sections, though.
1622 */
1623 if (section->offset != cfix->section[sec]->offset)
1624 return -pte_bad_image;
1625
1626 if (section->size != cfix->section[sec]->size)
1627 return -pte_bad_image;
1628
1629 errcode = pt_section_put(section);
1630 if (errcode < 0)
1631 return errcode;
1632 }
1633 }
1634
1635 return 0;
1636 }
1637
worker_add_file(void * arg)1638 static int worker_add_file(void *arg)
1639 {
1640 struct iscache_fixture *cfix;
1641 int it;
1642
1643 cfix = arg;
1644 if (!cfix)
1645 return -pte_internal;
1646
1647 for (it = 0; it < num_iterations; ++it) {
1648 uint64_t offset, size, laddr;
1649 int sec;
1650
1651 offset = it % 7 == 0 ? 0x1000 : 0x2000;
1652 size = it % 5 == 0 ? 0x1000 : 0x2000;
1653 laddr = it % 3 == 0 ? 0x1000 : 0x2000;
1654
1655 for (sec = 0; sec < num_sections; ++sec) {
1656 struct pt_section *section;
1657 uint64_t addr;
1658 int isid, errcode;
1659
1660 isid = pt_iscache_add_file(&cfix->iscache, "name",
1661 offset, size, laddr);
1662 if (isid < 0)
1663 return isid;
1664
1665 errcode = pt_iscache_lookup(&cfix->iscache, §ion,
1666 &addr, isid);
1667 if (errcode < 0)
1668 return errcode;
1669
1670 if (laddr != addr)
1671 return -pte_noip;
1672
1673 if (section->offset != offset)
1674 return -pte_bad_image;
1675
1676 if (section->size != size)
1677 return -pte_bad_image;
1678
1679 errcode = pt_section_put(section);
1680 if (errcode < 0)
1681 return errcode;
1682 }
1683 }
1684
1685 return 0;
1686 }
1687
worker_map(void * arg)1688 static int worker_map(void *arg)
1689 {
1690 struct iscache_fixture *cfix;
1691 int it, sec, status;
1692
1693 cfix = arg;
1694 if (!cfix)
1695 return -pte_internal;
1696
1697 for (it = 0; it < num_iterations; ++it) {
1698 for (sec = 0; sec < num_sections; ++sec) {
1699
1700 status = pt_section_map(cfix->section[sec]);
1701 if (status < 0)
1702 return status;
1703
1704 status = pt_section_unmap(cfix->section[sec]);
1705 if (status < 0)
1706 return status;
1707 }
1708 }
1709
1710 return 0;
1711 }
1712
worker_map_limit(void * arg)1713 static int worker_map_limit(void *arg)
1714 {
1715 struct iscache_fixture *cfix;
1716 uint64_t limits[] = { 0x8000, 0x3000, 0x12000, 0x0 }, limit;
1717 int it, sec, errcode, lim;
1718
1719 cfix = arg;
1720 if (!cfix)
1721 return -pte_internal;
1722
1723 lim = 0;
1724 for (it = 0; it < num_iterations; ++it) {
1725 for (sec = 0; sec < num_sections; ++sec) {
1726
1727 errcode = pt_section_map(cfix->section[sec]);
1728 if (errcode < 0)
1729 return errcode;
1730
1731 errcode = pt_section_unmap(cfix->section[sec]);
1732 if (errcode < 0)
1733 return errcode;
1734 }
1735
1736 if (it % 23 != 0)
1737 continue;
1738
1739 limit = limits[lim++];
1740 lim %= sizeof(limits) / sizeof(*limits);
1741
1742 errcode = pt_iscache_set_limit(&cfix->iscache, limit);
1743 if (errcode < 0)
1744 return errcode;
1745 }
1746
1747 return 0;
1748 }
1749
worker_map_bcache(void * arg)1750 static int worker_map_bcache(void *arg)
1751 {
1752 struct iscache_fixture *cfix;
1753 int it, sec, status;
1754
1755 cfix = arg;
1756 if (!cfix)
1757 return -pte_internal;
1758
1759 for (it = 0; it < num_iterations; ++it) {
1760 for (sec = 0; sec < num_sections; ++sec) {
1761 struct pt_section *section;
1762
1763 section = cfix->section[sec];
1764
1765 status = pt_section_map(section);
1766 if (status < 0)
1767 return status;
1768
1769 if (it % 13 == 0) {
1770 status = pt_section_request_bcache(section);
1771 if (status < 0) {
1772 (void) pt_section_unmap(section);
1773 return status;
1774 }
1775 }
1776
1777 status = pt_section_unmap(section);
1778 if (status < 0)
1779 return status;
1780 }
1781 }
1782
1783 return 0;
1784 }
1785
worker_add_map(void * arg)1786 static int worker_add_map(void *arg)
1787 {
1788 struct iscache_fixture *cfix;
1789 struct pt_section *section;
1790 int it;
1791
1792 cfix = arg;
1793 if (!cfix)
1794 return -pte_internal;
1795
1796 section = cfix->section[0];
1797 for (it = 0; it < num_iterations; ++it) {
1798 uint64_t laddr;
1799 int isid, errcode;
1800
1801 laddr = (uint64_t) it << 3;
1802
1803 isid = pt_iscache_add(&cfix->iscache, section, laddr);
1804 if (isid < 0)
1805 return isid;
1806
1807 errcode = pt_section_map(section);
1808 if (errcode < 0)
1809 return errcode;
1810
1811 errcode = pt_section_unmap(section);
1812 if (errcode < 0)
1813 return errcode;
1814 }
1815
1816 return 0;
1817 }
1818
worker_add_clear(void * arg)1819 static int worker_add_clear(void *arg)
1820 {
1821 struct iscache_fixture *cfix;
1822 struct pt_section *section;
1823 int it;
1824
1825 cfix = arg;
1826 if (!cfix)
1827 return -pte_internal;
1828
1829 section = cfix->section[0];
1830 for (it = 0; it < num_iterations; ++it) {
1831 uint64_t laddr;
1832 int isid, errcode;
1833
1834 laddr = (uint64_t) it << 3;
1835
1836 isid = pt_iscache_add(&cfix->iscache, section, laddr);
1837 if (isid < 0)
1838 return isid;
1839
1840 errcode = pt_iscache_clear(&cfix->iscache);
1841 if (errcode < 0)
1842 return errcode;
1843 }
1844
1845 return 0;
1846 }
1847
worker_add_file_map(void * arg)1848 static int worker_add_file_map(void *arg)
1849 {
1850 struct iscache_fixture *cfix;
1851 int it;
1852
1853 cfix = arg;
1854 if (!cfix)
1855 return -pte_internal;
1856
1857 for (it = 0; it < num_iterations; ++it) {
1858 struct pt_section *section;
1859 uint64_t offset, size, laddr, addr;
1860 int isid, errcode;
1861
1862 offset = it % 7 < 4 ? 0x1000 : 0x2000;
1863 size = it % 5 < 3 ? 0x1000 : 0x2000;
1864 laddr = it % 3 < 2 ? 0x1000 : 0x2000;
1865
1866 isid = pt_iscache_add_file(&cfix->iscache, "name",
1867 offset, size, laddr);
1868 if (isid < 0)
1869 return isid;
1870
1871 errcode = pt_iscache_lookup(&cfix->iscache, §ion,
1872 &addr, isid);
1873 if (errcode < 0)
1874 return errcode;
1875
1876 if (addr != laddr)
1877 return -pte_internal;
1878
1879 errcode = pt_section_map(section);
1880 if (errcode < 0)
1881 return errcode;
1882
1883 errcode = pt_section_unmap(section);
1884 if (errcode < 0)
1885 return errcode;
1886 }
1887
1888 return 0;
1889 }
1890
worker_add_file_clear(void * arg)1891 static int worker_add_file_clear(void *arg)
1892 {
1893 struct iscache_fixture *cfix;
1894 int it;
1895
1896 cfix = arg;
1897 if (!cfix)
1898 return -pte_internal;
1899
1900 for (it = 0; it < num_iterations; ++it) {
1901 uint64_t offset, size, laddr;
1902 int isid, errcode;
1903
1904 offset = it % 7 < 4 ? 0x1000 : 0x2000;
1905 size = it % 5 < 3 ? 0x1000 : 0x2000;
1906 laddr = it % 3 < 2 ? 0x1000 : 0x2000;
1907
1908 isid = pt_iscache_add_file(&cfix->iscache, "name",
1909 offset, size, laddr);
1910 if (isid < 0)
1911 return isid;
1912
1913 if (it % 11 < 9)
1914 continue;
1915
1916 errcode = pt_iscache_clear(&cfix->iscache);
1917 if (errcode < 0)
1918 return errcode;
1919 }
1920
1921 return 0;
1922 }
1923
stress(struct iscache_fixture * cfix,int (* worker)(void *))1924 static struct ptunit_result stress(struct iscache_fixture *cfix,
1925 int (*worker)(void *))
1926 {
1927 int errcode;
1928
1929 #if defined(FEATURE_THREADS)
1930 {
1931 int thrd;
1932
1933 for (thrd = 0; thrd < num_threads; ++thrd)
1934 ptu_test(ptunit_thrd_create, &cfix->thrd, worker, cfix);
1935 }
1936 #endif /* defined(FEATURE_THREADS) */
1937
1938 errcode = worker(cfix);
1939 ptu_int_eq(errcode, 0);
1940
1941 return ptu_passed();
1942 }
main(int argc,char ** argv)1943 int main(int argc, char **argv)
1944 {
1945 struct iscache_fixture cfix, dfix, sfix;
1946 struct ptunit_suite suite;
1947
1948 cfix.init = cfix_init;
1949 cfix.fini = cfix_fini;
1950
1951 dfix.init = dfix_init;
1952 dfix.fini = cfix_fini;
1953
1954 sfix.init = sfix_init;
1955 sfix.fini = cfix_fini;
1956
1957 suite = ptunit_mk_suite(argc, argv);
1958
1959 ptu_run(suite, init_null);
1960 ptu_run(suite, fini_null);
1961 ptu_run(suite, name_null);
1962 ptu_run(suite, add_null);
1963 ptu_run(suite, find_null);
1964 ptu_run(suite, lookup_null);
1965 ptu_run(suite, clear_null);
1966 ptu_run(suite, free_null);
1967 ptu_run(suite, add_file_null);
1968 ptu_run(suite, read_null);
1969
1970 ptu_run_f(suite, name, dfix);
1971 ptu_run_f(suite, name_none, dfix);
1972
1973 ptu_run_f(suite, init_fini, cfix);
1974 ptu_run_f(suite, add, cfix);
1975 ptu_run_f(suite, add_no_name, cfix);
1976 ptu_run_f(suite, add_file, cfix);
1977
1978 ptu_run_f(suite, find, cfix);
1979 ptu_run_f(suite, find_empty, cfix);
1980 ptu_run_f(suite, find_bad_filename, cfix);
1981 ptu_run_f(suite, find_null_filename, cfix);
1982 ptu_run_f(suite, find_bad_offset, cfix);
1983 ptu_run_f(suite, find_bad_size, cfix);
1984 ptu_run_f(suite, find_bad_laddr, cfix);
1985
1986 ptu_run_f(suite, lookup, cfix);
1987 ptu_run_f(suite, lookup_bad_isid, cfix);
1988
1989 ptu_run_f(suite, clear_empty, cfix);
1990 ptu_run_f(suite, clear_find, cfix);
1991 ptu_run_f(suite, clear_lookup, cfix);
1992
1993 ptu_run_f(suite, add_twice, cfix);
1994 ptu_run_f(suite, add_same, cfix);
1995 ptu_run_f(suite, add_twice_different_laddr, cfix);
1996 ptu_run_f(suite, add_same_different_laddr, cfix);
1997 ptu_run_f(suite, add_different_same_laddr, cfix);
1998
1999 ptu_run_f(suite, add_file_same, cfix);
2000 ptu_run_f(suite, add_file_same_different_laddr, cfix);
2001 ptu_run_f(suite, add_file_different_same_laddr, cfix);
2002
2003 ptu_run_f(suite, read, cfix);
2004 ptu_run_f(suite, read_truncate, cfix);
2005 ptu_run_f(suite, read_bad_vaddr, cfix);
2006 ptu_run_f(suite, read_bad_isid, cfix);
2007
2008 ptu_run_f(suite, lru_map, cfix);
2009 ptu_run_f(suite, lru_read, cfix);
2010 ptu_run_f(suite, lru_map_nodup, cfix);
2011 ptu_run_f(suite, lru_map_too_big, cfix);
2012 ptu_run_f(suite, lru_map_add_front, cfix);
2013 ptu_run_f(suite, lru_map_move_front, cfix);
2014 ptu_run_f(suite, lru_map_evict, cfix);
2015 ptu_run_f(suite, lru_limit_evict, cfix);
2016 ptu_run_f(suite, lru_bcache_evict, cfix);
2017 ptu_run_f(suite, lru_bcache_clear, cfix);
2018 ptu_run_f(suite, lru_clear, cfix);
2019
2020 ptu_run_fp(suite, stress, cfix, worker_add);
2021 ptu_run_fp(suite, stress, cfix, worker_add_file);
2022 ptu_run_fp(suite, stress, sfix, worker_map);
2023 ptu_run_fp(suite, stress, sfix, worker_map_limit);
2024 ptu_run_fp(suite, stress, sfix, worker_map_bcache);
2025 ptu_run_fp(suite, stress, cfix, worker_add_map);
2026 ptu_run_fp(suite, stress, cfix, worker_add_clear);
2027 ptu_run_fp(suite, stress, cfix, worker_add_file_map);
2028 ptu_run_fp(suite, stress, cfix, worker_add_file_clear);
2029
2030 return ptunit_report(&suite);
2031 }
2032