1/*	$NetBSD: t_ufetchstore.c,v 1.4 2019/04/07 15:50:12 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 2019 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__COPYRIGHT("@(#) Copyright (c) 2019\
34 The NetBSD Foundation, inc. All rights reserved.");
35__RCSID("$NetBSD: t_ufetchstore.c,v 1.4 2019/04/07 15:50:12 thorpej Exp $");
36
37#include <sys/types.h>
38#include <sys/endian.h>
39#include <sys/module.h>
40#include <sys/sysctl.h>
41
42#include <err.h>
43#include <errno.h>
44#include <limits.h>
45
46#include <atf-c.h>
47
48#include "common.h"
49
50#define	mib_name	"kern.ufetchstore_test.test"
51
52static bool module_loaded;
53
54#define	MODULE_PATH	\
55	"/usr/tests/modules/ufetchstore_tester/ufetchstore_tester.kmod"
56#define	MODULE_NAME	"ufetchstore_tester"
57
58#define	CHECK_MODULE()							\
59do {									\
60	load_module();							\
61	if (! module_loaded) {						\
62		atf_tc_skip("loading '%s' module failed.", MODULE_NAME);\
63	}								\
64} while (/*CONSTCOND*/0)
65
66static void
67load_module(void)
68{
69#ifndef SKIP_MODULE
70	if (module_loaded)
71		return;
72
73	modctl_load_t params = {
74		.ml_filename = MODULE_PATH,
75		.ml_flags = MODCTL_NO_PROP,
76	};
77
78	if (modctl(MODCTL_LOAD, &params) != 0) {
79		warn("failed to load module '%s'", MODULE_PATH);
80	} else {
81		module_loaded = true;
82	}
83#else
84	module_loaded = true;
85#endif /* ! SKIP_MODULE */
86}
87
88#define	UADDR(x)	((uintptr_t)(x))
89
90static void
91unload_module(void)
92{
93#ifndef SKIP_MODULE
94	char module_name[] = MODULE_NAME;
95
96	if (modctl(MODCTL_UNLOAD, module_name) != 0) {
97		warn("failed to unload module '%s'", MODULE_NAME);
98	} else {
99		module_loaded = false;
100	}
101#endif /* ! SKIP_MODULE */
102}
103
104static unsigned long
105vm_max_address_raw(void)
106{
107	static unsigned long max_addr = 0;
108	int rv;
109
110	if (max_addr == 0) {
111		size_t max_addr_size = sizeof(max_addr);
112		rv = sysctlbyname("vm.maxaddress", &max_addr, &max_addr_size,
113				  NULL, 0);
114		if (rv != 0)
115	                err(1, "sysctlbyname('vm.maxaddress')");
116        }
117	return max_addr;
118}
119
120static void *
121vm_max_address(void)
122{
123	return (void *)vm_max_address_raw();
124}
125
126static void *
127vm_max_address_minus(unsigned int adj)
128{
129	return (void *)(vm_max_address_raw() - adj);
130}
131
132static int
133do_sysctl(struct ufetchstore_test_args *args)
134{
135	uint64_t arg_addr64 = (uintptr_t)args;
136	int rv;
137
138	args->fetchstore_error = EBADF;	/* poison */
139	args->pointer_size = (int)sizeof(void *);
140
141	/*
142	 * Yes, the intent is to provide the pointer, not the structure,
143	 * to the kernel side of the test harness.
144	 */
145	rv = sysctlbyname(mib_name, NULL, NULL, &arg_addr64,
146			  sizeof(arg_addr64));
147	if (rv != 0) {
148		rv = errno;
149		warn("sysctlbyname('%s') -> %d", mib_name, rv);
150		return rv;
151	}
152	return 0;
153}
154
155static int
156do_ufetch_8(const uint8_t *uaddr, uint8_t *res)
157{
158	struct ufetchstore_test_args args = {
159		.uaddr64 = UADDR(uaddr),
160		.test_op = OP_LOAD,
161		.size = 8,
162	};
163
164	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
165	*res = args.val8;
166	return args.fetchstore_error;
167}
168
169static int
170do_ufetch_16(const uint16_t *uaddr, uint16_t *res)
171{
172	struct ufetchstore_test_args args = {
173		.uaddr64 = UADDR(uaddr),
174		.test_op = OP_LOAD,
175		.size = 16,
176	};
177
178	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
179	*res = args.val16;
180	return args.fetchstore_error;
181}
182
183static int
184do_ufetch_32(const uint32_t *uaddr, uint32_t *res)
185{
186	struct ufetchstore_test_args args = {
187		.uaddr64 = UADDR(uaddr),
188		.test_op = OP_LOAD,
189		.size = 32,
190	};
191
192	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
193	*res = args.val32;
194	return args.fetchstore_error;
195}
196
197#ifdef _LP64
198static int
199do_ufetch_64(const uint64_t *uaddr, uint64_t *res)
200{
201	struct ufetchstore_test_args args = {
202		.uaddr64 = UADDR(uaddr),
203		.test_op = OP_LOAD,
204		.size = 64,
205	};
206
207	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
208	*res = args.val64;
209	return args.fetchstore_error;
210}
211#endif /* _LP64 */
212
213static int
214do_ustore_8(uint8_t *uaddr, uint8_t val)
215{
216	struct ufetchstore_test_args args = {
217		.uaddr64 = UADDR(uaddr),
218		.test_op = OP_STORE,
219		.size = 8,
220		.val8 = val,
221	};
222
223	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
224	return args.fetchstore_error;
225}
226
227static int
228do_ustore_16(uint16_t *uaddr, uint16_t val)
229{
230	struct ufetchstore_test_args args = {
231		.uaddr64 = UADDR(uaddr),
232		.test_op = OP_STORE,
233		.size = 16,
234		.val16 = val,
235	};
236
237	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
238	return args.fetchstore_error;
239}
240
241static int
242do_ustore_32(uint32_t *uaddr, uint32_t val)
243{
244	struct ufetchstore_test_args args = {
245		.uaddr64 = UADDR(uaddr),
246		.test_op = OP_STORE,
247		.size = 32,
248		.val32 = val,
249	};
250
251	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
252	return args.fetchstore_error;
253}
254
255#ifdef _LP64
256static int
257do_ustore_64(uint64_t *uaddr, uint64_t val)
258{
259	struct ufetchstore_test_args args = {
260		.uaddr64 = UADDR(uaddr),
261		.test_op = OP_STORE,
262		.size = 64,
263		.val64 = val,
264	};
265
266	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
267	return args.fetchstore_error;
268}
269#endif /* _LP64 */
270
271static int
272do_ucas_32(uint32_t *uaddr, uint32_t expected, uint32_t new, uint32_t *actualp)
273{
274	struct ufetchstore_test_args args = {
275		.uaddr64 = UADDR(uaddr),
276		.test_op = OP_CAS,
277		.size = 32,
278		.val32 = new,
279		.ea_val32 = expected,
280	};
281
282	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
283	*actualp = args.ea_val32;
284	return args.fetchstore_error;
285}
286
287#ifdef _LP64
288static int
289do_ucas_64(uint64_t *uaddr, uint64_t expected, uint64_t new, uint64_t *actualp)
290{
291	struct ufetchstore_test_args args = {
292		.uaddr64 = UADDR(uaddr),
293		.test_op = OP_CAS,
294		.size = 64,
295		.val64 = new,
296		.ea_val64 = expected,
297	};
298
299	ATF_REQUIRE_EQ(do_sysctl(&args), 0);
300	*actualp = args.ea_val64;
301	return args.fetchstore_error;
302}
303#endif /* _LP64 */
304
305struct memory_cell {
306	unsigned long guard0;
307	union {
308		unsigned long test_cell;
309#ifdef _LP64
310		uint64_t val64;
311#endif
312		uint32_t val32[sizeof(long) / 4];
313		uint16_t val16[sizeof(long) / 2];
314		uint8_t  val8 [sizeof(long)    ];
315	};
316	unsigned long guard1;
317};
318
319#define	index8		1
320#define	index16		1
321#define	index32		0
322
323#define	test_pattern8	0xa5
324#define	test_pattern16	0x5a6b
325#define	test_pattern32	0xb01cafe1
326#ifdef _LP64
327#define	test_pattern64	0xcafedeadfeedbabe
328#endif
329
330#if _BYTE_ORDER == _LITTLE_ENDIAN
331#define	test_cell_val8	((unsigned long)test_pattern8  << (index8  * NBBY))
332#define	test_cell_val16	((unsigned long)test_pattern16 << (index16 * NBBY*2))
333#define	test_cell_val32	((unsigned long)test_pattern32 << (index32 * NBBY*4))
334#ifdef _LP64
335#define	test_cell_val64	((unsigned long)test_pattern64)
336#endif
337#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
338
339#if _BYTE_ORDER == _BIG_ENDIAN
340#ifdef _LP64
341#define	test_cell_val8	((unsigned long)test_pattern8  << (56-(index8  * NBBY)))
342#define	test_cell_val16	((unsigned long)test_pattern16 << (48-(index16 * NBBY*2)))
343#define	test_cell_val32	((unsigned long)test_pattern32 << (32-(index32 * NBBY*4)))
344#define	test_cell_val64	((unsigned long)test_pattern64)
345#else /* ! _LP64 */
346#define	test_cell_val8	((unsigned long)test_pattern8  << (24-(index8  * NBBY)))
347#define	test_cell_val16	((unsigned long)test_pattern16 << (16-(index16 * NBBY*2)))
348#define	test_cell_val32	((unsigned long)test_pattern32)
349#endif /* _LP64 */
350#endif /* #if _BYTE_ORDER == _BIG_ENDIAN */
351
352#define	read_test_cell(cell)		(cell)->test_cell
353#define	write_test_cell(cell, v)	(cell)->test_cell = (v)
354
355#define	memory_cell_initializer		\
356	{				\
357		.guard0 = ULONG_MAX,	\
358		.test_cell = 0,		\
359		.guard1 = ULONG_MAX,	\
360	}
361
362static bool
363memory_cell_check_guard(const struct memory_cell * const cell)
364{
365	return cell->guard0 == ULONG_MAX &&
366	       cell->guard1 == ULONG_MAX;
367}
368
369ATF_TC_WITH_CLEANUP(ufetch_8);
370ATF_TC_HEAD(ufetch_8, tc)
371{
372	atf_tc_set_md_var(tc, "descr",
373	    "test for correct ufetch_8 behavior");
374}
375ATF_TC_BODY(ufetch_8, tc)
376{
377	struct memory_cell cell = memory_cell_initializer;
378	uint8_t res;
379
380	CHECK_MODULE();
381
382	write_test_cell(&cell, test_cell_val8);
383	ATF_REQUIRE_EQ(do_ufetch_8(&cell.val8[index8], &res), 0);
384	ATF_REQUIRE(memory_cell_check_guard(&cell));
385	ATF_REQUIRE(res == test_pattern8);
386}
387ATF_TC_CLEANUP(ufetch_8, tc)
388{
389	unload_module();
390}
391
392ATF_TC_WITH_CLEANUP(ufetch_16);
393ATF_TC_HEAD(ufetch_16, tc)
394{
395	atf_tc_set_md_var(tc, "descr",
396	    "test for correct ufetch_16 behavior");
397}
398ATF_TC_BODY(ufetch_16, tc)
399{
400	struct memory_cell cell = memory_cell_initializer;
401	uint16_t res;
402
403	CHECK_MODULE();
404
405	write_test_cell(&cell, test_cell_val16);
406	ATF_REQUIRE_EQ(do_ufetch_16(&cell.val16[index16], &res), 0);
407	ATF_REQUIRE(memory_cell_check_guard(&cell));
408	ATF_REQUIRE(res == test_pattern16);
409}
410ATF_TC_CLEANUP(ufetch_16, tc)
411{
412	unload_module();
413}
414
415ATF_TC_WITH_CLEANUP(ufetch_32);
416ATF_TC_HEAD(ufetch_32, tc)
417{
418	atf_tc_set_md_var(tc, "descr",
419	    "test for correct ufetch_32 behavior");
420}
421ATF_TC_BODY(ufetch_32, tc)
422{
423	struct memory_cell cell = memory_cell_initializer;
424	uint32_t res;
425
426	CHECK_MODULE();
427
428	write_test_cell(&cell, test_cell_val32);
429	ATF_REQUIRE_EQ(do_ufetch_32(&cell.val32[index32], &res), 0);
430	ATF_REQUIRE(memory_cell_check_guard(&cell));
431	ATF_REQUIRE(res == test_pattern32);
432}
433ATF_TC_CLEANUP(ufetch_32, tc)
434{
435	unload_module();
436}
437
438#ifdef _LP64
439ATF_TC_WITH_CLEANUP(ufetch_64);
440ATF_TC_HEAD(ufetch_64, tc)
441{
442	atf_tc_set_md_var(tc, "descr",
443	    "test for correct ufetch_64 behavior");
444}
445ATF_TC_BODY(ufetch_64, tc)
446{
447	struct memory_cell cell = memory_cell_initializer;
448	uint64_t res;
449
450	CHECK_MODULE();
451
452	write_test_cell(&cell, test_cell_val64);
453	ATF_REQUIRE_EQ(do_ufetch_64(&cell.val64, &res), 0);
454	ATF_REQUIRE(memory_cell_check_guard(&cell));
455	ATF_REQUIRE(res == test_pattern64);
456}
457ATF_TC_CLEANUP(ufetch_64, tc)
458{
459	unload_module();
460}
461#endif /* _LP64 */
462
463ATF_TC_WITH_CLEANUP(ufetch_8_null);
464ATF_TC_HEAD(ufetch_8_null, tc)
465{
466	atf_tc_set_md_var(tc, "descr",
467	    "test for correct ufetch_8 NULL pointer behavior");
468}
469ATF_TC_BODY(ufetch_8_null, tc)
470{
471	uint8_t res;
472
473	CHECK_MODULE();
474
475	ATF_REQUIRE_EQ(do_ufetch_8(NULL, &res), EFAULT);
476}
477ATF_TC_CLEANUP(ufetch_8_null, tc)
478{
479	unload_module();
480}
481
482ATF_TC_WITH_CLEANUP(ufetch_16_null);
483ATF_TC_HEAD(ufetch_16_null, tc)
484{
485	atf_tc_set_md_var(tc, "descr",
486	    "test for correct ufetch_16 NULL pointer behavior");
487}
488ATF_TC_BODY(ufetch_16_null, tc)
489{
490	uint16_t res;
491
492	CHECK_MODULE();
493
494	ATF_REQUIRE_EQ(do_ufetch_16(NULL, &res), EFAULT);
495}
496ATF_TC_CLEANUP(ufetch_16_null, tc)
497{
498	unload_module();
499}
500
501ATF_TC_WITH_CLEANUP(ufetch_32_null);
502ATF_TC_HEAD(ufetch_32_null, tc)
503{
504	atf_tc_set_md_var(tc, "descr",
505	    "test for correct ufetch_32 NULL pointer behavior");
506}
507ATF_TC_BODY(ufetch_32_null, tc)
508{
509	uint32_t res;
510
511	CHECK_MODULE();
512
513	ATF_REQUIRE_EQ(do_ufetch_32(NULL, &res), EFAULT);
514}
515ATF_TC_CLEANUP(ufetch_32_null, tc)
516{
517	unload_module();
518}
519
520#ifdef _LP64
521ATF_TC_WITH_CLEANUP(ufetch_64_null);
522ATF_TC_HEAD(ufetch_64_null, tc)
523{
524	atf_tc_set_md_var(tc, "descr",
525	    "test for correct ufetch_64 NULL pointer behavior");
526}
527ATF_TC_BODY(ufetch_64_null, tc)
528{
529	uint64_t res;
530
531	CHECK_MODULE();
532
533	ATF_REQUIRE_EQ(do_ufetch_64(NULL, &res), EFAULT);
534}
535ATF_TC_CLEANUP(ufetch_64_null, tc)
536{
537	unload_module();
538}
539#endif /* _LP64 */
540
541ATF_TC_WITH_CLEANUP(ufetch_8_max);
542ATF_TC_HEAD(ufetch_8_max, tc)
543{
544	atf_tc_set_md_var(tc, "descr",
545	    "test for correct ufetch_8 VM_MAX_ADDRESS pointer behavior");
546}
547ATF_TC_BODY(ufetch_8_max, tc)
548{
549	uint8_t res;
550
551	CHECK_MODULE();
552
553	ATF_REQUIRE_EQ(do_ufetch_8(vm_max_address(), &res), EFAULT);
554}
555ATF_TC_CLEANUP(ufetch_8_max, tc)
556{
557	unload_module();
558}
559
560ATF_TC_WITH_CLEANUP(ufetch_16_max);
561ATF_TC_HEAD(ufetch_16_max, tc)
562{
563	atf_tc_set_md_var(tc, "descr",
564	    "test for correct ufetch_16 VM_MAX_ADDRESS pointer behavior");
565}
566ATF_TC_BODY(ufetch_16_max, tc)
567{
568	uint16_t res;
569
570	CHECK_MODULE();
571
572	ATF_REQUIRE_EQ(do_ufetch_16(vm_max_address(), &res), EFAULT);
573}
574ATF_TC_CLEANUP(ufetch_16_max, tc)
575{
576	unload_module();
577}
578
579ATF_TC_WITH_CLEANUP(ufetch_32_max);
580ATF_TC_HEAD(ufetch_32_max, tc)
581{
582	atf_tc_set_md_var(tc, "descr",
583	    "test for correct ufetch_32 VM_MAX_ADDRESS pointer behavior");
584}
585ATF_TC_BODY(ufetch_32_max, tc)
586{
587	uint32_t res;
588
589	CHECK_MODULE();
590
591	ATF_REQUIRE_EQ(do_ufetch_32(vm_max_address(), &res), EFAULT);
592}
593ATF_TC_CLEANUP(ufetch_32_max, tc)
594{
595	unload_module();
596}
597
598#ifdef _LP64
599ATF_TC_WITH_CLEANUP(ufetch_64_max);
600ATF_TC_HEAD(ufetch_64_max, tc)
601{
602	atf_tc_set_md_var(tc, "descr",
603	    "test for correct ufetch_64 VM_MAX_ADDRESS pointer behavior");
604}
605ATF_TC_BODY(ufetch_64_max, tc)
606{
607	uint64_t res;
608
609	CHECK_MODULE();
610
611	ATF_REQUIRE_EQ(do_ufetch_64(vm_max_address(), &res), EFAULT);
612}
613ATF_TC_CLEANUP(ufetch_64_max, tc)
614{
615	unload_module();
616}
617#endif /* _LP64 */
618
619ATF_TC_WITH_CLEANUP(ufetch_16_nearmax_overflow);
620ATF_TC_HEAD(ufetch_16_nearmax_overflow, tc)
621{
622	atf_tc_set_md_var(tc, "descr",
623	    "test for correct ufetch_16 near-VM_MAX_ADDRESS pointer behavior");
624}
625ATF_TC_BODY(ufetch_16_nearmax_overflow, tc)
626{
627	uint16_t res;
628
629	CHECK_MODULE();
630
631	/*
632	 * For no-strict-alignment platforms: address checks must return
633	 * EFAULT.
634	 *
635	 * For strict-alignment platforms: alignment checks must return
636	 * EFAULT.
637	 */
638	ATF_REQUIRE_EQ(do_ufetch_16(vm_max_address_minus(1), &res), EFAULT);
639}
640ATF_TC_CLEANUP(ufetch_16_nearmax_overflow, tc)
641{
642	unload_module();
643}
644
645ATF_TC_WITH_CLEANUP(ufetch_32_nearmax_overflow);
646ATF_TC_HEAD(ufetch_32_nearmax_overflow, tc)
647{
648	atf_tc_set_md_var(tc, "descr",
649	    "test for correct ufetch_32 near-VM_MAX_ADDRESS pointer behavior");
650}
651ATF_TC_BODY(ufetch_32_nearmax_overflow, tc)
652{
653	uint32_t res;
654
655	CHECK_MODULE();
656
657	/*
658	 * For no-strict-alignment platforms: address checks must return
659	 * EFAULT.
660	 *
661	 * For strict-alignment platforms: alignment checks must return
662	 * EFAULT.
663	 */
664	ATF_REQUIRE_EQ(do_ufetch_32(vm_max_address_minus(3), &res), EFAULT);
665}
666ATF_TC_CLEANUP(ufetch_32_nearmax_overflow, tc)
667{
668	unload_module();
669}
670
671#ifdef _LP64
672ATF_TC_WITH_CLEANUP(ufetch_64_nearmax_overflow);
673ATF_TC_HEAD(ufetch_64_nearmax_overflow, tc)
674{
675	atf_tc_set_md_var(tc, "descr",
676	    "test for correct ufetch_64 near-VM_MAX_ADDRESS pointer behavior");
677}
678ATF_TC_BODY(ufetch_64_nearmax_overflow, tc)
679{
680	uint64_t res;
681
682	CHECK_MODULE();
683
684	/*
685	 * For no-strict-alignment platforms: address checks must return
686	 * EFAULT.
687	 *
688	 * For strict-alignment platforms: alignment checks must return
689	 * EFAULT.
690	 */
691	ATF_REQUIRE_EQ(do_ufetch_64(vm_max_address_minus(7), &res), EFAULT);
692}
693ATF_TC_CLEANUP(ufetch_64_nearmax_overflow, tc)
694{
695	unload_module();
696}
697#endif /* _LP64 */
698
699
700ATF_TC_WITH_CLEANUP(ustore_8);
701ATF_TC_HEAD(ustore_8, tc)
702{
703	atf_tc_set_md_var(tc, "descr",
704	    "test for correct ustore_8 behavior");
705}
706ATF_TC_BODY(ustore_8, tc)
707{
708	struct memory_cell cell = memory_cell_initializer;
709
710	CHECK_MODULE();
711
712	ATF_REQUIRE_EQ(do_ustore_8(&cell.val8[index8], test_pattern8), 0);
713	ATF_REQUIRE(memory_cell_check_guard(&cell));
714	ATF_REQUIRE(read_test_cell(&cell) == test_cell_val8);
715}
716ATF_TC_CLEANUP(ustore_8, tc)
717{
718	unload_module();
719}
720
721ATF_TC_WITH_CLEANUP(ustore_16);
722ATF_TC_HEAD(ustore_16, tc)
723{
724	atf_tc_set_md_var(tc, "descr",
725	    "test for correct ustore_16 behavior");
726}
727ATF_TC_BODY(ustore_16, tc)
728{
729	struct memory_cell cell = memory_cell_initializer;
730
731	CHECK_MODULE();
732
733	ATF_REQUIRE_EQ(do_ustore_16(&cell.val16[index16], test_pattern16), 0);
734	ATF_REQUIRE(memory_cell_check_guard(&cell));
735	ATF_REQUIRE(read_test_cell(&cell) == test_cell_val16);
736}
737ATF_TC_CLEANUP(ustore_16, tc)
738{
739	unload_module();
740}
741
742ATF_TC_WITH_CLEANUP(ustore_32);
743ATF_TC_HEAD(ustore_32, tc)
744{
745	atf_tc_set_md_var(tc, "descr",
746	    "test for correct ustore_32 behavior");
747}
748ATF_TC_BODY(ustore_32, tc)
749{
750	struct memory_cell cell = memory_cell_initializer;
751
752	CHECK_MODULE();
753
754	ATF_REQUIRE_EQ(do_ustore_32(&cell.val32[index32], test_pattern32), 0);
755	ATF_REQUIRE(memory_cell_check_guard(&cell));
756	ATF_REQUIRE(read_test_cell(&cell) == test_cell_val32);
757}
758ATF_TC_CLEANUP(ustore_32, tc)
759{
760	unload_module();
761}
762
763#ifdef _LP64
764ATF_TC_WITH_CLEANUP(ustore_64);
765ATF_TC_HEAD(ustore_64, tc)
766{
767	atf_tc_set_md_var(tc, "descr",
768	    "test for correct ustore_64 behavior");
769}
770ATF_TC_BODY(ustore_64, tc)
771{
772	struct memory_cell cell = memory_cell_initializer;
773
774	CHECK_MODULE();
775
776	ATF_REQUIRE_EQ(do_ustore_64(&cell.val64, test_pattern64), 0);
777	ATF_REQUIRE(memory_cell_check_guard(&cell));
778	ATF_REQUIRE(read_test_cell(&cell) == test_cell_val64);
779}
780ATF_TC_CLEANUP(ustore_64, tc)
781{
782	unload_module();
783}
784#endif /* _LP64 */
785
786ATF_TC_WITH_CLEANUP(ustore_8_null);
787ATF_TC_HEAD(ustore_8_null, tc)
788{
789	atf_tc_set_md_var(tc, "descr",
790	    "test for correct ustore_8 NULL pointer behavior");
791}
792ATF_TC_BODY(ustore_8_null, tc)
793{
794	CHECK_MODULE();
795
796	ATF_REQUIRE_EQ(do_ustore_8(NULL, 0), EFAULT);
797}
798ATF_TC_CLEANUP(ustore_8_null, tc)
799{
800	unload_module();
801}
802
803ATF_TC_WITH_CLEANUP(ustore_16_null);
804ATF_TC_HEAD(ustore_16_null, tc)
805{
806	atf_tc_set_md_var(tc, "descr",
807	    "test for correct ustore_16 NULL pointer behavior");
808}
809ATF_TC_BODY(ustore_16_null, tc)
810{
811	CHECK_MODULE();
812
813	ATF_REQUIRE_EQ(do_ustore_16(NULL, 0), EFAULT);
814}
815ATF_TC_CLEANUP(ustore_16_null, tc)
816{
817	unload_module();
818}
819
820ATF_TC_WITH_CLEANUP(ustore_32_null);
821ATF_TC_HEAD(ustore_32_null, tc)
822{
823	atf_tc_set_md_var(tc, "descr",
824	    "test for correct ustore_32 NULL pointer behavior");
825}
826ATF_TC_BODY(ustore_32_null, tc)
827{
828	CHECK_MODULE();
829
830	ATF_REQUIRE_EQ(do_ustore_32(NULL, 0), EFAULT);
831}
832ATF_TC_CLEANUP(ustore_32_null, tc)
833{
834	unload_module();
835}
836
837#ifdef _LP64
838ATF_TC_WITH_CLEANUP(ustore_64_null);
839ATF_TC_HEAD(ustore_64_null, tc)
840{
841	atf_tc_set_md_var(tc, "descr",
842	    "test for correct ustore_64 NULL pointer behavior");
843}
844ATF_TC_BODY(ustore_64_null, tc)
845{
846	CHECK_MODULE();
847
848	ATF_REQUIRE_EQ(do_ustore_64(NULL, 0), EFAULT);
849}
850ATF_TC_CLEANUP(ustore_64_null, tc)
851{
852	unload_module();
853}
854#endif /* _LP64 */
855
856ATF_TC_WITH_CLEANUP(ustore_8_max);
857ATF_TC_HEAD(ustore_8_max, tc)
858{
859	atf_tc_set_md_var(tc, "descr",
860	    "test for correct ustore_8 VM_MAX_ADDRESS pointer behavior");
861}
862ATF_TC_BODY(ustore_8_max, tc)
863{
864	CHECK_MODULE();
865
866	ATF_REQUIRE_EQ(do_ustore_8(vm_max_address(), 0), EFAULT);
867}
868ATF_TC_CLEANUP(ustore_8_max, tc)
869{
870	unload_module();
871}
872
873ATF_TC_WITH_CLEANUP(ustore_16_max);
874ATF_TC_HEAD(ustore_16_max, tc)
875{
876	atf_tc_set_md_var(tc, "descr",
877	    "test for correct ustore_16 VM_MAX_ADDRESS pointer behavior");
878}
879ATF_TC_BODY(ustore_16_max, tc)
880{
881	CHECK_MODULE();
882
883	ATF_REQUIRE_EQ(do_ustore_16(vm_max_address(), 0), EFAULT);
884}
885ATF_TC_CLEANUP(ustore_16_max, tc)
886{
887	unload_module();
888}
889
890ATF_TC_WITH_CLEANUP(ustore_32_max);
891ATF_TC_HEAD(ustore_32_max, tc)
892{
893	atf_tc_set_md_var(tc, "descr",
894	    "test for correct ustore_32 VM_MAX_ADDRESS pointer behavior");
895}
896ATF_TC_BODY(ustore_32_max, tc)
897{
898	CHECK_MODULE();
899
900	ATF_REQUIRE_EQ(do_ustore_32(vm_max_address(), 0), EFAULT);
901}
902ATF_TC_CLEANUP(ustore_32_max, tc)
903{
904	unload_module();
905}
906
907#ifdef _LP64
908ATF_TC_WITH_CLEANUP(ustore_64_max);
909ATF_TC_HEAD(ustore_64_max, tc)
910{
911	atf_tc_set_md_var(tc, "descr",
912	    "test for correct ustore_64 VM_MAX_ADDRESS pointer behavior");
913}
914ATF_TC_BODY(ustore_64_max, tc)
915{
916	CHECK_MODULE();
917
918	ATF_REQUIRE_EQ(do_ustore_64(vm_max_address(), 0), EFAULT);
919}
920ATF_TC_CLEANUP(ustore_64_max, tc)
921{
922	unload_module();
923}
924#endif /* _LP64 */
925
926ATF_TC_WITH_CLEANUP(ustore_16_nearmax_overflow);
927ATF_TC_HEAD(ustore_16_nearmax_overflow, tc)
928{
929	atf_tc_set_md_var(tc, "descr",
930	    "test for correct ustore_16 VM_MAX_ADDRESS pointer behavior");
931}
932ATF_TC_BODY(ustore_16_nearmax_overflow, tc)
933{
934	CHECK_MODULE();
935
936	/*
937	 * For no-strict-alignment platforms: address checks must return
938	 * EFAULT.
939	 *
940	 * For strict-alignment platforms: alignment checks must return
941	 * EFAULT.
942	 */
943	ATF_REQUIRE_EQ(do_ustore_16(vm_max_address_minus(1), 0), EFAULT);
944}
945ATF_TC_CLEANUP(ustore_16_nearmax_overflow, tc)
946{
947	unload_module();
948}
949
950ATF_TC_WITH_CLEANUP(ustore_32_nearmax_overflow);
951ATF_TC_HEAD(ustore_32_nearmax_overflow, tc)
952{
953	atf_tc_set_md_var(tc, "descr",
954	    "test for correct ustore_32 VM_MAX_ADDRESS pointer behavior");
955}
956ATF_TC_BODY(ustore_32_nearmax_overflow, tc)
957{
958	CHECK_MODULE();
959
960	/*
961	 * For no-strict-alignment platforms: address checks must return
962	 * EFAULT.
963	 *
964	 * For strict-alignment platforms: alignment checks must return
965	 * EFAULT.
966	 */
967	ATF_REQUIRE_EQ(do_ustore_32(vm_max_address_minus(3), 0), EFAULT);
968}
969ATF_TC_CLEANUP(ustore_32_nearmax_overflow, tc)
970{
971	unload_module();
972}
973
974#ifdef _LP64
975ATF_TC_WITH_CLEANUP(ustore_64_nearmax_overflow);
976ATF_TC_HEAD(ustore_64_nearmax_overflow, tc)
977{
978	atf_tc_set_md_var(tc, "descr",
979	    "test for correct ustore_64 VM_MAX_ADDRESS pointer behavior");
980}
981ATF_TC_BODY(ustore_64_nearmax_overflow, tc)
982{
983	CHECK_MODULE();
984
985	/*
986	 * For no-strict-alignment platforms: address checks must return
987	 * EFAULT.
988	 *
989	 * For strict-alignment platforms: alignment checks must return
990	 * EFAULT.
991	 */
992	ATF_REQUIRE_EQ(do_ustore_64(vm_max_address_minus(7), 0), EFAULT);
993}
994ATF_TC_CLEANUP(ustore_64_nearmax_overflow, tc)
995{
996	unload_module();
997}
998#endif /* _LP64 */
999
1000
1001ATF_TC_WITH_CLEANUP(ucas_32);
1002ATF_TC_HEAD(ucas_32, tc)
1003{
1004	atf_tc_set_md_var(tc, "descr",
1005	    "test for correct ucas_32 behavior");
1006}
1007ATF_TC_BODY(ucas_32, tc)
1008{
1009	uint32_t cell = 0xdeadbeef;
1010	uint32_t actual = 0;
1011
1012	CHECK_MODULE();
1013
1014	ATF_REQUIRE_EQ(do_ucas_32(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0);
1015	ATF_REQUIRE(actual == 0xdeadbeef);
1016	ATF_REQUIRE(cell == 0xbeefdead);
1017}
1018ATF_TC_CLEANUP(ucas_32, tc)
1019{
1020	unload_module();
1021}
1022
1023#ifdef _LP64
1024ATF_TC_WITH_CLEANUP(ucas_64);
1025ATF_TC_HEAD(ucas_64, tc)
1026{
1027	atf_tc_set_md_var(tc, "descr",
1028	    "test for correct ucas_64 behavior");
1029}
1030ATF_TC_BODY(ucas_64, tc)
1031{
1032	uint64_t cell = 0xdeadbeef;
1033	uint64_t actual = 0;
1034
1035	CHECK_MODULE();
1036
1037	ATF_REQUIRE_EQ(do_ucas_64(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0);
1038	ATF_REQUIRE(actual == 0xdeadbeef);
1039	ATF_REQUIRE(cell == 0xbeefdead);
1040}
1041ATF_TC_CLEANUP(ucas_64, tc)
1042{
1043	unload_module();
1044}
1045#endif /* _LP64 */
1046
1047ATF_TC_WITH_CLEANUP(ucas_32_miscompare);
1048ATF_TC_HEAD(ucas_32_miscompare, tc)
1049{
1050	atf_tc_set_md_var(tc, "descr",
1051	    "test for correct ucas_32 behavior with miscompare");
1052}
1053ATF_TC_BODY(ucas_32_miscompare, tc)
1054{
1055	uint32_t cell = 0xa5a5a5a5;
1056	uint32_t actual = 0;
1057
1058	CHECK_MODULE();
1059
1060	ATF_REQUIRE_EQ(do_ucas_32(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0);
1061	ATF_REQUIRE(actual == 0xa5a5a5a5);
1062	ATF_REQUIRE(cell == 0xa5a5a5a5);
1063}
1064ATF_TC_CLEANUP(ucas_32_miscompare, tc)
1065{
1066	unload_module();
1067}
1068
1069#ifdef _LP64
1070ATF_TC_WITH_CLEANUP(ucas_64_miscompare);
1071ATF_TC_HEAD(ucas_64_miscompare, tc)
1072{
1073	atf_tc_set_md_var(tc, "descr",
1074	    "test for correct ucas_64 behavior with miscompare");
1075}
1076ATF_TC_BODY(ucas_64_miscompare, tc)
1077{
1078	uint64_t cell = 0xa5a5a5a5;
1079	uint64_t actual = 0;
1080
1081	CHECK_MODULE();
1082
1083	ATF_REQUIRE_EQ(do_ucas_64(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0);
1084	ATF_REQUIRE(actual == 0xa5a5a5a5);
1085	ATF_REQUIRE(cell == 0xa5a5a5a5);
1086}
1087ATF_TC_CLEANUP(ucas_64_miscompare, tc)
1088{
1089	unload_module();
1090}
1091#endif /* _LP64 */
1092
1093ATF_TC_WITH_CLEANUP(ucas_32_null);
1094ATF_TC_HEAD(ucas_32_null, tc)
1095{
1096	atf_tc_set_md_var(tc, "descr",
1097	    "test for correct ucas_32 NULL pointer behavior");
1098}
1099ATF_TC_BODY(ucas_32_null, tc)
1100{
1101	uint32_t actual = 0;
1102
1103	CHECK_MODULE();
1104
1105	ATF_REQUIRE_EQ(do_ucas_32(NULL, 0xdeadbeef, 0xbeefdead, &actual),
1106	    EFAULT);
1107}
1108ATF_TC_CLEANUP(ucas_32_null, tc)
1109{
1110	unload_module();
1111}
1112
1113#ifdef _LP64
1114ATF_TC_WITH_CLEANUP(ucas_64_null);
1115ATF_TC_HEAD(ucas_64_null, tc)
1116{
1117	atf_tc_set_md_var(tc, "descr",
1118	    "test for correct ucas_64 NULL pointer behavior");
1119}
1120ATF_TC_BODY(ucas_64_null, tc)
1121{
1122	uint64_t actual = 0;
1123
1124	CHECK_MODULE();
1125
1126	ATF_REQUIRE_EQ(do_ucas_64(NULL, 0xdeadbeef, 0xbeefdead, &actual),
1127	    EFAULT);
1128}
1129ATF_TC_CLEANUP(ucas_64_null, tc)
1130{
1131	unload_module();
1132}
1133#endif /* _LP64 */
1134
1135ATF_TC_WITH_CLEANUP(ucas_32_max);
1136ATF_TC_HEAD(ucas_32_max, tc)
1137{
1138	atf_tc_set_md_var(tc, "descr",
1139	    "test for correct ucas_32 VM_MAX_ADDRESS pointer behavior");
1140}
1141ATF_TC_BODY(ucas_32_max, tc)
1142{
1143	uint32_t actual = 0;
1144
1145	CHECK_MODULE();
1146
1147	ATF_REQUIRE_EQ(do_ucas_32(vm_max_address(), 0xdeadbeef, 0xbeefdead,
1148	    &actual), EFAULT);
1149}
1150ATF_TC_CLEANUP(ucas_32_max, tc)
1151{
1152	unload_module();
1153}
1154
1155#ifdef _LP64
1156ATF_TC_WITH_CLEANUP(ucas_64_max);
1157ATF_TC_HEAD(ucas_64_max, tc)
1158{
1159	atf_tc_set_md_var(tc, "descr",
1160	    "test for correct ucas_64 VM_MAX_ADDRESS pointer behavior");
1161}
1162ATF_TC_BODY(ucas_64_max, tc)
1163{
1164	uint64_t actual = 0;
1165
1166	CHECK_MODULE();
1167
1168	ATF_REQUIRE_EQ(do_ucas_64(vm_max_address(), 0xdeadbeef, 0xbeefdead,
1169	    &actual), EFAULT);
1170}
1171ATF_TC_CLEANUP(ucas_64_max, tc)
1172{
1173	unload_module();
1174}
1175#endif /* _LP64 */
1176
1177ATF_TC_WITH_CLEANUP(ucas_32_nearmax_overflow);
1178ATF_TC_HEAD(ucas_32_nearmax_overflow, tc)
1179{
1180	atf_tc_set_md_var(tc, "descr",
1181	    "test for correct ucas_32 near-VM_MAX_ADDRESS pointer behavior");
1182}
1183ATF_TC_BODY(ucas_32_nearmax_overflow, tc)
1184{
1185	uint32_t actual = 0;
1186
1187	CHECK_MODULE();
1188
1189	/*
1190	 * For no-strict-alignment platforms: address checks must return
1191	 * EFAULT.
1192	 *
1193	 * For strict-alignment platforms: alignment checks must return
1194	 * EFAULT.
1195	 */
1196	ATF_REQUIRE_EQ(do_ucas_32(vm_max_address_minus(3), 0xdeadbeef,
1197	    0xbeefdead, &actual), EFAULT);
1198}
1199ATF_TC_CLEANUP(ucas_32_nearmax_overflow, tc)
1200{
1201	unload_module();
1202}
1203
1204#ifdef _LP64
1205ATF_TC_WITH_CLEANUP(ucas_64_nearmax_overflow);
1206ATF_TC_HEAD(ucas_64_nearmax_overflow, tc)
1207{
1208	atf_tc_set_md_var(tc, "descr",
1209	    "test for correct ucas_64 near-VM_MAX_ADDRESS pointer behavior");
1210}
1211ATF_TC_BODY(ucas_64_nearmax_overflow, tc)
1212{
1213	uint64_t actual = 0;
1214
1215	CHECK_MODULE();
1216
1217	/*
1218	 * For no-strict-alignment platforms: address checks must return
1219	 * EFAULT.
1220	 *
1221	 * For strict-alignment platforms: alignment checks must return
1222	 * EFAULT.
1223	 */
1224	ATF_REQUIRE_EQ(do_ucas_64(vm_max_address_minus(7), 0xdeadbeef,
1225	    0xbeefdead, &actual), EFAULT);
1226}
1227ATF_TC_CLEANUP(ucas_64_nearmax_overflow, tc)
1228{
1229	unload_module();
1230}
1231#endif /* _LP64 */
1232
1233ATF_TP_ADD_TCS(tp)
1234{
1235	ATF_TP_ADD_TC(tp, ufetch_8);
1236	ATF_TP_ADD_TC(tp, ufetch_16);
1237	ATF_TP_ADD_TC(tp, ufetch_32);
1238#ifdef _LP64
1239	ATF_TP_ADD_TC(tp, ufetch_64);
1240#endif
1241
1242	ATF_TP_ADD_TC(tp, ufetch_8_null);
1243	ATF_TP_ADD_TC(tp, ufetch_16_null);
1244	ATF_TP_ADD_TC(tp, ufetch_32_null);
1245#ifdef _LP64
1246	ATF_TP_ADD_TC(tp, ufetch_64_null);
1247#endif
1248
1249	ATF_TP_ADD_TC(tp, ufetch_8_max);
1250	ATF_TP_ADD_TC(tp, ufetch_16_max);
1251	ATF_TP_ADD_TC(tp, ufetch_32_max);
1252#ifdef _LP64
1253	ATF_TP_ADD_TC(tp, ufetch_64_max);
1254#endif
1255
1256	ATF_TP_ADD_TC(tp, ufetch_16_nearmax_overflow);
1257	ATF_TP_ADD_TC(tp, ufetch_32_nearmax_overflow);
1258#ifdef _LP64
1259	ATF_TP_ADD_TC(tp, ufetch_64_nearmax_overflow);
1260#endif
1261
1262	ATF_TP_ADD_TC(tp, ustore_8);
1263	ATF_TP_ADD_TC(tp, ustore_16);
1264	ATF_TP_ADD_TC(tp, ustore_32);
1265#ifdef _LP64
1266	ATF_TP_ADD_TC(tp, ustore_64);
1267#endif
1268
1269	ATF_TP_ADD_TC(tp, ustore_8_null);
1270	ATF_TP_ADD_TC(tp, ustore_16_null);
1271	ATF_TP_ADD_TC(tp, ustore_32_null);
1272#ifdef _LP64
1273	ATF_TP_ADD_TC(tp, ustore_64_null);
1274#endif
1275
1276	ATF_TP_ADD_TC(tp, ustore_8_max);
1277	ATF_TP_ADD_TC(tp, ustore_16_max);
1278	ATF_TP_ADD_TC(tp, ustore_32_max);
1279#ifdef _LP64
1280	ATF_TP_ADD_TC(tp, ustore_64_max);
1281#endif
1282
1283	ATF_TP_ADD_TC(tp, ustore_16_nearmax_overflow);
1284	ATF_TP_ADD_TC(tp, ustore_32_nearmax_overflow);
1285#ifdef _LP64
1286	ATF_TP_ADD_TC(tp, ustore_64_nearmax_overflow);
1287#endif
1288
1289	ATF_TP_ADD_TC(tp, ucas_32);
1290#ifdef _LP64
1291	ATF_TP_ADD_TC(tp, ucas_64);
1292#endif
1293
1294	ATF_TP_ADD_TC(tp, ucas_32_miscompare);
1295#ifdef _LP64
1296	ATF_TP_ADD_TC(tp, ucas_64_miscompare);
1297#endif
1298
1299	ATF_TP_ADD_TC(tp, ucas_32_null);
1300#ifdef _LP64
1301	ATF_TP_ADD_TC(tp, ucas_64_null);
1302#endif
1303
1304	ATF_TP_ADD_TC(tp, ucas_32_max);
1305#ifdef _LP64
1306	ATF_TP_ADD_TC(tp, ucas_64_max);
1307#endif
1308
1309	ATF_TP_ADD_TC(tp, ucas_32_nearmax_overflow);
1310#ifdef _LP64
1311	ATF_TP_ADD_TC(tp, ucas_64_nearmax_overflow);
1312#endif
1313
1314	return atf_no_error();
1315}
1316