Home | History | Annotate | Line # | Download | only in ufetchstore
      1 /*	$NetBSD: ufetchstore_tester.c,v 1.1 2019/04/15 23:41:23 christos 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/types.h>
     33 #include <sys/module.h>
     34 #include <sys/sysctl.h>
     35 #include <sys/systm.h>
     36 
     37 #include "common.h"
     38 
     39 static struct tester_ctx {
     40 	struct sysctllog *ctx_sysctllog;
     41 } tester_ctx;
     42 
     43 static int
     44 test_ufetch(void * const uaddr, struct ufetchstore_test_args * const args)
     45 {
     46 	int error = 0;
     47 
     48 	switch (args->size) {
     49 	case 8:
     50 		args->fetchstore_error = ufetch_8(uaddr, &args->val8);
     51 		break;
     52 	case 16:
     53 		args->fetchstore_error = ufetch_16(uaddr, &args->val16);
     54 		break;
     55 	case 32:
     56 		args->fetchstore_error = ufetch_32(uaddr, &args->val32);
     57 		break;
     58 #ifdef _LP64
     59 	case 64:
     60 		args->fetchstore_error = ufetch_64(uaddr, &args->val64);
     61 		break;
     62 #endif /* _LP64 */
     63 	default:
     64 		error = EINVAL;
     65 	}
     66 
     67 	return error;
     68 }
     69 
     70 static int
     71 test_ustore(void * const uaddr, struct ufetchstore_test_args * const args)
     72 {
     73 	int error = 0;
     74 
     75 	switch (args->size) {
     76 	case 8:
     77 		args->fetchstore_error = ustore_8(uaddr, args->val8);
     78 		break;
     79 	case 16:
     80 		args->fetchstore_error = ustore_16(uaddr, args->val16);
     81 		break;
     82 	case 32:
     83 		args->fetchstore_error = ustore_32(uaddr, args->val32);
     84 		break;
     85 #ifdef _LP64
     86 	case 64:
     87 		args->fetchstore_error = ustore_64(uaddr, args->val64);
     88 		break;
     89 #endif /* _LP64 */
     90 	default:
     91 		error = EINVAL;
     92 	}
     93 
     94 	return error;
     95 }
     96 
     97 static int
     98 test_ucas(void * const uaddr, struct ufetchstore_test_args * const args)
     99 {
    100 	int error = 0;
    101 
    102 	switch (args->size) {
    103 	case 32:
    104 		args->fetchstore_error = ucas_32(uaddr,
    105 		    args->ea_val32, args->val32, &args->ea_val32);
    106 		break;
    107 #ifdef _LP64
    108 	case 64:
    109 		args->fetchstore_error = ucas_64(uaddr,
    110 		    args->ea_val64, args->val64, &args->ea_val64);
    111 		break;
    112 #endif /* _LP64 */
    113 	default:
    114 		error = EINVAL;
    115 	}
    116 
    117 	return error;
    118 }
    119 
    120 static int
    121 do_ufetchstore_test(SYSCTLFN_ARGS)
    122 {
    123 	struct sysctlnode node;
    124 	struct ufetchstore_test_args *uargs, args;
    125 	uint64_t args64;
    126 	int error;
    127 
    128 	node = *rnode;
    129 
    130 	uargs = NULL;
    131 	node.sysctl_data = &args64;
    132 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    133 	if (error)
    134 		return error;
    135 	if (newp == NULL)
    136 		return EINVAL;
    137 
    138 	uargs = (void *)(uintptr_t)args64;
    139 
    140 	error = copyin(uargs, &args, sizeof(args));
    141 	if (error)
    142 		return error;
    143 
    144 	args.fetchstore_error = EBADF;	/* poison */
    145 
    146 	void *uaddr = (void *)(uintptr_t)args.uaddr64;
    147 
    148 	switch (args.test_op) {
    149 	case OP_LOAD:
    150 		error = test_ufetch(uaddr, &args);
    151 		break;
    152 
    153 	case OP_STORE:
    154 		error = test_ustore(uaddr, &args);
    155 		break;
    156 
    157 	case OP_CAS:
    158 		error = test_ucas(uaddr, &args);
    159 		break;
    160 
    161 	default:
    162 		error = EINVAL;
    163 	}
    164 
    165 	if (error == 0)
    166 		error = copyout(&args, uargs, sizeof(args));
    167 	return error;
    168 }
    169 
    170 static int
    171 ufetchstore_tester_init(void)
    172 {
    173 	struct sysctllog **log = &tester_ctx.ctx_sysctllog;
    174 	const struct sysctlnode *rnode, *cnode;
    175 	int error;
    176 
    177 	error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT,
    178 	    CTLTYPE_NODE, "ufetchstore_test",
    179 	    SYSCTL_DESCR("ufetchstore testing interface"),
    180 	    NULL, 0, NULL, 0, CTL_KERN, CTL_CREATE, CTL_EOL);
    181 	if (error)
    182 		goto return_error;
    183 
    184 	error = sysctl_createv(log, 0, &rnode, &cnode,
    185 	    /*
    186 	     * It's really a pointer to our argument structure, because
    187 	     * we want to have precise control over when copyin / copyout
    188 	     * happens.
    189 	     */
    190 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_QUAD, "test",
    191 	    SYSCTL_DESCR("execute a ufetchstore test"),
    192 	    do_ufetchstore_test, 0,
    193 	    (void *)&tester_ctx, 0, CTL_CREATE, CTL_EOL);
    194 
    195  return_error:
    196  	if (error)
    197 		sysctl_teardown(log);
    198 	return error;
    199 }
    200 
    201 static int
    202 ufetchstore_tester_fini(void)
    203 {
    204 	sysctl_teardown(&tester_ctx.ctx_sysctllog);
    205 	return 0;
    206 }
    207 
    208 static int
    209 ufetchstore_tester_modcmd(modcmd_t cmd, void *arg __unused)
    210 {
    211 	int error;
    212 
    213 	switch (cmd) {
    214 	case MODULE_CMD_INIT:
    215 		error = ufetchstore_tester_init();
    216 		break;
    217 
    218 	case MODULE_CMD_FINI:
    219 		error = ufetchstore_tester_fini();
    220 		break;
    221 
    222 	case MODULE_CMD_STAT:
    223 	default:
    224 		error = ENOTTY;
    225 	}
    226 
    227 	return error;
    228 }
    229 
    230 MODULE(MODULE_CLASS_MISC, ufetchstore_tester, NULL);
    231