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