xref: /netbsd-src/tests/modules/ufetchstore/ufetchstore_tester.c (revision 6851d4c46556a42ae53fdc3d4a849a3534f34c12)
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
test_ufetch(void * const uaddr,struct ufetchstore_test_args * const args)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
test_ustore(void * const uaddr,struct ufetchstore_test_args * const args)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
test_ucas(void * const uaddr,struct ufetchstore_test_args * const args)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
do_ufetchstore_test(SYSCTLFN_ARGS)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
ufetchstore_tester_init(void)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
ufetchstore_tester_fini(void)202 ufetchstore_tester_fini(void)
203 {
204 	sysctl_teardown(&tester_ctx.ctx_sysctllog);
205 	return 0;
206 }
207 
208 static int
ufetchstore_tester_modcmd(modcmd_t cmd,void * arg __unused)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