xref: /netbsd-src/tests/modules/ufetchstore/ufetchstore_tester.c (revision 6851d4c46556a42ae53fdc3d4a849a3534f34c12)
1*6851d4c4Schristos /*	$NetBSD: ufetchstore_tester.c,v 1.1 2019/04/15 23:41:23 christos Exp $	*/
2*6851d4c4Schristos 
3*6851d4c4Schristos /*-
4*6851d4c4Schristos  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5*6851d4c4Schristos  * All rights reserved.
6*6851d4c4Schristos  *
7*6851d4c4Schristos  * This code is derived from software contributed to The NetBSD Foundation
8*6851d4c4Schristos  * by Jason R. Thorpe.
9*6851d4c4Schristos  *
10*6851d4c4Schristos  * Redistribution and use in source and binary forms, with or without
11*6851d4c4Schristos  * modification, are permitted provided that the following conditions
12*6851d4c4Schristos  * are met:
13*6851d4c4Schristos  * 1. Redistributions of source code must retain the above copyright
14*6851d4c4Schristos  *    notice, this list of conditions and the following disclaimer.
15*6851d4c4Schristos  * 2. Redistributions in binary form must reproduce the above copyright
16*6851d4c4Schristos  *    notice, this list of conditions and the following disclaimer in the
17*6851d4c4Schristos  *    documentation and/or other materials provided with the distribution.
18*6851d4c4Schristos  *
19*6851d4c4Schristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*6851d4c4Schristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*6851d4c4Schristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*6851d4c4Schristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*6851d4c4Schristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*6851d4c4Schristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*6851d4c4Schristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*6851d4c4Schristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*6851d4c4Schristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*6851d4c4Schristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*6851d4c4Schristos  * POSSIBILITY OF SUCH DAMAGE.
30*6851d4c4Schristos  */
31*6851d4c4Schristos 
32*6851d4c4Schristos #include <sys/types.h>
33*6851d4c4Schristos #include <sys/module.h>
34*6851d4c4Schristos #include <sys/sysctl.h>
35*6851d4c4Schristos #include <sys/systm.h>
36*6851d4c4Schristos 
37*6851d4c4Schristos #include "common.h"
38*6851d4c4Schristos 
39*6851d4c4Schristos static struct tester_ctx {
40*6851d4c4Schristos 	struct sysctllog *ctx_sysctllog;
41*6851d4c4Schristos } tester_ctx;
42*6851d4c4Schristos 
43*6851d4c4Schristos static int
test_ufetch(void * const uaddr,struct ufetchstore_test_args * const args)44*6851d4c4Schristos test_ufetch(void * const uaddr, struct ufetchstore_test_args * const args)
45*6851d4c4Schristos {
46*6851d4c4Schristos 	int error = 0;
47*6851d4c4Schristos 
48*6851d4c4Schristos 	switch (args->size) {
49*6851d4c4Schristos 	case 8:
50*6851d4c4Schristos 		args->fetchstore_error = ufetch_8(uaddr, &args->val8);
51*6851d4c4Schristos 		break;
52*6851d4c4Schristos 	case 16:
53*6851d4c4Schristos 		args->fetchstore_error = ufetch_16(uaddr, &args->val16);
54*6851d4c4Schristos 		break;
55*6851d4c4Schristos 	case 32:
56*6851d4c4Schristos 		args->fetchstore_error = ufetch_32(uaddr, &args->val32);
57*6851d4c4Schristos 		break;
58*6851d4c4Schristos #ifdef _LP64
59*6851d4c4Schristos 	case 64:
60*6851d4c4Schristos 		args->fetchstore_error = ufetch_64(uaddr, &args->val64);
61*6851d4c4Schristos 		break;
62*6851d4c4Schristos #endif /* _LP64 */
63*6851d4c4Schristos 	default:
64*6851d4c4Schristos 		error = EINVAL;
65*6851d4c4Schristos 	}
66*6851d4c4Schristos 
67*6851d4c4Schristos 	return error;
68*6851d4c4Schristos }
69*6851d4c4Schristos 
70*6851d4c4Schristos static int
test_ustore(void * const uaddr,struct ufetchstore_test_args * const args)71*6851d4c4Schristos test_ustore(void * const uaddr, struct ufetchstore_test_args * const args)
72*6851d4c4Schristos {
73*6851d4c4Schristos 	int error = 0;
74*6851d4c4Schristos 
75*6851d4c4Schristos 	switch (args->size) {
76*6851d4c4Schristos 	case 8:
77*6851d4c4Schristos 		args->fetchstore_error = ustore_8(uaddr, args->val8);
78*6851d4c4Schristos 		break;
79*6851d4c4Schristos 	case 16:
80*6851d4c4Schristos 		args->fetchstore_error = ustore_16(uaddr, args->val16);
81*6851d4c4Schristos 		break;
82*6851d4c4Schristos 	case 32:
83*6851d4c4Schristos 		args->fetchstore_error = ustore_32(uaddr, args->val32);
84*6851d4c4Schristos 		break;
85*6851d4c4Schristos #ifdef _LP64
86*6851d4c4Schristos 	case 64:
87*6851d4c4Schristos 		args->fetchstore_error = ustore_64(uaddr, args->val64);
88*6851d4c4Schristos 		break;
89*6851d4c4Schristos #endif /* _LP64 */
90*6851d4c4Schristos 	default:
91*6851d4c4Schristos 		error = EINVAL;
92*6851d4c4Schristos 	}
93*6851d4c4Schristos 
94*6851d4c4Schristos 	return error;
95*6851d4c4Schristos }
96*6851d4c4Schristos 
97*6851d4c4Schristos static int
test_ucas(void * const uaddr,struct ufetchstore_test_args * const args)98*6851d4c4Schristos test_ucas(void * const uaddr, struct ufetchstore_test_args * const args)
99*6851d4c4Schristos {
100*6851d4c4Schristos 	int error = 0;
101*6851d4c4Schristos 
102*6851d4c4Schristos 	switch (args->size) {
103*6851d4c4Schristos 	case 32:
104*6851d4c4Schristos 		args->fetchstore_error = ucas_32(uaddr,
105*6851d4c4Schristos 		    args->ea_val32, args->val32, &args->ea_val32);
106*6851d4c4Schristos 		break;
107*6851d4c4Schristos #ifdef _LP64
108*6851d4c4Schristos 	case 64:
109*6851d4c4Schristos 		args->fetchstore_error = ucas_64(uaddr,
110*6851d4c4Schristos 		    args->ea_val64, args->val64, &args->ea_val64);
111*6851d4c4Schristos 		break;
112*6851d4c4Schristos #endif /* _LP64 */
113*6851d4c4Schristos 	default:
114*6851d4c4Schristos 		error = EINVAL;
115*6851d4c4Schristos 	}
116*6851d4c4Schristos 
117*6851d4c4Schristos 	return error;
118*6851d4c4Schristos }
119*6851d4c4Schristos 
120*6851d4c4Schristos static int
do_ufetchstore_test(SYSCTLFN_ARGS)121*6851d4c4Schristos do_ufetchstore_test(SYSCTLFN_ARGS)
122*6851d4c4Schristos {
123*6851d4c4Schristos 	struct sysctlnode node;
124*6851d4c4Schristos 	struct ufetchstore_test_args *uargs, args;
125*6851d4c4Schristos 	uint64_t args64;
126*6851d4c4Schristos 	int error;
127*6851d4c4Schristos 
128*6851d4c4Schristos 	node = *rnode;
129*6851d4c4Schristos 
130*6851d4c4Schristos 	uargs = NULL;
131*6851d4c4Schristos 	node.sysctl_data = &args64;
132*6851d4c4Schristos 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
133*6851d4c4Schristos 	if (error)
134*6851d4c4Schristos 		return error;
135*6851d4c4Schristos 	if (newp == NULL)
136*6851d4c4Schristos 		return EINVAL;
137*6851d4c4Schristos 
138*6851d4c4Schristos 	uargs = (void *)(uintptr_t)args64;
139*6851d4c4Schristos 
140*6851d4c4Schristos 	error = copyin(uargs, &args, sizeof(args));
141*6851d4c4Schristos 	if (error)
142*6851d4c4Schristos 		return error;
143*6851d4c4Schristos 
144*6851d4c4Schristos 	args.fetchstore_error = EBADF;	/* poison */
145*6851d4c4Schristos 
146*6851d4c4Schristos 	void *uaddr = (void *)(uintptr_t)args.uaddr64;
147*6851d4c4Schristos 
148*6851d4c4Schristos 	switch (args.test_op) {
149*6851d4c4Schristos 	case OP_LOAD:
150*6851d4c4Schristos 		error = test_ufetch(uaddr, &args);
151*6851d4c4Schristos 		break;
152*6851d4c4Schristos 
153*6851d4c4Schristos 	case OP_STORE:
154*6851d4c4Schristos 		error = test_ustore(uaddr, &args);
155*6851d4c4Schristos 		break;
156*6851d4c4Schristos 
157*6851d4c4Schristos 	case OP_CAS:
158*6851d4c4Schristos 		error = test_ucas(uaddr, &args);
159*6851d4c4Schristos 		break;
160*6851d4c4Schristos 
161*6851d4c4Schristos 	default:
162*6851d4c4Schristos 		error = EINVAL;
163*6851d4c4Schristos 	}
164*6851d4c4Schristos 
165*6851d4c4Schristos 	if (error == 0)
166*6851d4c4Schristos 		error = copyout(&args, uargs, sizeof(args));
167*6851d4c4Schristos 	return error;
168*6851d4c4Schristos }
169*6851d4c4Schristos 
170*6851d4c4Schristos static int
ufetchstore_tester_init(void)171*6851d4c4Schristos ufetchstore_tester_init(void)
172*6851d4c4Schristos {
173*6851d4c4Schristos 	struct sysctllog **log = &tester_ctx.ctx_sysctllog;
174*6851d4c4Schristos 	const struct sysctlnode *rnode, *cnode;
175*6851d4c4Schristos 	int error;
176*6851d4c4Schristos 
177*6851d4c4Schristos 	error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT,
178*6851d4c4Schristos 	    CTLTYPE_NODE, "ufetchstore_test",
179*6851d4c4Schristos 	    SYSCTL_DESCR("ufetchstore testing interface"),
180*6851d4c4Schristos 	    NULL, 0, NULL, 0, CTL_KERN, CTL_CREATE, CTL_EOL);
181*6851d4c4Schristos 	if (error)
182*6851d4c4Schristos 		goto return_error;
183*6851d4c4Schristos 
184*6851d4c4Schristos 	error = sysctl_createv(log, 0, &rnode, &cnode,
185*6851d4c4Schristos 	    /*
186*6851d4c4Schristos 	     * It's really a pointer to our argument structure, because
187*6851d4c4Schristos 	     * we want to have precise control over when copyin / copyout
188*6851d4c4Schristos 	     * happens.
189*6851d4c4Schristos 	     */
190*6851d4c4Schristos 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_QUAD, "test",
191*6851d4c4Schristos 	    SYSCTL_DESCR("execute a ufetchstore test"),
192*6851d4c4Schristos 	    do_ufetchstore_test, 0,
193*6851d4c4Schristos 	    (void *)&tester_ctx, 0, CTL_CREATE, CTL_EOL);
194*6851d4c4Schristos 
195*6851d4c4Schristos  return_error:
196*6851d4c4Schristos  	if (error)
197*6851d4c4Schristos 		sysctl_teardown(log);
198*6851d4c4Schristos 	return error;
199*6851d4c4Schristos }
200*6851d4c4Schristos 
201*6851d4c4Schristos static int
ufetchstore_tester_fini(void)202*6851d4c4Schristos ufetchstore_tester_fini(void)
203*6851d4c4Schristos {
204*6851d4c4Schristos 	sysctl_teardown(&tester_ctx.ctx_sysctllog);
205*6851d4c4Schristos 	return 0;
206*6851d4c4Schristos }
207*6851d4c4Schristos 
208*6851d4c4Schristos static int
ufetchstore_tester_modcmd(modcmd_t cmd,void * arg __unused)209*6851d4c4Schristos ufetchstore_tester_modcmd(modcmd_t cmd, void *arg __unused)
210*6851d4c4Schristos {
211*6851d4c4Schristos 	int error;
212*6851d4c4Schristos 
213*6851d4c4Schristos 	switch (cmd) {
214*6851d4c4Schristos 	case MODULE_CMD_INIT:
215*6851d4c4Schristos 		error = ufetchstore_tester_init();
216*6851d4c4Schristos 		break;
217*6851d4c4Schristos 
218*6851d4c4Schristos 	case MODULE_CMD_FINI:
219*6851d4c4Schristos 		error = ufetchstore_tester_fini();
220*6851d4c4Schristos 		break;
221*6851d4c4Schristos 
222*6851d4c4Schristos 	case MODULE_CMD_STAT:
223*6851d4c4Schristos 	default:
224*6851d4c4Schristos 		error = ENOTTY;
225*6851d4c4Schristos 	}
226*6851d4c4Schristos 
227*6851d4c4Schristos 	return error;
228*6851d4c4Schristos }
229*6851d4c4Schristos 
230*6851d4c4Schristos MODULE(MODULE_CLASS_MISC, ufetchstore_tester, NULL);
231