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_image.h"
32#include "pt_section.h"
33#include "pt_mapped_section.h"
34
35#include "intel-pt.h"
36
37
38struct image_fixture;
39
40/* A test mapping. */
41struct ifix_mapping {
42	/* The contents. */
43	uint8_t content[0x10];
44
45	/* The size - between 0 and sizeof(content). */
46	uint64_t size;
47
48	/* An artificial error code to be injected into pt_section_read().
49	 *
50	 * If @errcode is non-zero, pt_section_read() fails with @errcode.
51	 */
52	int errcode;
53};
54
55/* A test file status - turned into a section status. */
56struct ifix_status {
57	/* Delete indication:
58	 * - zero if initialized and not (yet) deleted
59	 * - non-zero if deleted and not (re-)initialized
60	 */
61	int deleted;
62
63	/* Put with use-count of zero indication. */
64	int bad_put;
65
66	/* The test mapping to be used. */
67	struct ifix_mapping *mapping;
68
69	/* A link back to the test fixture providing this section. */
70	struct image_fixture *ifix;
71};
72
73enum {
74	ifix_nsecs = 5
75};
76
77/* A fake image section cache. */
78struct pt_image_section_cache {
79	/* The cached sections. */
80	struct pt_section *section[ifix_nsecs];
81
82	/* Their load addresses. */
83	uint64_t laddr[ifix_nsecs];
84
85	/* The number of used sections. */
86	int nsecs;
87};
88
89extern int pt_iscache_lookup(struct pt_image_section_cache *iscache,
90			     struct pt_section **section, uint64_t *laddr,
91			     int isid);
92
93
94/* A test fixture providing an image, test sections, and asids. */
95struct image_fixture {
96	/* The image. */
97	struct pt_image image;
98
99	/* The test states. */
100	struct ifix_status status[ifix_nsecs];
101
102	/* The test mappings. */
103	struct ifix_mapping mapping[ifix_nsecs];
104
105	/* The sections. */
106	struct pt_section section[ifix_nsecs];
107
108	/* The asids. */
109	struct pt_asid asid[3];
110
111	/* The number of used sections/mappings/states. */
112	int nsecs;
113
114	/* An initially empty image as destination for image copies. */
115	struct pt_image copy;
116
117	/* A test section cache. */
118	struct pt_image_section_cache iscache;
119
120	/* The test fixture initialization and finalization functions. */
121	struct ptunit_result (*init)(struct image_fixture *);
122	struct ptunit_result (*fini)(struct image_fixture *);
123};
124
125static void ifix_init_section(struct pt_section *section, char *filename,
126			      struct ifix_status *status,
127			      struct ifix_mapping *mapping,
128			      struct image_fixture *ifix)
129{
130	uint8_t i;
131
132	memset(section, 0, sizeof(*section));
133
134	section->filename = filename;
135	section->status = status;
136	section->size = mapping->size = sizeof(mapping->content);
137	section->offset = 0x10;
138
139	for (i = 0; i < mapping->size; ++i)
140		mapping->content[i] = i;
141
142	status->deleted = 0;
143	status->bad_put = 0;
144	status->mapping = mapping;
145	status->ifix = ifix;
146}
147
148static int ifix_add_section(struct image_fixture *ifix, char *filename)
149{
150	int index;
151
152	if (!ifix)
153		return -pte_internal;
154
155	index = ifix->nsecs;
156	if (ifix_nsecs <= index)
157		return -pte_internal;
158
159	ifix_init_section(&ifix->section[index], filename, &ifix->status[index],
160			  &ifix->mapping[index], ifix);
161
162	ifix->nsecs += 1;
163	return index;
164}
165
166static int ifix_cache_section(struct image_fixture *ifix,
167			      struct pt_section *section, uint64_t laddr)
168{
169	int index;
170
171	if (!ifix)
172		return -pte_internal;
173
174	index = ifix->iscache.nsecs;
175	if (ifix_nsecs <= index)
176		return -pte_internal;
177
178	ifix->iscache.section[index] = section;
179	ifix->iscache.laddr[index] = laddr;
180
181	index += 1;
182	ifix->iscache.nsecs = index;
183
184	return index;
185}
186
187const char *pt_section_filename(const struct pt_section *section)
188{
189	if (!section)
190		return NULL;
191
192	return section->filename;
193}
194
195uint64_t pt_section_offset(const struct pt_section *section)
196{
197	if (!section)
198		return 0ull;
199
200	return section->offset;
201}
202
203uint64_t pt_section_size(const struct pt_section *section)
204{
205	if (!section)
206		return 0ull;
207
208	return section->size;
209}
210
211struct pt_section *pt_mk_section(const char *file, uint64_t offset,
212				 uint64_t size)
213{
214	(void) file;
215	(void) offset;
216	(void) size;
217
218	/* This function is not used by our tests. */
219	return NULL;
220}
221
222int pt_section_get(struct pt_section *section)
223{
224	if (!section)
225		return -pte_internal;
226
227	section->ucount += 1;
228	return 0;
229}
230
231int pt_section_put(struct pt_section *section)
232{
233	struct ifix_status *status;
234	uint16_t ucount;
235
236	if (!section)
237		return -pte_internal;
238
239	status = section->status;
240	if (!status)
241		return -pte_internal;
242
243	ucount = section->ucount;
244	if (!ucount) {
245		status->bad_put += 1;
246
247		return -pte_internal;
248	}
249
250	ucount = --section->ucount;
251	if (!ucount) {
252		status->deleted += 1;
253
254		if (status->deleted > 1)
255			return -pte_internal;
256	}
257
258	return 0;
259}
260
261int pt_iscache_lookup(struct pt_image_section_cache *iscache,
262		      struct pt_section **section, uint64_t *laddr, int isid)
263{
264	if (!iscache || !section || !laddr)
265		return -pte_internal;
266
267	if (!isid || iscache->nsecs < isid)
268		return -pte_bad_image;
269
270	isid -= 1;
271
272	*section = iscache->section[isid];
273	*laddr = iscache->laddr[isid];
274
275	return pt_section_get(*section);
276}
277
278static int ifix_unmap(struct pt_section *section)
279{
280	uint16_t mcount;
281
282	if (!section)
283		return -pte_internal;
284
285	mcount = section->mcount;
286	if (!mcount)
287		return -pte_internal;
288
289	if (!section->mapping)
290		return -pte_internal;
291
292	mcount = --section->mcount;
293	if (!mcount)
294		section->mapping = NULL;
295
296	return 0;
297}
298
299static int ifix_read(const struct pt_section *section, uint8_t *buffer,
300		     uint16_t size, uint64_t offset)
301{
302	struct ifix_mapping *mapping;
303	uint64_t begin, end;
304
305	if (!section || !buffer)
306		return -pte_internal;
307
308	begin = offset;
309	end = begin + size;
310
311	if (end < begin)
312		return -pte_nomap;
313
314	mapping = section->mapping;
315	if (!mapping)
316		return -pte_nomap;
317
318	if (mapping->errcode)
319		return mapping->errcode;
320
321	if (mapping->size <= begin)
322		return -pte_nomap;
323
324	if (mapping->size < end) {
325		end = mapping->size;
326		size = (uint16_t) (end - begin);
327	}
328
329	memcpy(buffer, &mapping->content[begin], size);
330
331	return size;
332}
333
334int pt_section_map(struct pt_section *section)
335{
336	struct ifix_status *status;
337	uint16_t mcount;
338
339	if (!section)
340		return -pte_internal;
341
342	mcount = section->mcount++;
343	if (mcount)
344		return 0;
345
346	if (section->mapping)
347		return -pte_internal;
348
349	status = section->status;
350	if (!status)
351		return -pte_internal;
352
353	section->mapping = status->mapping;
354	section->unmap = ifix_unmap;
355	section->read = ifix_read;
356
357	return 0;
358}
359
360int pt_section_on_map_lock(struct pt_section *section)
361{
362	if (!section)
363		return -pte_internal;
364
365	return 0;
366}
367
368int pt_section_unmap(struct pt_section *section)
369{
370	if (!section)
371		return -pte_internal;
372
373	if (!section->unmap)
374		return -pte_nomap;
375
376	return section->unmap(section);
377}
378
379int pt_section_read(const struct pt_section *section, uint8_t *buffer,
380		    uint16_t size, uint64_t offset)
381{
382	if (!section)
383		return -pte_internal;
384
385	if (!section->read)
386		return -pte_nomap;
387
388	return section->read(section, buffer, size, offset);
389}
390
391/* A test read memory callback. */
392static int image_readmem_callback(uint8_t *buffer, size_t size,
393				  const struct pt_asid *asid,
394				  uint64_t ip, void *context)
395{
396	const uint8_t *memory;
397	size_t idx;
398
399	(void) asid;
400
401	if (!buffer)
402		return -pte_invalid;
403
404	/* We use a constant offset of 0x3000. */
405	if (ip < 0x3000ull)
406		return -pte_nomap;
407
408	ip -= 0x3000ull;
409
410	memory = (const uint8_t *) context;
411	if (!memory)
412		return -pte_internal;
413
414	for (idx = 0; idx < size; ++idx)
415		buffer[idx] = memory[ip + idx];
416
417	return (int) idx;
418}
419
420static struct ptunit_result init(void)
421{
422	struct pt_image image;
423
424	memset(&image, 0xcd, sizeof(image));
425
426	pt_image_init(&image, NULL);
427	ptu_null(image.name);
428	ptu_null(image.sections);
429	ptu_null((void *) (uintptr_t) image.readmem.callback);
430	ptu_null(image.readmem.context);
431
432	return ptu_passed();
433}
434
435static struct ptunit_result init_name(struct image_fixture *ifix)
436{
437	memset(&ifix->image, 0xcd, sizeof(ifix->image));
438
439	pt_image_init(&ifix->image, "image-name");
440	ptu_str_eq(ifix->image.name, "image-name");
441	ptu_null(ifix->image.sections);
442	ptu_null((void *) (uintptr_t) ifix->image.readmem.callback);
443	ptu_null(ifix->image.readmem.context);
444
445	return ptu_passed();
446}
447
448static struct ptunit_result init_null(void)
449{
450	pt_image_init(NULL, NULL);
451
452	return ptu_passed();
453}
454
455static struct ptunit_result fini(void)
456{
457	struct ifix_mapping mapping;
458	struct ifix_status status;
459	struct pt_section section;
460	struct pt_image image;
461	struct pt_asid asid;
462	int errcode;
463
464	pt_asid_init(&asid);
465	ifix_init_section(&section, NULL, &status, &mapping, NULL);
466
467	pt_image_init(&image, NULL);
468	errcode = pt_image_add(&image, &section, &asid, 0x0ull, 0);
469	ptu_int_eq(errcode, 0);
470
471	pt_image_fini(&image);
472	ptu_int_eq(section.ucount, 0);
473	ptu_int_eq(section.mcount, 0);
474	ptu_int_eq(status.deleted, 1);
475	ptu_int_eq(status.bad_put, 0);
476
477	return ptu_passed();
478}
479
480static struct ptunit_result fini_empty(void)
481{
482	struct pt_image image;
483
484	pt_image_init(&image, NULL);
485	pt_image_fini(&image);
486
487	return ptu_passed();
488}
489
490static struct ptunit_result fini_null(void)
491{
492	pt_image_fini(NULL);
493
494	return ptu_passed();
495}
496
497static struct ptunit_result name(struct image_fixture *ifix)
498{
499	const char *name;
500
501	pt_image_init(&ifix->image, "image-name");
502
503	name = pt_image_name(&ifix->image);
504	ptu_str_eq(name, "image-name");
505
506	return ptu_passed();
507}
508
509static struct ptunit_result name_none(void)
510{
511	struct pt_image image;
512	const char *name;
513
514	pt_image_init(&image, NULL);
515
516	name = pt_image_name(&image);
517	ptu_null(name);
518
519	return ptu_passed();
520}
521
522static struct ptunit_result name_null(void)
523{
524	const char *name;
525
526	name = pt_image_name(NULL);
527	ptu_null(name);
528
529	return ptu_passed();
530}
531
532static struct ptunit_result read_empty(struct image_fixture *ifix)
533{
534	struct pt_asid asid;
535	uint8_t buffer[] = { 0xcc, 0xcc };
536	int status, isid;
537
538	pt_asid_init(&asid);
539
540	isid = -1;
541	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
542			       &asid, 0x1000ull);
543	ptu_int_eq(status, -pte_nomap);
544	ptu_int_eq(isid, -1);
545	ptu_uint_eq(buffer[0], 0xcc);
546	ptu_uint_eq(buffer[1], 0xcc);
547
548	return ptu_passed();
549}
550
551static struct ptunit_result overlap_front(struct image_fixture *ifix)
552{
553	uint8_t buffer[] = { 0xcc, 0xcc };
554	int status, isid;
555
556	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
557			      0x1001ull, 1);
558	ptu_int_eq(status, 0);
559
560	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
561			      0x1000ull, 2);
562	ptu_int_eq(status, 0);
563
564	isid = -1;
565	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
566			       0x1010ull);
567	ptu_int_eq(status, 1);
568	ptu_int_eq(isid, 1);
569	ptu_uint_eq(buffer[0], 0x0f);
570	ptu_uint_eq(buffer[1], 0xcc);
571
572	buffer[0] = 0xcc;
573
574	isid = -1;
575	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
576			       0x100full);
577	ptu_int_eq(status, 1);
578	ptu_int_eq(isid, 2);
579	ptu_uint_eq(buffer[0], 0x0f);
580	ptu_uint_eq(buffer[1], 0xcc);
581
582	return ptu_passed();
583}
584
585static struct ptunit_result overlap_back(struct image_fixture *ifix)
586{
587	uint8_t buffer[] = { 0xcc, 0xcc };
588	int status, isid;
589
590	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
591			      0x1000ull, 1);
592	ptu_int_eq(status, 0);
593
594	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
595			      0x1001ull, 2);
596	ptu_int_eq(status, 0);
597
598	isid = -1;
599	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
600			       0x1000ull);
601	ptu_int_eq(status, 1);
602	ptu_int_eq(isid, 1);
603	ptu_uint_eq(buffer[0], 0x00);
604	ptu_uint_eq(buffer[1], 0xcc);
605
606	isid = -1;
607	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
608			       0x1010ull);
609	ptu_int_eq(status, 1);
610	ptu_int_eq(isid, 2);
611	ptu_uint_eq(buffer[0], 0x0f);
612	ptu_uint_eq(buffer[1], 0xcc);
613
614	isid = -1;
615	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
616			       0x1001ull);
617	ptu_int_eq(status, 1);
618	ptu_int_eq(isid, 2);
619	ptu_uint_eq(buffer[0], 0x00);
620	ptu_uint_eq(buffer[1], 0xcc);
621
622	return ptu_passed();
623}
624
625static struct ptunit_result overlap_multiple(struct image_fixture *ifix)
626{
627	uint8_t buffer[] = { 0xcc, 0xcc };
628	int status, isid;
629
630	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
631			      0x1000ull, 1);
632	ptu_int_eq(status, 0);
633
634	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
635			      0x1010ull, 2);
636	ptu_int_eq(status, 0);
637
638	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
639			      0x1008ull, 3);
640	ptu_int_eq(status, 0);
641
642	isid = -1;
643	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
644			       0x1007ull);
645	ptu_int_eq(status, 1);
646	ptu_int_eq(isid, 1);
647	ptu_uint_eq(buffer[0], 0x07);
648	ptu_uint_eq(buffer[1], 0xcc);
649
650	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
651			       0x1008ull);
652	ptu_int_eq(status, 1);
653	ptu_int_eq(isid, 3);
654	ptu_uint_eq(buffer[0], 0x00);
655	ptu_uint_eq(buffer[1], 0xcc);
656
657	isid = -1;
658	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
659			       0x1017ull);
660	ptu_int_eq(status, 1);
661	ptu_int_eq(isid, 3);
662	ptu_uint_eq(buffer[0], 0x0f);
663	ptu_uint_eq(buffer[1], 0xcc);
664
665	isid = -1;
666	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
667			       0x1018ull);
668	ptu_int_eq(status, 1);
669	ptu_int_eq(isid, 2);
670	ptu_uint_eq(buffer[0], 0x08);
671	ptu_uint_eq(buffer[1], 0xcc);
672
673	return ptu_passed();
674}
675
676static struct ptunit_result overlap_mid(struct image_fixture *ifix)
677{
678	uint8_t buffer[] = { 0xcc, 0xcc };
679	int status, isid;
680
681	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
682			      0x1000ull, 1);
683	ptu_int_eq(status, 0);
684
685	ifix->section[1].size = 0x8;
686	ifix->mapping[1].size = 0x8;
687	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
688			      0x1004ull, 2);
689	ptu_int_eq(status, 0);
690
691	isid = -1;
692	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
693			       0x1003ull);
694	ptu_int_eq(status, 1);
695	ptu_int_eq(isid, 1);
696	ptu_uint_eq(buffer[0], 0x03);
697	ptu_uint_eq(buffer[1], 0xcc);
698
699	isid = -1;
700	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
701			       0x1004ull);
702	ptu_int_eq(status, 1);
703	ptu_int_eq(isid, 2);
704	ptu_uint_eq(buffer[0], 0x00);
705	ptu_uint_eq(buffer[1], 0xcc);
706
707	isid = -1;
708	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
709			       0x100bull);
710	ptu_int_eq(status, 1);
711	ptu_int_eq(isid, 2);
712	ptu_uint_eq(buffer[0], 0x07);
713	ptu_uint_eq(buffer[1], 0xcc);
714
715	isid = -1;
716	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
717			       0x100cull);
718	ptu_int_eq(status, 1);
719	ptu_int_eq(isid, 1);
720	ptu_uint_eq(buffer[0], 0x0c);
721	ptu_uint_eq(buffer[1], 0xcc);
722
723	return ptu_passed();
724}
725
726static struct ptunit_result contained(struct image_fixture *ifix)
727{
728	uint8_t buffer[] = { 0xcc, 0xcc };
729	int status, isid;
730
731	ifix->section[0].size = 0x8;
732	ifix->mapping[0].size = 0x8;
733	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
734			      0x1004ull, 1);
735	ptu_int_eq(status, 0);
736
737	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
738			      0x1000ull, 2);
739	ptu_int_eq(status, 0);
740
741	isid = -1;
742	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
743			       0x1008ull);
744	ptu_int_eq(status, 1);
745	ptu_int_eq(isid, 2);
746	ptu_uint_eq(buffer[0], 0x08);
747	ptu_uint_eq(buffer[1], 0xcc);
748
749	return ptu_passed();
750}
751
752static struct ptunit_result contained_multiple(struct image_fixture *ifix)
753{
754	uint8_t buffer[] = { 0xcc, 0xcc };
755	int status, isid;
756
757	ifix->section[0].size = 0x2;
758	ifix->mapping[0].size = 0x2;
759	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
760			      0x1004ull, 1);
761	ptu_int_eq(status, 0);
762
763	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
764			      0x1008ull, 2);
765	ptu_int_eq(status, 0);
766
767	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
768			      0x1000ull, 3);
769	ptu_int_eq(status, 0);
770
771	isid = -1;
772	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
773			       0x1004ull);
774	ptu_int_eq(status, 1);
775	ptu_int_eq(isid, 3);
776	ptu_uint_eq(buffer[0], 0x04);
777	ptu_uint_eq(buffer[1], 0xcc);
778
779	isid = -1;
780	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
781			       0x1008ull);
782	ptu_int_eq(status, 1);
783	ptu_int_eq(isid, 3);
784	ptu_uint_eq(buffer[0], 0x08);
785	ptu_uint_eq(buffer[1], 0xcc);
786
787	return ptu_passed();
788}
789
790static struct ptunit_result contained_back(struct image_fixture *ifix)
791{
792	uint8_t buffer[] = { 0xcc, 0xcc };
793	int status, isid;
794
795	ifix->section[0].size = 0x8;
796	ifix->mapping[0].size = 0x8;
797	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
798			      0x1004ull, 1);
799	ptu_int_eq(status, 0);
800
801	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
802			      0x100cull, 2);
803	ptu_int_eq(status, 0);
804
805	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
806			      0x1000ull, 3);
807	ptu_int_eq(status, 0);
808
809	isid = -1;
810	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
811			       0x1004ull);
812	ptu_int_eq(status, 1);
813	ptu_int_eq(isid, 3);
814	ptu_uint_eq(buffer[0], 0x04);
815	ptu_uint_eq(buffer[1], 0xcc);
816
817	isid = -1;
818	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
819			       0x100cull);
820	ptu_int_eq(status, 1);
821	ptu_int_eq(isid, 3);
822	ptu_uint_eq(buffer[0], 0x0c);
823	ptu_uint_eq(buffer[1], 0xcc);
824
825	isid = -1;
826	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
827			       0x100full);
828	ptu_int_eq(status, 1);
829	ptu_int_eq(isid, 3);
830	ptu_uint_eq(buffer[0], 0x0f);
831	ptu_uint_eq(buffer[1], 0xcc);
832
833	isid = -1;
834	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
835			       0x1010ull);
836	ptu_int_eq(status, 1);
837	ptu_int_eq(isid, 2);
838	ptu_uint_eq(buffer[0], 0x04);
839	ptu_uint_eq(buffer[1], 0xcc);
840
841	return ptu_passed();
842}
843
844static struct ptunit_result same(struct image_fixture *ifix)
845{
846	uint8_t buffer[] = { 0xcc, 0xcc };
847	int status, isid;
848
849	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
850			      0x1000ull, 1);
851	ptu_int_eq(status, 0);
852
853	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
854			      0x1000ull, 1);
855	ptu_int_eq(status, 0);
856
857	isid = -1;
858	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
859			       0x1008ull);
860	ptu_int_eq(status, 1);
861	ptu_int_eq(isid, 1);
862	ptu_uint_eq(buffer[0], 0x08);
863	ptu_uint_eq(buffer[1], 0xcc);
864
865	return ptu_passed();
866}
867
868static struct ptunit_result same_different_isid(struct image_fixture *ifix)
869{
870	uint8_t buffer[] = { 0xcc, 0xcc };
871	int status, isid;
872
873	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
874			      0x1000ull, 1);
875	ptu_int_eq(status, 0);
876
877	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
878			      0x1000ull, 2);
879	ptu_int_eq(status, 0);
880
881	isid = -1;
882	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
883			       0x1008ull);
884	ptu_int_eq(status, 1);
885	ptu_int_eq(isid, 2);
886	ptu_uint_eq(buffer[0], 0x08);
887	ptu_uint_eq(buffer[1], 0xcc);
888
889	return ptu_passed();
890}
891
892static struct ptunit_result same_different_offset(struct image_fixture *ifix)
893{
894	uint8_t buffer[] = { 0xcc, 0xcc }, i;
895	int status, isid, index;
896
897	/* Add another section from a different part of the same file as an
898	 * existing section.
899	 */
900	index = ifix_add_section(ifix, ifix->section[0].filename);
901	ptu_int_gt(index, 0);
902
903	ifix->section[index].offset = ifix->section[0].offset + 0x10;
904	ptu_uint_eq(ifix->section[index].size, ifix->section[0].size);
905
906	/* Change the content of the new section so we can distinguish them. */
907	for (i = 0; i < ifix->mapping[index].size; ++i)
908		ifix->mapping[index].content[i] += 0x10;
909
910
911	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
912			      0x1000ull, 0);
913	ptu_int_eq(status, 0);
914
915	status = pt_image_add(&ifix->image, &ifix->section[index],
916			      &ifix->asid[0], 0x1000ull, 0);
917	ptu_int_eq(status, 0);
918
919	isid = -1;
920	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
921			       0x1000ull);
922	ptu_int_eq(status, 1);
923	ptu_int_eq(isid, 0);
924	ptu_uint_eq(buffer[0], 0x10);
925	ptu_uint_eq(buffer[1], 0xcc);
926
927	isid = -1;
928	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
929			       0x100full);
930	ptu_int_eq(status, 1);
931	ptu_int_eq(isid, 0);
932	ptu_uint_eq(buffer[0], 0x1f);
933	ptu_uint_eq(buffer[1], 0xcc);
934
935	return ptu_passed();
936}
937
938static struct ptunit_result adjacent(struct image_fixture *ifix)
939{
940	uint8_t buffer[] = { 0xcc, 0xcc };
941	int status, isid;
942
943	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
944			      0x1000ull, 1);
945	ptu_int_eq(status, 0);
946
947	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
948			      0x1000ull - ifix->section[1].size, 2);
949	ptu_int_eq(status, 0);
950
951	status = pt_image_add(&ifix->image, &ifix->section[2], &ifix->asid[0],
952			      0x1000ull + ifix->section[0].size, 3);
953	ptu_int_eq(status, 0);
954
955	isid = -1;
956	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
957			       0x1000ull);
958	ptu_int_eq(status, 1);
959	ptu_int_eq(isid, 1);
960	ptu_uint_eq(buffer[0], 0x00);
961	ptu_uint_eq(buffer[1], 0xcc);
962
963	isid = -1;
964	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
965			       0xfffull);
966	ptu_int_eq(status, 1);
967	ptu_int_eq(isid, 2);
968	ptu_uint_eq(buffer[0],
969		    ifix->mapping[1].content[ifix->mapping[1].size - 1]);
970	ptu_uint_eq(buffer[1], 0xcc);
971
972	isid = -1;
973	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
974			       0x1000ull + ifix->section[0].size);
975	ptu_int_eq(status, 1);
976	ptu_int_eq(isid, 3);
977	ptu_uint_eq(buffer[0], 0x00);
978	ptu_uint_eq(buffer[1], 0xcc);
979
980	return ptu_passed();
981}
982
983static struct ptunit_result read_null(struct image_fixture *ifix)
984{
985	uint8_t buffer;
986	int status, isid;
987
988	status = pt_image_read(NULL, &isid, &buffer, 1, &ifix->asid[0],
989			       0x1000ull);
990	ptu_int_eq(status, -pte_internal);
991
992	status = pt_image_read(&ifix->image, NULL, &buffer, 1, &ifix->asid[0],
993			       0x1000ull);
994	ptu_int_eq(status, -pte_internal);
995
996	status = pt_image_read(&ifix->image, &isid, NULL, 1, &ifix->asid[0],
997			       0x1000ull);
998	ptu_int_eq(status, -pte_internal);
999
1000	status = pt_image_read(&ifix->image, &isid, &buffer, 1, NULL,
1001			       0x1000ull);
1002	ptu_int_eq(status, -pte_internal);
1003
1004	return ptu_passed();
1005}
1006
1007static struct ptunit_result read(struct image_fixture *ifix)
1008{
1009	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1010	int status, isid;
1011
1012	isid = -1;
1013	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1014			       0x2003ull);
1015	ptu_int_eq(status, 2);
1016	ptu_int_eq(isid, 11);
1017	ptu_uint_eq(buffer[0], 0x03);
1018	ptu_uint_eq(buffer[1], 0x04);
1019	ptu_uint_eq(buffer[2], 0xcc);
1020
1021	return ptu_passed();
1022}
1023
1024static struct ptunit_result read_asid(struct image_fixture *ifix)
1025{
1026	uint8_t buffer[] = { 0xcc, 0xcc };
1027	int status, isid;
1028
1029	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
1030			      0x1000ull, 1);
1031	ptu_int_eq(status, 0);
1032
1033	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[1],
1034			      0x1008ull, 2);
1035	ptu_int_eq(status, 0);
1036
1037	isid = -1;
1038	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
1039			       0x1009ull);
1040	ptu_int_eq(status, 1);
1041	ptu_int_eq(isid, 1);
1042	ptu_uint_eq(buffer[0], 0x09);
1043	ptu_uint_eq(buffer[1], 0xcc);
1044
1045	isid = -1;
1046	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[1],
1047			       0x1009ull);
1048	ptu_int_eq(status, 1);
1049	ptu_int_eq(isid, 2);
1050	ptu_uint_eq(buffer[0], 0x01);
1051	ptu_uint_eq(buffer[1], 0xcc);
1052
1053	return ptu_passed();
1054}
1055
1056static struct ptunit_result read_bad_asid(struct image_fixture *ifix)
1057{
1058	uint8_t buffer[] = { 0xcc, 0xcc };
1059	int status, isid;
1060
1061	isid = -1;
1062	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1063			       &ifix->asid[0], 0x2003ull);
1064	ptu_int_eq(status, -pte_nomap);
1065	ptu_int_eq(isid, -1);
1066	ptu_uint_eq(buffer[0], 0xcc);
1067	ptu_uint_eq(buffer[1], 0xcc);
1068
1069	return ptu_passed();
1070}
1071
1072static struct ptunit_result read_null_asid(struct image_fixture *ifix)
1073{
1074	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1075	int status, isid;
1076
1077	isid = -1;
1078	status = pt_image_read(&ifix->image, &isid, buffer, 2, NULL, 0x2003ull);
1079	ptu_int_eq(status, -pte_internal);
1080	ptu_int_eq(isid, -1);
1081	ptu_uint_eq(buffer[0], 0xcc);
1082	ptu_uint_eq(buffer[1], 0xcc);
1083
1084	return ptu_passed();
1085}
1086
1087static struct ptunit_result read_callback(struct image_fixture *ifix)
1088{
1089	uint8_t memory[] = { 0xdd, 0x01, 0x02, 0xdd };
1090	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1091	int status, isid;
1092
1093	status = pt_image_set_callback(&ifix->image, image_readmem_callback,
1094				       memory);
1095	ptu_int_eq(status, 0);
1096
1097	isid = -1;
1098	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1099			       0x3001ull);
1100	ptu_int_eq(status, 2);
1101	ptu_int_eq(isid, 0);
1102	ptu_uint_eq(buffer[0], 0x01);
1103	ptu_uint_eq(buffer[1], 0x02);
1104	ptu_uint_eq(buffer[2], 0xcc);
1105
1106	return ptu_passed();
1107}
1108
1109static struct ptunit_result read_nomem(struct image_fixture *ifix)
1110{
1111	uint8_t buffer[] = { 0xcc, 0xcc };
1112	int status, isid;
1113
1114	isid = -1;
1115	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1116			       &ifix->asid[1], 0x1010ull);
1117	ptu_int_eq(status, -pte_nomap);
1118	ptu_int_eq(isid, -1);
1119	ptu_uint_eq(buffer[0], 0xcc);
1120	ptu_uint_eq(buffer[1], 0xcc);
1121
1122	return ptu_passed();
1123}
1124
1125static struct ptunit_result read_truncated(struct image_fixture *ifix)
1126{
1127	uint8_t buffer[] = { 0xcc, 0xcc };
1128	int status, isid;
1129
1130	isid = -1;
1131	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1132			       &ifix->asid[0], 0x100full);
1133	ptu_int_eq(status, 1);
1134	ptu_int_eq(isid, 10);
1135	ptu_uint_eq(buffer[0], 0x0f);
1136	ptu_uint_eq(buffer[1], 0xcc);
1137
1138	return ptu_passed();
1139}
1140
1141static struct ptunit_result read_error(struct image_fixture *ifix)
1142{
1143	uint8_t buffer[] = { 0xcc };
1144	int status, isid;
1145
1146	ifix->mapping[0].errcode = -pte_nosync;
1147
1148	isid = -1;
1149	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
1150			       0x1000ull);
1151	ptu_int_eq(status, -pte_nosync);
1152	ptu_int_eq(isid, 10);
1153	ptu_uint_eq(buffer[0], 0xcc);
1154
1155	return ptu_passed();
1156}
1157
1158static struct ptunit_result read_spurious_error(struct image_fixture *ifix)
1159{
1160	uint8_t buffer[] = { 0xcc, 0xcc };
1161	int status, isid;
1162
1163	isid = -1;
1164	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
1165			       0x1000ull);
1166	ptu_int_eq(status, 1);
1167	ptu_int_eq(isid, 10);
1168	ptu_uint_eq(buffer[0], 0x00);
1169	ptu_uint_eq(buffer[1], 0xcc);
1170
1171	ifix->mapping[0].errcode = -pte_nosync;
1172
1173	isid = -1;
1174	status = pt_image_read(&ifix->image, &isid, buffer, 1, &ifix->asid[0],
1175			       0x1005ull);
1176	ptu_int_eq(status, -pte_nosync);
1177	ptu_int_eq(isid, 10);
1178	ptu_uint_eq(buffer[0], 0x00);
1179
1180	return ptu_passed();
1181}
1182
1183static struct ptunit_result remove_section(struct image_fixture *ifix)
1184{
1185	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1186	int status, isid;
1187
1188	isid = -1;
1189	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1190			       0x1001ull);
1191	ptu_int_eq(status, 2);
1192	ptu_int_eq(isid, 10);
1193	ptu_uint_eq(buffer[0], 0x01);
1194	ptu_uint_eq(buffer[1], 0x02);
1195	ptu_uint_eq(buffer[2], 0xcc);
1196
1197	status = pt_image_remove(&ifix->image, &ifix->section[0],
1198				 &ifix->asid[0], 0x1000ull);
1199	ptu_int_eq(status, 0);
1200
1201	ptu_int_ne(ifix->status[0].deleted, 0);
1202	ptu_int_eq(ifix->status[1].deleted, 0);
1203
1204	isid = -1;
1205	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1206			       &ifix->asid[0], 0x1003ull);
1207	ptu_int_eq(status, -pte_nomap);
1208	ptu_int_eq(isid, -1);
1209	ptu_uint_eq(buffer[0], 0x01);
1210	ptu_uint_eq(buffer[1], 0x02);
1211	ptu_uint_eq(buffer[2], 0xcc);
1212
1213	isid = -1;
1214	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1215			       0x2003ull);
1216	ptu_int_eq(status, 2);
1217	ptu_int_eq(isid, 11);
1218	ptu_uint_eq(buffer[0], 0x03);
1219	ptu_uint_eq(buffer[1], 0x04);
1220	ptu_uint_eq(buffer[2], 0xcc);
1221
1222	return ptu_passed();
1223}
1224
1225static struct ptunit_result remove_bad_vaddr(struct image_fixture *ifix)
1226{
1227	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1228	int status, isid;
1229
1230	isid = -1;
1231	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1232			       0x1001ull);
1233	ptu_int_eq(status, 2);
1234	ptu_int_eq(isid, 10);
1235	ptu_uint_eq(buffer[0], 0x01);
1236	ptu_uint_eq(buffer[1], 0x02);
1237	ptu_uint_eq(buffer[2], 0xcc);
1238
1239	status = pt_image_remove(&ifix->image, &ifix->section[0],
1240				 &ifix->asid[0], 0x2000ull);
1241	ptu_int_eq(status, -pte_bad_image);
1242
1243	ptu_int_eq(ifix->status[0].deleted, 0);
1244	ptu_int_eq(ifix->status[1].deleted, 0);
1245
1246	isid = -1;
1247	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1248			       0x1003ull);
1249	ptu_int_eq(status, 2);
1250	ptu_int_eq(isid, 10);
1251	ptu_uint_eq(buffer[0], 0x03);
1252	ptu_uint_eq(buffer[1], 0x04);
1253	ptu_uint_eq(buffer[2], 0xcc);
1254
1255	isid = -1;
1256	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1257			       0x2005ull);
1258	ptu_int_eq(status, 2);
1259	ptu_int_eq(isid, 11);
1260	ptu_uint_eq(buffer[0], 0x05);
1261	ptu_uint_eq(buffer[1], 0x06);
1262	ptu_uint_eq(buffer[2], 0xcc);
1263
1264	return ptu_passed();
1265}
1266
1267static struct ptunit_result remove_bad_asid(struct image_fixture *ifix)
1268{
1269	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1270	int status, isid;
1271
1272	isid = -1;
1273	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1274			       0x1001ull);
1275	ptu_int_eq(status, 2);
1276	ptu_int_eq(isid, 10);
1277	ptu_uint_eq(buffer[0], 0x01);
1278	ptu_uint_eq(buffer[1], 0x02);
1279	ptu_uint_eq(buffer[2], 0xcc);
1280
1281	status = pt_image_remove(&ifix->image, &ifix->section[0],
1282				 &ifix->asid[1], 0x1000ull);
1283	ptu_int_eq(status, -pte_bad_image);
1284
1285	ptu_int_eq(ifix->status[0].deleted, 0);
1286	ptu_int_eq(ifix->status[1].deleted, 0);
1287
1288	isid = -1;
1289	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1290			       0x1003ull);
1291	ptu_int_eq(status, 2);
1292	ptu_int_eq(isid, 10);
1293	ptu_uint_eq(buffer[0], 0x03);
1294	ptu_uint_eq(buffer[1], 0x04);
1295	ptu_uint_eq(buffer[2], 0xcc);
1296
1297	isid = -1;
1298	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1299			       0x2005ull);
1300	ptu_int_eq(status, 2);
1301	ptu_int_eq(isid, 11);
1302	ptu_uint_eq(buffer[0], 0x05);
1303	ptu_uint_eq(buffer[1], 0x06);
1304	ptu_uint_eq(buffer[2], 0xcc);
1305
1306	return ptu_passed();
1307}
1308
1309static struct ptunit_result remove_by_filename(struct image_fixture *ifix)
1310{
1311	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1312	int status, isid;
1313
1314	isid = -1;
1315	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1316			       0x1001ull);
1317	ptu_int_eq(status, 2);
1318	ptu_int_eq(isid, 10);
1319	ptu_uint_eq(buffer[0], 0x01);
1320	ptu_uint_eq(buffer[1], 0x02);
1321	ptu_uint_eq(buffer[2], 0xcc);
1322
1323	status = pt_image_remove_by_filename(&ifix->image,
1324					     ifix->section[0].filename,
1325					     &ifix->asid[0]);
1326	ptu_int_eq(status, 1);
1327
1328	ptu_int_ne(ifix->status[0].deleted, 0);
1329	ptu_int_eq(ifix->status[1].deleted, 0);
1330
1331	isid = -1;
1332	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1333			       &ifix->asid[0], 0x1003ull);
1334	ptu_int_eq(status, -pte_nomap);
1335	ptu_int_eq(isid, -1);
1336	ptu_uint_eq(buffer[0], 0x01);
1337	ptu_uint_eq(buffer[1], 0x02);
1338	ptu_uint_eq(buffer[2], 0xcc);
1339
1340	isid = -1;
1341	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1342			       0x2003ull);
1343	ptu_int_eq(status, 2);
1344	ptu_int_eq(isid, 11);
1345	ptu_uint_eq(buffer[0], 0x03);
1346	ptu_uint_eq(buffer[1], 0x04);
1347	ptu_uint_eq(buffer[2], 0xcc);
1348
1349	return ptu_passed();
1350}
1351
1352static struct ptunit_result
1353remove_by_filename_bad_asid(struct image_fixture *ifix)
1354{
1355	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1356	int status, isid;
1357
1358	isid = -1;
1359	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1360			       0x1001ull);
1361	ptu_int_eq(status, 2);
1362	ptu_int_eq(isid, 10);
1363	ptu_uint_eq(buffer[0], 0x01);
1364	ptu_uint_eq(buffer[1], 0x02);
1365	ptu_uint_eq(buffer[2], 0xcc);
1366
1367	status = pt_image_remove_by_filename(&ifix->image,
1368					     ifix->section[0].filename,
1369					     &ifix->asid[1]);
1370	ptu_int_eq(status, 0);
1371
1372	ptu_int_eq(ifix->status[0].deleted, 0);
1373	ptu_int_eq(ifix->status[1].deleted, 0);
1374
1375	isid = -1;
1376	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1377			       0x1003ull);
1378	ptu_int_eq(status, 2);
1379	ptu_int_eq(isid, 10);
1380	ptu_uint_eq(buffer[0], 0x03);
1381	ptu_uint_eq(buffer[1], 0x04);
1382	ptu_uint_eq(buffer[2], 0xcc);
1383
1384	isid = -1;
1385	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1386			       0x2005ull);
1387	ptu_int_eq(status, 2);
1388	ptu_int_eq(isid, 11);
1389	ptu_uint_eq(buffer[0], 0x05);
1390	ptu_uint_eq(buffer[1], 0x06);
1391	ptu_uint_eq(buffer[2], 0xcc);
1392
1393	return ptu_passed();
1394}
1395
1396static struct ptunit_result remove_none_by_filename(struct image_fixture *ifix)
1397{
1398	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1399	int status, isid;
1400
1401	status = pt_image_remove_by_filename(&ifix->image, "bad-name",
1402					     &ifix->asid[0]);
1403	ptu_int_eq(status, 0);
1404
1405	ptu_int_eq(ifix->status[0].deleted, 0);
1406	ptu_int_eq(ifix->status[1].deleted, 0);
1407
1408	isid = -1;
1409	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1410			       0x1003ull);
1411	ptu_int_eq(status, 2);
1412	ptu_int_eq(isid, 10);
1413	ptu_uint_eq(buffer[0], 0x03);
1414	ptu_uint_eq(buffer[1], 0x04);
1415	ptu_uint_eq(buffer[2], 0xcc);
1416
1417	isid = -1;
1418	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1419			       0x2001ull);
1420	ptu_int_eq(status, 2);
1421	ptu_int_eq(isid, 11);
1422	ptu_uint_eq(buffer[0], 0x01);
1423	ptu_uint_eq(buffer[1], 0x02);
1424	ptu_uint_eq(buffer[2], 0xcc);
1425
1426	return ptu_passed();
1427}
1428
1429static struct ptunit_result remove_all_by_filename(struct image_fixture *ifix)
1430{
1431	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1432	int status, isid;
1433
1434	ifix->section[0].filename = "same-name";
1435	ifix->section[1].filename = "same-name";
1436
1437	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
1438			      0x1000ull, 1);
1439	ptu_int_eq(status, 0);
1440
1441	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
1442			      0x2000ull, 2);
1443	ptu_int_eq(status, 0);
1444
1445	isid = -1;
1446	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1447			       0x1001ull);
1448	ptu_int_eq(status, 2);
1449	ptu_int_eq(isid, 1);
1450	ptu_uint_eq(buffer[0], 0x01);
1451	ptu_uint_eq(buffer[1], 0x02);
1452	ptu_uint_eq(buffer[2], 0xcc);
1453
1454	status = pt_image_remove_by_filename(&ifix->image, "same-name",
1455					     &ifix->asid[0]);
1456	ptu_int_eq(status, 2);
1457
1458	ptu_int_ne(ifix->status[0].deleted, 0);
1459	ptu_int_ne(ifix->status[1].deleted, 0);
1460
1461	isid = -1;
1462	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1463			       &ifix->asid[0], 0x1003ull);
1464	ptu_int_eq(status, -pte_nomap);
1465	ptu_int_eq(isid, -1);
1466	ptu_uint_eq(buffer[0], 0x01);
1467	ptu_uint_eq(buffer[1], 0x02);
1468	ptu_uint_eq(buffer[2], 0xcc);
1469
1470	isid = -1;
1471	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1472			       &ifix->asid[0], 0x2003ull);
1473	ptu_int_eq(status, -pte_nomap);
1474	ptu_int_eq(isid, -1);
1475	ptu_uint_eq(buffer[0], 0x01);
1476	ptu_uint_eq(buffer[1], 0x02);
1477	ptu_uint_eq(buffer[2], 0xcc);
1478
1479	return ptu_passed();
1480}
1481
1482static struct ptunit_result remove_by_asid(struct image_fixture *ifix)
1483{
1484	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1485	int status, isid;
1486
1487	isid = -1;
1488	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1489			       0x1001ull);
1490	ptu_int_eq(status, 2);
1491	ptu_int_eq(isid, 10);
1492	ptu_uint_eq(buffer[0], 0x01);
1493	ptu_uint_eq(buffer[1], 0x02);
1494	ptu_uint_eq(buffer[2], 0xcc);
1495
1496	status = pt_image_remove_by_asid(&ifix->image, &ifix->asid[0]);
1497	ptu_int_eq(status, 1);
1498
1499	ptu_int_ne(ifix->status[0].deleted, 0);
1500	ptu_int_eq(ifix->status[1].deleted, 0);
1501
1502	isid = -1;
1503	status = pt_image_read(&ifix->image, &isid, buffer, sizeof(buffer),
1504			       &ifix->asid[0], 0x1003ull);
1505	ptu_int_eq(status, -pte_nomap);
1506	ptu_int_eq(isid, -1);
1507	ptu_uint_eq(buffer[0], 0x01);
1508	ptu_uint_eq(buffer[1], 0x02);
1509	ptu_uint_eq(buffer[2], 0xcc);
1510
1511	isid = -1;
1512	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1513			       0x2003ull);
1514	ptu_int_eq(status, 2);
1515	ptu_int_eq(isid, 11);
1516	ptu_uint_eq(buffer[0], 0x03);
1517	ptu_uint_eq(buffer[1], 0x04);
1518	ptu_uint_eq(buffer[2], 0xcc);
1519
1520	return ptu_passed();
1521}
1522
1523static struct ptunit_result copy_empty(struct image_fixture *ifix)
1524{
1525	struct pt_asid asid;
1526	uint8_t buffer[] = { 0xcc, 0xcc };
1527	int status, isid;
1528
1529	pt_asid_init(&asid);
1530
1531	status = pt_image_copy(&ifix->copy, &ifix->image);
1532	ptu_int_eq(status, 0);
1533
1534	isid = -1;
1535	status = pt_image_read(&ifix->copy, &isid, buffer, sizeof(buffer),
1536			       &asid, 0x1000ull);
1537	ptu_int_eq(status, -pte_nomap);
1538	ptu_int_eq(isid, -1);
1539	ptu_uint_eq(buffer[0], 0xcc);
1540	ptu_uint_eq(buffer[1], 0xcc);
1541
1542	return ptu_passed();
1543}
1544
1545static struct ptunit_result copy(struct image_fixture *ifix)
1546{
1547	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1548	int status, isid;
1549
1550	status = pt_image_copy(&ifix->copy, &ifix->image);
1551	ptu_int_eq(status, 0);
1552
1553	isid = -1;
1554	status = pt_image_read(&ifix->copy, &isid, buffer, 2, &ifix->asid[1],
1555			       0x2003ull);
1556	ptu_int_eq(status, 2);
1557	ptu_int_eq(isid, 11);
1558	ptu_uint_eq(buffer[0], 0x03);
1559	ptu_uint_eq(buffer[1], 0x04);
1560	ptu_uint_eq(buffer[2], 0xcc);
1561
1562	return ptu_passed();
1563}
1564
1565static struct ptunit_result copy_self(struct image_fixture *ifix)
1566{
1567	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1568	int status, isid;
1569
1570	status = pt_image_copy(&ifix->image, &ifix->image);
1571	ptu_int_eq(status, 0);
1572
1573	isid = -1;
1574	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[1],
1575			       0x2003ull);
1576	ptu_int_eq(status, 2);
1577	ptu_int_eq(isid, 11);
1578	ptu_uint_eq(buffer[0], 0x03);
1579	ptu_uint_eq(buffer[1], 0x04);
1580	ptu_uint_eq(buffer[2], 0xcc);
1581
1582	return ptu_passed();
1583}
1584
1585static struct ptunit_result copy_shrink(struct image_fixture *ifix)
1586{
1587	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1588	int status, isid;
1589
1590	status = pt_image_add(&ifix->copy, &ifix->section[1], &ifix->asid[1],
1591			      0x2000ull, 1);
1592	ptu_int_eq(status, 0);
1593
1594	status = pt_image_copy(&ifix->copy, &ifix->image);
1595	ptu_int_eq(status, 0);
1596
1597	isid = -1;
1598	status = pt_image_read(&ifix->copy, &isid, buffer, 2, &ifix->asid[1],
1599			       0x2003ull);
1600	ptu_int_eq(status, 2);
1601	ptu_int_eq(isid, 11);
1602	ptu_uint_eq(buffer[0], 0x03);
1603	ptu_uint_eq(buffer[1], 0x04);
1604	ptu_uint_eq(buffer[2], 0xcc);
1605
1606	return ptu_passed();
1607}
1608
1609static struct ptunit_result copy_split(struct image_fixture *ifix)
1610{
1611	uint8_t buffer[] = { 0xcc, 0xcc };
1612	int status, isid;
1613
1614	status = pt_image_add(&ifix->copy, &ifix->section[0], &ifix->asid[0],
1615			      0x2000ull, 1);
1616	ptu_int_eq(status, 0);
1617
1618	ifix->section[1].size = 0x7;
1619	ifix->mapping[1].size = 0x7;
1620
1621	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
1622			      0x2001ull, 2);
1623	ptu_int_eq(status, 0);
1624
1625	ifix->section[2].size = 0x8;
1626	ifix->mapping[2].size = 0x8;
1627
1628	status = pt_image_add(&ifix->image, &ifix->section[2], &ifix->asid[0],
1629			      0x2008ull, 3);
1630	ptu_int_eq(status, 0);
1631
1632	status = pt_image_copy(&ifix->copy, &ifix->image);
1633	ptu_int_eq(status, 0);
1634
1635	isid = -1;
1636	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1637			       0x2003ull);
1638	ptu_int_eq(status, 1);
1639	ptu_int_eq(isid, 2);
1640	ptu_uint_eq(buffer[0], 0x02);
1641	ptu_uint_eq(buffer[1], 0xcc);
1642
1643	isid = -1;
1644	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1645			       0x2009ull);
1646	ptu_int_eq(status, 1);
1647	ptu_int_eq(isid, 3);
1648	ptu_uint_eq(buffer[0], 0x01);
1649	ptu_uint_eq(buffer[1], 0xcc);
1650
1651	isid = -1;
1652	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1653			       0x2000ull);
1654	ptu_int_eq(status, 1);
1655	ptu_int_eq(isid, 1);
1656	ptu_uint_eq(buffer[0], 0x00);
1657	ptu_uint_eq(buffer[1], 0xcc);
1658
1659	return ptu_passed();
1660}
1661
1662static struct ptunit_result copy_merge(struct image_fixture *ifix)
1663{
1664	uint8_t buffer[] = { 0xcc, 0xcc };
1665	int status, isid;
1666
1667	ifix->section[1].size = 0x8;
1668	ifix->mapping[1].size = 0x8;
1669
1670	status = pt_image_add(&ifix->copy, &ifix->section[1], &ifix->asid[0],
1671			      0x2000ull, 1);
1672	ptu_int_eq(status, 0);
1673
1674	ifix->section[2].size = 0x8;
1675	ifix->mapping[2].size = 0x8;
1676
1677	status = pt_image_add(&ifix->copy, &ifix->section[2], &ifix->asid[0],
1678			      0x2008ull, 2);
1679	ptu_int_eq(status, 0);
1680
1681	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
1682			      0x2000ull, 3);
1683	ptu_int_eq(status, 0);
1684
1685	status = pt_image_copy(&ifix->copy, &ifix->image);
1686	ptu_int_eq(status, 0);
1687
1688	isid = -1;
1689	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1690			       0x2003ull);
1691	ptu_int_eq(status, 1);
1692	ptu_int_eq(isid, 3);
1693	ptu_uint_eq(buffer[0], 0x03);
1694	ptu_uint_eq(buffer[1], 0xcc);
1695
1696	isid = -1;
1697	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1698			       0x200aull);
1699	ptu_int_eq(status, 1);
1700	ptu_int_eq(isid, 3);
1701	ptu_uint_eq(buffer[0], 0x0a);
1702	ptu_uint_eq(buffer[1], 0xcc);
1703
1704	return ptu_passed();
1705}
1706
1707static struct ptunit_result copy_overlap(struct image_fixture *ifix)
1708{
1709	uint8_t buffer[] = { 0xcc, 0xcc };
1710	int status, isid;
1711
1712	status = pt_image_add(&ifix->copy, &ifix->section[0], &ifix->asid[0],
1713			      0x2000ull, 1);
1714	ptu_int_eq(status, 0);
1715
1716	status = pt_image_add(&ifix->copy, &ifix->section[1], &ifix->asid[0],
1717			      0x2010ull, 2);
1718	ptu_int_eq(status, 0);
1719
1720	status = pt_image_add(&ifix->image, &ifix->section[2], &ifix->asid[0],
1721			      0x2008ull, 3);
1722	ptu_int_eq(status, 0);
1723
1724	status = pt_image_copy(&ifix->copy, &ifix->image);
1725	ptu_int_eq(status, 0);
1726
1727	isid = -1;
1728	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1729			       0x2003ull);
1730	ptu_int_eq(status, 1);
1731	ptu_int_eq(isid, 1);
1732	ptu_uint_eq(buffer[0], 0x03);
1733	ptu_uint_eq(buffer[1], 0xcc);
1734
1735	isid = -1;
1736	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1737			       0x200aull);
1738	ptu_int_eq(status, 1);
1739	ptu_int_eq(isid, 3);
1740	ptu_uint_eq(buffer[0], 0x02);
1741	ptu_uint_eq(buffer[1], 0xcc);
1742
1743	isid = -1;
1744	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1745			       0x2016ull);
1746	ptu_int_eq(status, 1);
1747	ptu_int_eq(isid, 3);
1748	ptu_uint_eq(buffer[0], 0x0e);
1749	ptu_uint_eq(buffer[1], 0xcc);
1750
1751	isid = -1;
1752	status = pt_image_read(&ifix->copy, &isid, buffer, 1, &ifix->asid[0],
1753			       0x2019ull);
1754	ptu_int_eq(status, 1);
1755	ptu_int_eq(isid, 2);
1756	ptu_uint_eq(buffer[0], 0x09);
1757	ptu_uint_eq(buffer[1], 0xcc);
1758
1759	return ptu_passed();
1760}
1761
1762static struct ptunit_result copy_replace(struct image_fixture *ifix)
1763{
1764	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1765	int status, isid;
1766
1767	ifix->section[0].size = 0x8;
1768	ifix->mapping[0].size = 0x8;
1769
1770	status = pt_image_add(&ifix->copy, &ifix->section[0], &ifix->asid[0],
1771			      0x1004ull, 1);
1772	ptu_int_eq(status, 0);
1773
1774	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[0],
1775			      0x1000ull, 2);
1776	ptu_int_eq(status, 0);
1777
1778	status = pt_image_copy(&ifix->copy, &ifix->image);
1779	ptu_int_eq(status, 0);
1780
1781	isid = -1;
1782	status = pt_image_read(&ifix->copy, &isid, buffer, 2, &ifix->asid[0],
1783			       0x1003ull);
1784	ptu_int_eq(status, 2);
1785	ptu_int_eq(isid, 2);
1786	ptu_uint_eq(buffer[0], 0x03);
1787	ptu_uint_eq(buffer[1], 0x04);
1788	ptu_uint_eq(buffer[2], 0xcc);
1789
1790	return ptu_passed();
1791}
1792
1793static struct ptunit_result add_cached_null(void)
1794{
1795	struct pt_image_section_cache iscache;
1796	struct pt_image image;
1797	int status;
1798
1799	status = pt_image_add_cached(NULL, &iscache, 0, NULL);
1800	ptu_int_eq(status, -pte_invalid);
1801
1802	status = pt_image_add_cached(&image, NULL, 0, NULL);
1803	ptu_int_eq(status, -pte_invalid);
1804
1805	return ptu_passed();
1806}
1807
1808static struct ptunit_result add_cached(struct image_fixture *ifix)
1809{
1810	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1811	int status, isid, risid;
1812
1813	isid = ifix_cache_section(ifix, &ifix->section[0], 0x1000ull);
1814	ptu_int_gt(isid, 0);
1815
1816	status = pt_image_add_cached(&ifix->image, &ifix->iscache, isid,
1817				      &ifix->asid[0]);
1818	ptu_int_eq(status, 0);
1819
1820	risid = -1;
1821	status = pt_image_read(&ifix->image, &risid, buffer, 2, &ifix->asid[0],
1822			       0x1003ull);
1823	ptu_int_eq(status, 2);
1824	ptu_int_eq(risid, isid);
1825	ptu_uint_eq(buffer[0], 0x03);
1826	ptu_uint_eq(buffer[1], 0x04);
1827	ptu_uint_eq(buffer[2], 0xcc);
1828
1829	return ptu_passed();
1830}
1831
1832static struct ptunit_result add_cached_null_asid(struct image_fixture *ifix)
1833{
1834	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1835	int status, isid, risid;
1836
1837	isid = ifix_cache_section(ifix, &ifix->section[0], 0x1000ull);
1838	ptu_int_gt(isid, 0);
1839
1840	status = pt_image_add_cached(&ifix->image, &ifix->iscache, isid, NULL);
1841	ptu_int_eq(status, 0);
1842
1843	risid = -1;
1844	status = pt_image_read(&ifix->image, &risid, buffer, 2, &ifix->asid[0],
1845			       0x1003ull);
1846	ptu_int_eq(status, 2);
1847	ptu_int_eq(risid, isid);
1848	ptu_uint_eq(buffer[0], 0x03);
1849	ptu_uint_eq(buffer[1], 0x04);
1850	ptu_uint_eq(buffer[2], 0xcc);
1851
1852	return ptu_passed();
1853}
1854
1855static struct ptunit_result add_cached_twice(struct image_fixture *ifix)
1856{
1857	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1858	int status, isid, risid;
1859
1860	isid = ifix_cache_section(ifix, &ifix->section[0], 0x1000ull);
1861	ptu_int_gt(isid, 0);
1862
1863	status = pt_image_add_cached(&ifix->image, &ifix->iscache, isid,
1864				      &ifix->asid[0]);
1865	ptu_int_eq(status, 0);
1866
1867	status = pt_image_add_cached(&ifix->image, &ifix->iscache, isid,
1868				      &ifix->asid[0]);
1869	ptu_int_eq(status, 0);
1870
1871	risid = -1;
1872	status = pt_image_read(&ifix->image, &risid, buffer, 2, &ifix->asid[0],
1873			       0x1003ull);
1874	ptu_int_eq(status, 2);
1875	ptu_int_eq(risid, isid);
1876	ptu_uint_eq(buffer[0], 0x03);
1877	ptu_uint_eq(buffer[1], 0x04);
1878	ptu_uint_eq(buffer[2], 0xcc);
1879
1880	return ptu_passed();
1881}
1882
1883static struct ptunit_result add_cached_bad_isid(struct image_fixture *ifix)
1884{
1885	uint8_t buffer[] = { 0xcc, 0xcc, 0xcc };
1886	int status, isid;
1887
1888	status = pt_image_add_cached(&ifix->image, &ifix->iscache, 1,
1889				      &ifix->asid[0]);
1890	ptu_int_eq(status, -pte_bad_image);
1891
1892	isid = -1;
1893	status = pt_image_read(&ifix->image, &isid, buffer, 2, &ifix->asid[0],
1894			       0x1003ull);
1895	ptu_int_eq(status, -pte_nomap);
1896	ptu_int_eq(isid, -1);
1897
1898	return ptu_passed();
1899}
1900
1901static struct ptunit_result find_null(struct image_fixture *ifix)
1902{
1903	struct pt_mapped_section msec;
1904	int status;
1905
1906	status = pt_image_find(NULL, &msec, &ifix->asid[0],
1907			       0x1000ull);
1908	ptu_int_eq(status, -pte_internal);
1909
1910	status = pt_image_find(&ifix->image, NULL, &ifix->asid[0],
1911			       0x1000ull);
1912	ptu_int_eq(status, -pte_internal);
1913
1914	status = pt_image_find(&ifix->image, &msec, NULL, 0x1000ull);
1915	ptu_int_eq(status, -pte_internal);
1916
1917	return ptu_passed();
1918}
1919
1920static struct ptunit_result find(struct image_fixture *ifix)
1921{
1922	struct pt_mapped_section msec;
1923	int status;
1924
1925	status = pt_image_find(&ifix->image, &msec, &ifix->asid[1], 0x2003ull);
1926	ptu_int_eq(status, 11);
1927	ptu_ptr_eq(msec.section, &ifix->section[1]);
1928	ptu_uint_eq(msec.vaddr, 0x2000ull);
1929
1930	status = pt_section_put(msec.section);
1931	ptu_int_eq(status, 0);
1932
1933	return ptu_passed();
1934}
1935
1936static struct ptunit_result find_asid(struct image_fixture *ifix)
1937{
1938	struct pt_mapped_section msec;
1939	int status;
1940
1941	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
1942			      0x1000ull, 1);
1943	ptu_int_eq(status, 0);
1944
1945	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[1],
1946			      0x1008ull, 2);
1947	ptu_int_eq(status, 0);
1948
1949	status = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1009ull);
1950	ptu_int_eq(status, 1);
1951	ptu_ptr_eq(msec.section, &ifix->section[0]);
1952	ptu_uint_eq(msec.vaddr, 0x1000ull);
1953
1954	status = pt_section_put(msec.section);
1955	ptu_int_eq(status, 0);
1956
1957	status = pt_image_find(&ifix->image, &msec, &ifix->asid[1], 0x1009ull);
1958	ptu_int_eq(status, 2);
1959	ptu_ptr_eq(msec.section, &ifix->section[0]);
1960	ptu_uint_eq(msec.vaddr, 0x1008ull);
1961
1962	status = pt_section_put(msec.section);
1963	ptu_int_eq(status, 0);
1964
1965	return ptu_passed();
1966}
1967
1968static struct ptunit_result find_bad_asid(struct image_fixture *ifix)
1969{
1970	struct pt_mapped_section msec;
1971	int status;
1972
1973	status = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x2003ull);
1974	ptu_int_eq(status, -pte_nomap);
1975
1976	return ptu_passed();
1977}
1978
1979static struct ptunit_result find_nomem(struct image_fixture *ifix)
1980{
1981	struct pt_mapped_section msec;
1982	int status;
1983
1984	status = pt_image_find(&ifix->image, &msec, &ifix->asid[1], 0x1010ull);
1985	ptu_int_eq(status, -pte_nomap);
1986
1987	return ptu_passed();
1988}
1989
1990static struct ptunit_result validate_null(struct image_fixture *ifix)
1991{
1992	struct pt_mapped_section msec;
1993	int status;
1994
1995	status = pt_image_validate(NULL, &msec, 0x1004ull, 10);
1996	ptu_int_eq(status, -pte_internal);
1997
1998	status = pt_image_validate(&ifix->image, NULL, 0x1004ull, 10);
1999	ptu_int_eq(status, -pte_internal);
2000
2001	return ptu_passed();
2002}
2003
2004static struct ptunit_result validate(struct image_fixture *ifix)
2005{
2006	struct pt_mapped_section msec;
2007	int isid, status;
2008
2009	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2010	ptu_int_ge(isid, 0);
2011
2012	status = pt_section_put(msec.section);
2013	ptu_int_eq(status, 0);
2014
2015	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid);
2016	ptu_int_eq(status, 0);
2017
2018	return ptu_passed();
2019}
2020
2021static struct ptunit_result validate_bad_asid(struct image_fixture *ifix)
2022{
2023	struct pt_mapped_section msec;
2024	int isid, status;
2025
2026	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2027	ptu_int_ge(isid, 0);
2028
2029	status = pt_section_put(msec.section);
2030	ptu_int_eq(status, 0);
2031
2032	msec.asid = ifix->asid[1];
2033
2034	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid);
2035	ptu_int_eq(status, -pte_nomap);
2036
2037	return ptu_passed();
2038}
2039
2040static struct ptunit_result validate_bad_vaddr(struct image_fixture *ifix)
2041{
2042	struct pt_mapped_section msec;
2043	int isid, status;
2044
2045	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2046	ptu_int_ge(isid, 0);
2047
2048	status = pt_section_put(msec.section);
2049	ptu_int_eq(status, 0);
2050
2051	msec.vaddr = 0x2000ull;
2052
2053	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid);
2054	ptu_int_eq(status, -pte_nomap);
2055
2056	return ptu_passed();
2057}
2058
2059static struct ptunit_result validate_bad_offset(struct image_fixture *ifix)
2060{
2061	struct pt_mapped_section msec;
2062	int isid, status;
2063
2064	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2065	ptu_int_ge(isid, 0);
2066
2067	status = pt_section_put(msec.section);
2068	ptu_int_eq(status, 0);
2069
2070	msec.offset = 0x8ull;
2071
2072	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid);
2073	ptu_int_eq(status, -pte_nomap);
2074
2075	return ptu_passed();
2076}
2077
2078static struct ptunit_result validate_bad_size(struct image_fixture *ifix)
2079{
2080	struct pt_mapped_section msec;
2081	int isid, status;
2082
2083	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2084	ptu_int_ge(isid, 0);
2085
2086	status = pt_section_put(msec.section);
2087	ptu_int_eq(status, 0);
2088
2089	msec.size = 0x8ull;
2090
2091	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid);
2092	ptu_int_eq(status, -pte_nomap);
2093
2094	return ptu_passed();
2095}
2096
2097static struct ptunit_result validate_bad_isid(struct image_fixture *ifix)
2098{
2099	struct pt_mapped_section msec;
2100	int isid, status;
2101
2102	isid = pt_image_find(&ifix->image, &msec, &ifix->asid[0], 0x1003ull);
2103	ptu_int_ge(isid, 0);
2104
2105	status = pt_section_put(msec.section);
2106	ptu_int_eq(status, 0);
2107
2108	status = pt_image_validate(&ifix->image, &msec, 0x1004ull, isid + 1);
2109	ptu_int_eq(status, -pte_nomap);
2110
2111	return ptu_passed();
2112}
2113
2114static struct ptunit_result ifix_init(struct image_fixture *ifix)
2115{
2116	int index;
2117
2118	pt_image_init(&ifix->image, NULL);
2119	pt_image_init(&ifix->copy, NULL);
2120
2121	memset(ifix->status, 0, sizeof(ifix->status));
2122	memset(ifix->mapping, 0, sizeof(ifix->mapping));
2123	memset(ifix->section, 0, sizeof(ifix->section));
2124	memset(&ifix->iscache, 0, sizeof(ifix->iscache));
2125
2126	ifix->nsecs = 0;
2127
2128	index = ifix_add_section(ifix, "file-0");
2129	ptu_int_eq(index, 0);
2130
2131	index = ifix_add_section(ifix, "file-1");
2132	ptu_int_eq(index, 1);
2133
2134	index = ifix_add_section(ifix, "file-2");
2135	ptu_int_eq(index, 2);
2136
2137	pt_asid_init(&ifix->asid[0]);
2138	ifix->asid[0].cr3 = 0xa000;
2139
2140	pt_asid_init(&ifix->asid[1]);
2141	ifix->asid[1].cr3 = 0xb000;
2142
2143	pt_asid_init(&ifix->asid[2]);
2144	ifix->asid[2].cr3 = 0xc000;
2145
2146	return ptu_passed();
2147}
2148
2149static struct ptunit_result rfix_init(struct image_fixture *ifix)
2150{
2151	int status;
2152
2153	ptu_check(ifix_init, ifix);
2154
2155	status = pt_image_add(&ifix->image, &ifix->section[0], &ifix->asid[0],
2156			      0x1000ull, 10);
2157	ptu_int_eq(status, 0);
2158
2159	status = pt_image_add(&ifix->image, &ifix->section[1], &ifix->asid[1],
2160			      0x2000ull, 11);
2161	ptu_int_eq(status, 0);
2162
2163	return ptu_passed();
2164}
2165
2166static struct ptunit_result dfix_fini(struct image_fixture *ifix)
2167{
2168	pt_image_fini(&ifix->image);
2169
2170	return ptu_passed();
2171}
2172
2173static struct ptunit_result ifix_fini(struct image_fixture *ifix)
2174{
2175	int sec;
2176
2177	ptu_check(dfix_fini, ifix);
2178
2179	pt_image_fini(&ifix->copy);
2180
2181	for (sec = 0; sec < ifix_nsecs; ++sec) {
2182		ptu_int_eq(ifix->section[sec].ucount, 0);
2183		ptu_int_eq(ifix->section[sec].mcount, 0);
2184		ptu_int_le(ifix->status[sec].deleted, 1);
2185		ptu_int_eq(ifix->status[sec].bad_put, 0);
2186	}
2187
2188	return ptu_passed();
2189}
2190
2191int main(int argc, char **argv)
2192{
2193	struct image_fixture dfix, ifix, rfix;
2194	struct ptunit_suite suite;
2195
2196	/* Dfix provides image destruction. */
2197	dfix.init = NULL;
2198	dfix.fini = dfix_fini;
2199
2200	/* Ifix provides an empty image. */
2201	ifix.init = ifix_init;
2202	ifix.fini = ifix_fini;
2203
2204	/* Rfix provides an image with two sections added. */
2205	rfix.init = rfix_init;
2206	rfix.fini = ifix_fini;
2207
2208	suite = ptunit_mk_suite(argc, argv);
2209
2210	ptu_run(suite, init);
2211	ptu_run_f(suite, init_name, dfix);
2212	ptu_run(suite, init_null);
2213
2214	ptu_run(suite, fini);
2215	ptu_run(suite, fini_empty);
2216	ptu_run(suite, fini_null);
2217
2218	ptu_run_f(suite, name, dfix);
2219	ptu_run(suite, name_none);
2220	ptu_run(suite, name_null);
2221
2222	ptu_run_f(suite, read_empty, ifix);
2223	ptu_run_f(suite, overlap_front, ifix);
2224	ptu_run_f(suite, overlap_back, ifix);
2225	ptu_run_f(suite, overlap_multiple, ifix);
2226	ptu_run_f(suite, overlap_mid, ifix);
2227	ptu_run_f(suite, contained, ifix);
2228	ptu_run_f(suite, contained_multiple, ifix);
2229	ptu_run_f(suite, contained_back, ifix);
2230	ptu_run_f(suite, same, ifix);
2231	ptu_run_f(suite, same_different_isid, ifix);
2232	ptu_run_f(suite, same_different_offset, ifix);
2233	ptu_run_f(suite, adjacent, ifix);
2234
2235	ptu_run_f(suite, read_null, rfix);
2236	ptu_run_f(suite, read, rfix);
2237	ptu_run_f(suite, read_null, rfix);
2238	ptu_run_f(suite, read_asid, ifix);
2239	ptu_run_f(suite, read_bad_asid, rfix);
2240	ptu_run_f(suite, read_null_asid, rfix);
2241	ptu_run_f(suite, read_callback, rfix);
2242	ptu_run_f(suite, read_nomem, rfix);
2243	ptu_run_f(suite, read_truncated, rfix);
2244	ptu_run_f(suite, read_error, rfix);
2245	ptu_run_f(suite, read_spurious_error, rfix);
2246
2247	ptu_run_f(suite, remove_section, rfix);
2248	ptu_run_f(suite, remove_bad_vaddr, rfix);
2249	ptu_run_f(suite, remove_bad_asid, rfix);
2250	ptu_run_f(suite, remove_by_filename, rfix);
2251	ptu_run_f(suite, remove_by_filename_bad_asid, rfix);
2252	ptu_run_f(suite, remove_none_by_filename, rfix);
2253	ptu_run_f(suite, remove_all_by_filename, ifix);
2254	ptu_run_f(suite, remove_by_asid, rfix);
2255
2256	ptu_run_f(suite, copy_empty, ifix);
2257	ptu_run_f(suite, copy, rfix);
2258	ptu_run_f(suite, copy_self, rfix);
2259	ptu_run_f(suite, copy_shrink, rfix);
2260	ptu_run_f(suite, copy_split, ifix);
2261	ptu_run_f(suite, copy_merge, ifix);
2262	ptu_run_f(suite, copy_overlap, ifix);
2263	ptu_run_f(suite, copy_replace, ifix);
2264
2265	ptu_run(suite, add_cached_null);
2266	ptu_run_f(suite, add_cached, ifix);
2267	ptu_run_f(suite, add_cached_null_asid, ifix);
2268	ptu_run_f(suite, add_cached_twice, ifix);
2269	ptu_run_f(suite, add_cached_bad_isid, ifix);
2270
2271	ptu_run_f(suite, find_null, rfix);
2272	ptu_run_f(suite, find, rfix);
2273	ptu_run_f(suite, find_asid, ifix);
2274	ptu_run_f(suite, find_bad_asid, rfix);
2275	ptu_run_f(suite, find_nomem, rfix);
2276
2277	ptu_run_f(suite, validate_null, rfix);
2278	ptu_run_f(suite, validate, rfix);
2279	ptu_run_f(suite, validate_bad_asid, rfix);
2280	ptu_run_f(suite, validate_bad_vaddr, rfix);
2281	ptu_run_f(suite, validate_bad_offset, rfix);
2282	ptu_run_f(suite, validate_bad_size, rfix);
2283	ptu_run_f(suite, validate_bad_isid, rfix);
2284
2285	return ptunit_report(&suite);
2286}
2287