Module Name: src Committed By: christos Date: Mon Apr 15 23:41:23 UTC 2019
Modified Files: src/tests/modules: Makefile src/tests/modules/ufetchstore: Makefile Added Files: src/tests/modules: t_ufetchstore.c src/tests/modules/ufetchstore: common.h ufetchstore_tester.c Removed Files: src/tests/modules/ufetchstore: Makefile.inc src/tests/modules/ufetchstore/module: Makefile common.h ufetchstore_tester.c Log Message: Re-arrange the ufetchstore tests to look like the other ones. To generate a diff of this commit: cvs rdiff -u -r1.16 -r1.17 src/tests/modules/Makefile cvs rdiff -u -r0 -r1.1 src/tests/modules/t_ufetchstore.c cvs rdiff -u -r1.2 -r1.3 src/tests/modules/ufetchstore/Makefile cvs rdiff -u -r1.1 -r0 src/tests/modules/ufetchstore/Makefile.inc cvs rdiff -u -r0 -r1.1 src/tests/modules/ufetchstore/common.h \ src/tests/modules/ufetchstore/ufetchstore_tester.c cvs rdiff -u -r1.1 -r0 src/tests/modules/ufetchstore/module/Makefile \ src/tests/modules/ufetchstore/module/common.h \ src/tests/modules/ufetchstore/module/ufetchstore_tester.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/modules/Makefile diff -u src/tests/modules/Makefile:1.16 src/tests/modules/Makefile:1.17 --- src/tests/modules/Makefile:1.16 Fri Apr 5 23:06:29 2019 +++ src/tests/modules/Makefile Mon Apr 15 19:41:23 2019 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.16 2019/04/06 03:06:29 thorpej Exp $ +# $NetBSD: Makefile,v 1.17 2019/04/15 23:41:23 christos Exp $ .include <bsd.own.mk> @@ -13,8 +13,12 @@ CPPFLAGS+= -D_KERNTYPES TESTS_C= t_modctl TESTS_C+= t_builtin TESTS_C+= t_kcov -LDADD= -lprop -LDADD+= -lrumpfs_kernfs -lrumpvfs -lrump -lrumpuser -lrump -lpthread +TESTS_C+= t_ufetchstore +CPPFLAGS.t_ufetchstore.c+=-I${.CURDIR}/ufetchstore +.for i in t_modctl t_builtin t_kcov +LDADD.${i}= -lprop +LDADD.${i}+= -lrumpfs_kernfs -lrumpvfs -lrump -lrumpuser -lrump -lpthread +.endfor TESTS_SH= t_abi_uvm TESTS_SH+= t_modload @@ -28,6 +32,4 @@ SUBDIR+= k_uvm SUBDIR+= threadpool_tester SUBDIR+= ufetchstore -ATFFILE_EXTRA_SUBDIRS= t_ufetchstore - .include <bsd.test.mk> Index: src/tests/modules/ufetchstore/Makefile diff -u src/tests/modules/ufetchstore/Makefile:1.2 src/tests/modules/ufetchstore/Makefile:1.3 --- src/tests/modules/ufetchstore/Makefile:1.2 Mon Apr 15 16:21:35 2019 +++ src/tests/modules/ufetchstore/Makefile Mon Apr 15 19:41:23 2019 @@ -1,17 +1,14 @@ -# $NetBSD: Makefile,v 1.2 2019/04/15 20:21:35 christos Exp $ +# $NetBSD: Makefile,v 1.3 2019/04/15 23:41:23 christos Exp $ .include <bsd.own.mk> -TESTSDIR= ${TESTSBASE}/modules/ufetchstore -CPPFLAGS+= -D_KERNTYPES -I${.CURDIR}/module +KMOD= ufetchstore_tester +KMODULEDIR= ${DESTDIR}/${TESTSBASE}/modules/${KMOD} -# Ideally this test could be in the parent Makefile, which could not descend -# into this directory at all. Unfortunately, the etc/mtree/NetBSD.dist file -# creates the 'modules' subdirectory unconditionally, which if left empty -# will confuse atf-run. Therefore we must install, at the very least, the -# Atffile into it. -TESTS_C= t_ufetchstore +SRCS= ufetchstore_tester.c -SUBDIR+= module +ATFFILE= no +NOMAN= # defined .include <bsd.test.mk> +.include <bsd.kmodule.mk> Added files: Index: src/tests/modules/t_ufetchstore.c diff -u /dev/null src/tests/modules/t_ufetchstore.c:1.1 --- /dev/null Mon Apr 15 19:41:23 2019 +++ src/tests/modules/t_ufetchstore.c Mon Apr 15 19:41:23 2019 @@ -0,0 +1,1315 @@ +/* $NetBSD: t_ufetchstore.c,v 1.1 2019/04/15 23:41:23 christos Exp $ */ + +/* + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__COPYRIGHT("@(#) Copyright (c) 2019\ + The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: t_ufetchstore.c,v 1.1 2019/04/15 23:41:23 christos Exp $"); + +#include <sys/types.h> +#include <sys/endian.h> +#include <sys/module.h> +#include <sys/sysctl.h> + +#include <err.h> +#include <errno.h> +#include <limits.h> + +#include <atf-c.h> + +#include "common.h" + +#define mib_name "kern.ufetchstore_test.test" + +static bool module_loaded; + +#define MODULE_PATH \ + "/usr/tests/modules/ufetchstore_tester/ufetchstore_tester.kmod" +#define MODULE_NAME "ufetchstore_tester" + +#define CHECK_MODULE() \ +do { \ + load_module(); \ + if (! module_loaded) { \ + atf_tc_skip("loading '%s' module failed.", MODULE_NAME);\ + } \ +} while (/*CONSTCOND*/0) + +static void +load_module(void) +{ +#ifndef SKIP_MODULE + if (module_loaded) + return; + + modctl_load_t params = { + .ml_filename = MODULE_PATH, + .ml_flags = MODCTL_NO_PROP, + }; + + if (modctl(MODCTL_LOAD, ¶ms) != 0) { + warn("failed to load module '%s'", MODULE_PATH); + } else { + module_loaded = true; + } +#else + module_loaded = true; +#endif /* ! SKIP_MODULE */ +} + +#define UADDR(x) ((uintptr_t)(x)) + +static void +unload_module(void) +{ +#ifndef SKIP_MODULE + char module_name[] = MODULE_NAME; + + if (modctl(MODCTL_UNLOAD, module_name) != 0) { + warn("failed to unload module '%s'", MODULE_NAME); + } else { + module_loaded = false; + } +#endif /* ! SKIP_MODULE */ +} + +static unsigned long +vm_max_address_raw(void) +{ + static unsigned long max_addr = 0; + int rv; + + if (max_addr == 0) { + size_t max_addr_size = sizeof(max_addr); + rv = sysctlbyname("vm.maxaddress", &max_addr, &max_addr_size, + NULL, 0); + if (rv != 0) + err(1, "sysctlbyname('vm.maxaddress')"); + } + return max_addr; +} + +static void * +vm_max_address(void) +{ + return (void *)vm_max_address_raw(); +} + +static void * +vm_max_address_minus(unsigned int adj) +{ + return (void *)(vm_max_address_raw() - adj); +} + +static int +do_sysctl(struct ufetchstore_test_args *args) +{ + uint64_t arg_addr64 = (uintptr_t)args; + int rv; + + args->fetchstore_error = EBADF; /* poison */ + args->pointer_size = (int)sizeof(void *); + + /* + * Yes, the intent is to provide the pointer, not the structure, + * to the kernel side of the test harness. + */ + rv = sysctlbyname(mib_name, NULL, NULL, &arg_addr64, + sizeof(arg_addr64)); + if (rv != 0) { + rv = errno; + warn("sysctlbyname('%s') -> %d", mib_name, rv); + return rv; + } + return 0; +} + +static int +do_ufetch_8(const uint8_t *uaddr, uint8_t *res) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_LOAD, + .size = 8, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *res = args.val8; + return args.fetchstore_error; +} + +static int +do_ufetch_16(const uint16_t *uaddr, uint16_t *res) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_LOAD, + .size = 16, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *res = args.val16; + return args.fetchstore_error; +} + +static int +do_ufetch_32(const uint32_t *uaddr, uint32_t *res) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_LOAD, + .size = 32, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *res = args.val32; + return args.fetchstore_error; +} + +#ifdef _LP64 +static int +do_ufetch_64(const uint64_t *uaddr, uint64_t *res) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_LOAD, + .size = 64, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *res = args.val64; + return args.fetchstore_error; +} +#endif /* _LP64 */ + +static int +do_ustore_8(uint8_t *uaddr, uint8_t val) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_STORE, + .size = 8, + .val8 = val, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + return args.fetchstore_error; +} + +static int +do_ustore_16(uint16_t *uaddr, uint16_t val) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_STORE, + .size = 16, + .val16 = val, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + return args.fetchstore_error; +} + +static int +do_ustore_32(uint32_t *uaddr, uint32_t val) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_STORE, + .size = 32, + .val32 = val, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + return args.fetchstore_error; +} + +#ifdef _LP64 +static int +do_ustore_64(uint64_t *uaddr, uint64_t val) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_STORE, + .size = 64, + .val64 = val, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + return args.fetchstore_error; +} +#endif /* _LP64 */ + +static int +do_ucas_32(uint32_t *uaddr, uint32_t expected, uint32_t new, uint32_t *actualp) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_CAS, + .size = 32, + .val32 = new, + .ea_val32 = expected, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *actualp = args.ea_val32; + return args.fetchstore_error; +} + +#ifdef _LP64 +static int +do_ucas_64(uint64_t *uaddr, uint64_t expected, uint64_t new, uint64_t *actualp) +{ + struct ufetchstore_test_args args = { + .uaddr64 = UADDR(uaddr), + .test_op = OP_CAS, + .size = 64, + .val64 = new, + .ea_val64 = expected, + }; + + ATF_REQUIRE_EQ(do_sysctl(&args), 0); + *actualp = args.ea_val64; + return args.fetchstore_error; +} +#endif /* _LP64 */ + +struct memory_cell { + unsigned long guard0; + union { + unsigned long test_cell; +#ifdef _LP64 + uint64_t val64; +#endif + uint32_t val32[sizeof(long) / 4]; + uint16_t val16[sizeof(long) / 2]; + uint8_t val8 [sizeof(long) ]; + }; + unsigned long guard1; +}; + +#define index8 1 +#define index16 1 +#define index32 0 + +#define test_pattern8 0xa5 +#define test_pattern16 0x5a6b +#define test_pattern32 0xb01cafe1 +#ifdef _LP64 +#define test_pattern64 0xcafedeadfeedbabe +#endif + +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define test_cell_val8 ((unsigned long)test_pattern8 << (index8 * NBBY)) +#define test_cell_val16 ((unsigned long)test_pattern16 << (index16 * NBBY*2)) +#define test_cell_val32 ((unsigned long)test_pattern32 << (index32 * NBBY*4)) +#ifdef _LP64 +#define test_cell_val64 ((unsigned long)test_pattern64) +#endif +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +#if _BYTE_ORDER == _BIG_ENDIAN +#ifdef _LP64 +#define test_cell_val8 ((unsigned long)test_pattern8 << (56-(index8 * NBBY))) +#define test_cell_val16 ((unsigned long)test_pattern16 << (48-(index16 * NBBY*2))) +#define test_cell_val32 ((unsigned long)test_pattern32 << (32-(index32 * NBBY*4))) +#define test_cell_val64 ((unsigned long)test_pattern64) +#else /* ! _LP64 */ +#define test_cell_val8 ((unsigned long)test_pattern8 << (24-(index8 * NBBY))) +#define test_cell_val16 ((unsigned long)test_pattern16 << (16-(index16 * NBBY*2))) +#define test_cell_val32 ((unsigned long)test_pattern32) +#endif /* _LP64 */ +#endif /* #if _BYTE_ORDER == _BIG_ENDIAN */ + +#define read_test_cell(cell) (cell)->test_cell +#define write_test_cell(cell, v) (cell)->test_cell = (v) + +#define memory_cell_initializer \ + { \ + .guard0 = ULONG_MAX, \ + .test_cell = 0, \ + .guard1 = ULONG_MAX, \ + } + +static bool +memory_cell_check_guard(const struct memory_cell * const cell) +{ + return cell->guard0 == ULONG_MAX && + cell->guard1 == ULONG_MAX; +} + +ATF_TC_WITH_CLEANUP(ufetch_8); +ATF_TC_HEAD(ufetch_8, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_8 behavior"); +} +ATF_TC_BODY(ufetch_8, tc) +{ + struct memory_cell cell = memory_cell_initializer; + uint8_t res; + + CHECK_MODULE(); + + write_test_cell(&cell, test_cell_val8); + ATF_REQUIRE_EQ(do_ufetch_8(&cell.val8[index8], &res), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(res == test_pattern8); +} +ATF_TC_CLEANUP(ufetch_8, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_16); +ATF_TC_HEAD(ufetch_16, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_16 behavior"); +} +ATF_TC_BODY(ufetch_16, tc) +{ + struct memory_cell cell = memory_cell_initializer; + uint16_t res; + + CHECK_MODULE(); + + write_test_cell(&cell, test_cell_val16); + ATF_REQUIRE_EQ(do_ufetch_16(&cell.val16[index16], &res), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(res == test_pattern16); +} +ATF_TC_CLEANUP(ufetch_16, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_32); +ATF_TC_HEAD(ufetch_32, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_32 behavior"); +} +ATF_TC_BODY(ufetch_32, tc) +{ + struct memory_cell cell = memory_cell_initializer; + uint32_t res; + + CHECK_MODULE(); + + write_test_cell(&cell, test_cell_val32); + ATF_REQUIRE_EQ(do_ufetch_32(&cell.val32[index32], &res), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(res == test_pattern32); +} +ATF_TC_CLEANUP(ufetch_32, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ufetch_64); +ATF_TC_HEAD(ufetch_64, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_64 behavior"); +} +ATF_TC_BODY(ufetch_64, tc) +{ + struct memory_cell cell = memory_cell_initializer; + uint64_t res; + + CHECK_MODULE(); + + write_test_cell(&cell, test_cell_val64); + ATF_REQUIRE_EQ(do_ufetch_64(&cell.val64, &res), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(res == test_pattern64); +} +ATF_TC_CLEANUP(ufetch_64, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ufetch_8_null); +ATF_TC_HEAD(ufetch_8_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_8 NULL pointer behavior"); +} +ATF_TC_BODY(ufetch_8_null, tc) +{ + uint8_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_8(NULL, &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_8_null, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_16_null); +ATF_TC_HEAD(ufetch_16_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_16 NULL pointer behavior"); +} +ATF_TC_BODY(ufetch_16_null, tc) +{ + uint16_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_16(NULL, &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_16_null, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_32_null); +ATF_TC_HEAD(ufetch_32_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_32 NULL pointer behavior"); +} +ATF_TC_BODY(ufetch_32_null, tc) +{ + uint32_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_32(NULL, &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_32_null, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ufetch_64_null); +ATF_TC_HEAD(ufetch_64_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_64 NULL pointer behavior"); +} +ATF_TC_BODY(ufetch_64_null, tc) +{ + uint64_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_64(NULL, &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_64_null, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ufetch_8_max); +ATF_TC_HEAD(ufetch_8_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_8 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_8_max, tc) +{ + uint8_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_8(vm_max_address(), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_8_max, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_16_max); +ATF_TC_HEAD(ufetch_16_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_16 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_16_max, tc) +{ + uint16_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_16(vm_max_address(), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_16_max, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_32_max); +ATF_TC_HEAD(ufetch_32_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_32 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_32_max, tc) +{ + uint32_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_32(vm_max_address(), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_32_max, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ufetch_64_max); +ATF_TC_HEAD(ufetch_64_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_64 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_64_max, tc) +{ + uint64_t res; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ufetch_64(vm_max_address(), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_64_max, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ufetch_16_nearmax_overflow); +ATF_TC_HEAD(ufetch_16_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_16 near-VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_16_nearmax_overflow, tc) +{ + uint16_t res; + + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ufetch_16(vm_max_address_minus(1), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_16_nearmax_overflow, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ufetch_32_nearmax_overflow); +ATF_TC_HEAD(ufetch_32_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_32 near-VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_32_nearmax_overflow, tc) +{ + uint32_t res; + + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ufetch_32(vm_max_address_minus(3), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_32_nearmax_overflow, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ufetch_64_nearmax_overflow); +ATF_TC_HEAD(ufetch_64_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ufetch_64 near-VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ufetch_64_nearmax_overflow, tc) +{ + uint64_t res; + + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ufetch_64(vm_max_address_minus(7), &res), EFAULT); +} +ATF_TC_CLEANUP(ufetch_64_nearmax_overflow, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + + +ATF_TC_WITH_CLEANUP(ustore_8); +ATF_TC_HEAD(ustore_8, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_8 behavior"); +} +ATF_TC_BODY(ustore_8, tc) +{ + struct memory_cell cell = memory_cell_initializer; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_8(&cell.val8[index8], test_pattern8), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(read_test_cell(&cell) == test_cell_val8); +} +ATF_TC_CLEANUP(ustore_8, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_16); +ATF_TC_HEAD(ustore_16, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_16 behavior"); +} +ATF_TC_BODY(ustore_16, tc) +{ + struct memory_cell cell = memory_cell_initializer; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_16(&cell.val16[index16], test_pattern16), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(read_test_cell(&cell) == test_cell_val16); +} +ATF_TC_CLEANUP(ustore_16, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_32); +ATF_TC_HEAD(ustore_32, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_32 behavior"); +} +ATF_TC_BODY(ustore_32, tc) +{ + struct memory_cell cell = memory_cell_initializer; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_32(&cell.val32[index32], test_pattern32), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(read_test_cell(&cell) == test_cell_val32); +} +ATF_TC_CLEANUP(ustore_32, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ustore_64); +ATF_TC_HEAD(ustore_64, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_64 behavior"); +} +ATF_TC_BODY(ustore_64, tc) +{ + struct memory_cell cell = memory_cell_initializer; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_64(&cell.val64, test_pattern64), 0); + ATF_REQUIRE(memory_cell_check_guard(&cell)); + ATF_REQUIRE(read_test_cell(&cell) == test_cell_val64); +} +ATF_TC_CLEANUP(ustore_64, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ustore_8_null); +ATF_TC_HEAD(ustore_8_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_8 NULL pointer behavior"); +} +ATF_TC_BODY(ustore_8_null, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_8(NULL, 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_8_null, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_16_null); +ATF_TC_HEAD(ustore_16_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_16 NULL pointer behavior"); +} +ATF_TC_BODY(ustore_16_null, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_16(NULL, 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_16_null, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_32_null); +ATF_TC_HEAD(ustore_32_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_32 NULL pointer behavior"); +} +ATF_TC_BODY(ustore_32_null, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_32(NULL, 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_32_null, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ustore_64_null); +ATF_TC_HEAD(ustore_64_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_64 NULL pointer behavior"); +} +ATF_TC_BODY(ustore_64_null, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_64(NULL, 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_64_null, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ustore_8_max); +ATF_TC_HEAD(ustore_8_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_8 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_8_max, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_8(vm_max_address(), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_8_max, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_16_max); +ATF_TC_HEAD(ustore_16_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_16 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_16_max, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_16(vm_max_address(), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_16_max, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_32_max); +ATF_TC_HEAD(ustore_32_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_32 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_32_max, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_32(vm_max_address(), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_32_max, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ustore_64_max); +ATF_TC_HEAD(ustore_64_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_64 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_64_max, tc) +{ + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ustore_64(vm_max_address(), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_64_max, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ustore_16_nearmax_overflow); +ATF_TC_HEAD(ustore_16_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_16 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_16_nearmax_overflow, tc) +{ + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ustore_16(vm_max_address_minus(1), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_16_nearmax_overflow, tc) +{ + unload_module(); +} + +ATF_TC_WITH_CLEANUP(ustore_32_nearmax_overflow); +ATF_TC_HEAD(ustore_32_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_32 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_32_nearmax_overflow, tc) +{ + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ustore_32(vm_max_address_minus(3), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_32_nearmax_overflow, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ustore_64_nearmax_overflow); +ATF_TC_HEAD(ustore_64_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ustore_64 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ustore_64_nearmax_overflow, tc) +{ + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ustore_64(vm_max_address_minus(7), 0), EFAULT); +} +ATF_TC_CLEANUP(ustore_64_nearmax_overflow, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + + +ATF_TC_WITH_CLEANUP(ucas_32); +ATF_TC_HEAD(ucas_32, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_32 behavior"); +} +ATF_TC_BODY(ucas_32, tc) +{ + uint32_t cell = 0xdeadbeef; + uint32_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_32(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0); + ATF_REQUIRE(actual == 0xdeadbeef); + ATF_REQUIRE(cell == 0xbeefdead); +} +ATF_TC_CLEANUP(ucas_32, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ucas_64); +ATF_TC_HEAD(ucas_64, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_64 behavior"); +} +ATF_TC_BODY(ucas_64, tc) +{ + uint64_t cell = 0xdeadbeef; + uint64_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_64(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0); + ATF_REQUIRE(actual == 0xdeadbeef); + ATF_REQUIRE(cell == 0xbeefdead); +} +ATF_TC_CLEANUP(ucas_64, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ucas_32_miscompare); +ATF_TC_HEAD(ucas_32_miscompare, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_32 behavior with miscompare"); +} +ATF_TC_BODY(ucas_32_miscompare, tc) +{ + uint32_t cell = 0xa5a5a5a5; + uint32_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_32(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0); + ATF_REQUIRE(actual == 0xa5a5a5a5); + ATF_REQUIRE(cell == 0xa5a5a5a5); +} +ATF_TC_CLEANUP(ucas_32_miscompare, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ucas_64_miscompare); +ATF_TC_HEAD(ucas_64_miscompare, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_64 behavior with miscompare"); +} +ATF_TC_BODY(ucas_64_miscompare, tc) +{ + uint64_t cell = 0xa5a5a5a5; + uint64_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_64(&cell, 0xdeadbeef, 0xbeefdead, &actual), 0); + ATF_REQUIRE(actual == 0xa5a5a5a5); + ATF_REQUIRE(cell == 0xa5a5a5a5); +} +ATF_TC_CLEANUP(ucas_64_miscompare, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ucas_32_null); +ATF_TC_HEAD(ucas_32_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_32 NULL pointer behavior"); +} +ATF_TC_BODY(ucas_32_null, tc) +{ + uint32_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_32(NULL, 0xdeadbeef, 0xbeefdead, &actual), + EFAULT); +} +ATF_TC_CLEANUP(ucas_32_null, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ucas_64_null); +ATF_TC_HEAD(ucas_64_null, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_64 NULL pointer behavior"); +} +ATF_TC_BODY(ucas_64_null, tc) +{ + uint64_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_64(NULL, 0xdeadbeef, 0xbeefdead, &actual), + EFAULT); +} +ATF_TC_CLEANUP(ucas_64_null, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ucas_32_max); +ATF_TC_HEAD(ucas_32_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_32 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ucas_32_max, tc) +{ + uint32_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_32(vm_max_address(), 0xdeadbeef, 0xbeefdead, + &actual), EFAULT); +} +ATF_TC_CLEANUP(ucas_32_max, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ucas_64_max); +ATF_TC_HEAD(ucas_64_max, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_64 VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ucas_64_max, tc) +{ + uint64_t actual = 0; + + CHECK_MODULE(); + + ATF_REQUIRE_EQ(do_ucas_64(vm_max_address(), 0xdeadbeef, 0xbeefdead, + &actual), EFAULT); +} +ATF_TC_CLEANUP(ucas_64_max, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TC_WITH_CLEANUP(ucas_32_nearmax_overflow); +ATF_TC_HEAD(ucas_32_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_32 near-VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ucas_32_nearmax_overflow, tc) +{ + uint32_t actual = 0; + + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ucas_32(vm_max_address_minus(3), 0xdeadbeef, + 0xbeefdead, &actual), EFAULT); +} +ATF_TC_CLEANUP(ucas_32_nearmax_overflow, tc) +{ + unload_module(); +} + +#ifdef _LP64 +ATF_TC_WITH_CLEANUP(ucas_64_nearmax_overflow); +ATF_TC_HEAD(ucas_64_nearmax_overflow, tc) +{ + atf_tc_set_md_var(tc, "descr", + "test for correct ucas_64 near-VM_MAX_ADDRESS pointer behavior"); +} +ATF_TC_BODY(ucas_64_nearmax_overflow, tc) +{ + uint64_t actual = 0; + + CHECK_MODULE(); + + /* + * For no-strict-alignment platforms: address checks must return + * EFAULT. + * + * For strict-alignment platforms: alignment checks must return + * EFAULT. + */ + ATF_REQUIRE_EQ(do_ucas_64(vm_max_address_minus(7), 0xdeadbeef, + 0xbeefdead, &actual), EFAULT); +} +ATF_TC_CLEANUP(ucas_64_nearmax_overflow, tc) +{ + unload_module(); +} +#endif /* _LP64 */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, ufetch_8); + ATF_TP_ADD_TC(tp, ufetch_16); + ATF_TP_ADD_TC(tp, ufetch_32); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ufetch_64); +#endif + + ATF_TP_ADD_TC(tp, ufetch_8_null); + ATF_TP_ADD_TC(tp, ufetch_16_null); + ATF_TP_ADD_TC(tp, ufetch_32_null); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ufetch_64_null); +#endif + + ATF_TP_ADD_TC(tp, ufetch_8_max); + ATF_TP_ADD_TC(tp, ufetch_16_max); + ATF_TP_ADD_TC(tp, ufetch_32_max); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ufetch_64_max); +#endif + + ATF_TP_ADD_TC(tp, ufetch_16_nearmax_overflow); + ATF_TP_ADD_TC(tp, ufetch_32_nearmax_overflow); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ufetch_64_nearmax_overflow); +#endif + + ATF_TP_ADD_TC(tp, ustore_8); + ATF_TP_ADD_TC(tp, ustore_16); + ATF_TP_ADD_TC(tp, ustore_32); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ustore_64); +#endif + + ATF_TP_ADD_TC(tp, ustore_8_null); + ATF_TP_ADD_TC(tp, ustore_16_null); + ATF_TP_ADD_TC(tp, ustore_32_null); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ustore_64_null); +#endif + + ATF_TP_ADD_TC(tp, ustore_8_max); + ATF_TP_ADD_TC(tp, ustore_16_max); + ATF_TP_ADD_TC(tp, ustore_32_max); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ustore_64_max); +#endif + + ATF_TP_ADD_TC(tp, ustore_16_nearmax_overflow); + ATF_TP_ADD_TC(tp, ustore_32_nearmax_overflow); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ustore_64_nearmax_overflow); +#endif + + ATF_TP_ADD_TC(tp, ucas_32); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ucas_64); +#endif + + ATF_TP_ADD_TC(tp, ucas_32_miscompare); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ucas_64_miscompare); +#endif + + ATF_TP_ADD_TC(tp, ucas_32_null); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ucas_64_null); +#endif + + ATF_TP_ADD_TC(tp, ucas_32_max); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ucas_64_max); +#endif + + ATF_TP_ADD_TC(tp, ucas_32_nearmax_overflow); +#ifdef _LP64 + ATF_TP_ADD_TC(tp, ucas_64_nearmax_overflow); +#endif + + return atf_no_error(); +} Index: src/tests/modules/ufetchstore/common.h diff -u /dev/null src/tests/modules/ufetchstore/common.h:1.1 --- /dev/null Mon Apr 15 19:41:23 2019 +++ src/tests/modules/ufetchstore/common.h Mon Apr 15 19:41:23 2019 @@ -0,0 +1,59 @@ +/* $NetBSD: common.h,v 1.1 2019/04/15 23:41:23 christos Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _UFETCHSTORE_TESTER_COMMON_H_ +#define _UFETCHSTORE_TESTER_COMMON_H_ + +#define OP_LOAD 0 +#define OP_STORE 1 +#define OP_CAS 2 + +struct ufetchstore_test_args { + int pointer_size; + int test_op; + int size; + int fetchstore_error; + uint64_t uaddr64; + union { + uint8_t val8; + uint16_t val16; + uint32_t val32; + uint64_t val64; + }; + union { + uint8_t ea_val8; + uint16_t ea_val16; + uint32_t ea_val32; + uint64_t ea_val64; + }; +}; + +#endif /* _UFETCHSTORE_TESTER_COMMON_H_ */ Index: src/tests/modules/ufetchstore/ufetchstore_tester.c diff -u /dev/null src/tests/modules/ufetchstore/ufetchstore_tester.c:1.1 --- /dev/null Mon Apr 15 19:41:23 2019 +++ src/tests/modules/ufetchstore/ufetchstore_tester.c Mon Apr 15 19:41:23 2019 @@ -0,0 +1,230 @@ +/* $NetBSD: ufetchstore_tester.c,v 1.1 2019/04/15 23:41:23 christos Exp $ */ + +/*- + * Copyright (c) 2019 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/module.h> +#include <sys/sysctl.h> +#include <sys/systm.h> + +#include "common.h" + +static struct tester_ctx { + struct sysctllog *ctx_sysctllog; +} tester_ctx; + +static int +test_ufetch(void * const uaddr, struct ufetchstore_test_args * const args) +{ + int error = 0; + + switch (args->size) { + case 8: + args->fetchstore_error = ufetch_8(uaddr, &args->val8); + break; + case 16: + args->fetchstore_error = ufetch_16(uaddr, &args->val16); + break; + case 32: + args->fetchstore_error = ufetch_32(uaddr, &args->val32); + break; +#ifdef _LP64 + case 64: + args->fetchstore_error = ufetch_64(uaddr, &args->val64); + break; +#endif /* _LP64 */ + default: + error = EINVAL; + } + + return error; +} + +static int +test_ustore(void * const uaddr, struct ufetchstore_test_args * const args) +{ + int error = 0; + + switch (args->size) { + case 8: + args->fetchstore_error = ustore_8(uaddr, args->val8); + break; + case 16: + args->fetchstore_error = ustore_16(uaddr, args->val16); + break; + case 32: + args->fetchstore_error = ustore_32(uaddr, args->val32); + break; +#ifdef _LP64 + case 64: + args->fetchstore_error = ustore_64(uaddr, args->val64); + break; +#endif /* _LP64 */ + default: + error = EINVAL; + } + + return error; +} + +static int +test_ucas(void * const uaddr, struct ufetchstore_test_args * const args) +{ + int error = 0; + + switch (args->size) { + case 32: + args->fetchstore_error = ucas_32(uaddr, + args->ea_val32, args->val32, &args->ea_val32); + break; +#ifdef _LP64 + case 64: + args->fetchstore_error = ucas_64(uaddr, + args->ea_val64, args->val64, &args->ea_val64); + break; +#endif /* _LP64 */ + default: + error = EINVAL; + } + + return error; +} + +static int +do_ufetchstore_test(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct ufetchstore_test_args *uargs, args; + uint64_t args64; + int error; + + node = *rnode; + + uargs = NULL; + node.sysctl_data = &args64; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error) + return error; + if (newp == NULL) + return EINVAL; + + uargs = (void *)(uintptr_t)args64; + + error = copyin(uargs, &args, sizeof(args)); + if (error) + return error; + + args.fetchstore_error = EBADF; /* poison */ + + void *uaddr = (void *)(uintptr_t)args.uaddr64; + + switch (args.test_op) { + case OP_LOAD: + error = test_ufetch(uaddr, &args); + break; + + case OP_STORE: + error = test_ustore(uaddr, &args); + break; + + case OP_CAS: + error = test_ucas(uaddr, &args); + break; + + default: + error = EINVAL; + } + + if (error == 0) + error = copyout(&args, uargs, sizeof(args)); + return error; +} + +static int +ufetchstore_tester_init(void) +{ + struct sysctllog **log = &tester_ctx.ctx_sysctllog; + const struct sysctlnode *rnode, *cnode; + int error; + + error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT, + CTLTYPE_NODE, "ufetchstore_test", + SYSCTL_DESCR("ufetchstore testing interface"), + NULL, 0, NULL, 0, CTL_KERN, CTL_CREATE, CTL_EOL); + if (error) + goto return_error; + + error = sysctl_createv(log, 0, &rnode, &cnode, + /* + * It's really a pointer to our argument structure, because + * we want to have precise control over when copyin / copyout + * happens. + */ + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_QUAD, "test", + SYSCTL_DESCR("execute a ufetchstore test"), + do_ufetchstore_test, 0, + (void *)&tester_ctx, 0, CTL_CREATE, CTL_EOL); + + return_error: + if (error) + sysctl_teardown(log); + return error; +} + +static int +ufetchstore_tester_fini(void) +{ + sysctl_teardown(&tester_ctx.ctx_sysctllog); + return 0; +} + +static int +ufetchstore_tester_modcmd(modcmd_t cmd, void *arg __unused) +{ + int error; + + switch (cmd) { + case MODULE_CMD_INIT: + error = ufetchstore_tester_init(); + break; + + case MODULE_CMD_FINI: + error = ufetchstore_tester_fini(); + break; + + case MODULE_CMD_STAT: + default: + error = ENOTTY; + } + + return error; +} + +MODULE(MODULE_CLASS_MISC, ufetchstore_tester, NULL);