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