]> git.proxmox.com Git - mirror_spl-debian.git/blob - module/splat/splat-generic.c
38df14d3b174709b139b93dc489bf004d1aca52b
[mirror_spl-debian.git] / module / splat / splat-generic.c
1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
10 *
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) Generic Tests.
25 \*****************************************************************************/
26
27 #include <sys/sunddi.h>
28 #include "splat-internal.h"
29
30 #define SPLAT_GENERIC_NAME "generic"
31 #define SPLAT_GENERIC_DESC "Kernel Generic Tests"
32
33 #define SPLAT_GENERIC_TEST1_ID 0x0d01
34 #define SPLAT_GENERIC_TEST1_NAME "ddi_strtoul"
35 #define SPLAT_GENERIC_TEST1_DESC "ddi_strtoul Test"
36
37 #define SPLAT_GENERIC_TEST2_ID 0x0d02
38 #define SPLAT_GENERIC_TEST2_NAME "ddi_strtol"
39 #define SPLAT_GENERIC_TEST2_DESC "ddi_strtol Test"
40
41 #define SPLAT_GENERIC_TEST3_ID 0x0d03
42 #define SPLAT_GENERIC_TEST3_NAME "ddi_strtoull"
43 #define SPLAT_GENERIC_TEST3_DESC "ddi_strtoull Test"
44
45 #define SPLAT_GENERIC_TEST4_ID 0x0d04
46 #define SPLAT_GENERIC_TEST4_NAME "ddi_strtoll"
47 #define SPLAT_GENERIC_TEST4_DESC "ddi_strtoll Test"
48
49 # define SPLAT_GENERIC_TEST5_ID 0x0d05
50 # define SPLAT_GENERIC_TEST5_NAME "udivdi3"
51 # define SPLAT_GENERIC_TEST5_DESC "Unsigned Div-64 Test"
52
53 # define SPLAT_GENERIC_TEST6_ID 0x0d06
54 # define SPLAT_GENERIC_TEST6_NAME "divdi3"
55 # define SPLAT_GENERIC_TEST6_DESC "Signed Div-64 Test"
56
57 #define STR_POS "123456789"
58 #define STR_NEG "-123456789"
59 #define STR_BASE "0xabcdef"
60 #define STR_RANGE_MAX "10000000000000000"
61 #define STR_RANGE_MIN "-10000000000000000"
62 #define STR_INVAL1 "12345U"
63 #define STR_INVAL2 "invald"
64
65 #define VAL_POS 123456789
66 #define VAL_NEG -123456789
67 #define VAL_BASE 0xabcdef
68 #define VAL_INVAL1 12345U
69
70 #define define_generic_msg_strtox(type, valtype) \
71 static void \
72 generic_msg_strto##type(struct file *file, char *msg, int rc, int *err, \
73 const char *s, valtype d, char *endptr) \
74 { \
75 splat_vprint(file, SPLAT_GENERIC_TEST1_NAME, \
76 "%s (%d) %s: %s == %lld, 0x%p\n", \
77 rc ? "Fail" : "Pass", *err, msg, s, \
78 (unsigned long long)d, endptr); \
79 *err = rc; \
80 }
81
82 define_generic_msg_strtox(ul, unsigned long);
83 define_generic_msg_strtox(l, long);
84 define_generic_msg_strtox(ull, unsigned long long);
85 define_generic_msg_strtox(ll, long long);
86
87 #define define_splat_generic_test_strtox(type, valtype) \
88 static int \
89 splat_generic_test_strto##type(struct file *file, void *arg) \
90 { \
91 int rc, rc1, rc2, rc3, rc4, rc5, rc6, rc7; \
92 char str[20], *endptr; \
93 valtype r; \
94 \
95 /* Positive value: expect success */ \
96 r = 0; \
97 rc = 1; \
98 endptr = NULL; \
99 rc1 = ddi_strto##type(STR_POS, &endptr, 10, &r); \
100 if (rc1 == 0 && r == VAL_POS && endptr && *endptr == '\0') \
101 rc = 0; \
102 \
103 generic_msg_strto##type(file, "positive", rc , &rc1, \
104 STR_POS, r, endptr); \
105 \
106 /* Negative value: expect success */ \
107 r = 0; \
108 rc = 1; \
109 endptr = NULL; \
110 strcpy(str, STR_NEG); \
111 rc2 = ddi_strto##type(str, &endptr, 10, &r); \
112 if (#type[0] == 'u') { \
113 if (rc2 == 0 && r == 0 && endptr == str) \
114 rc = 0; \
115 } else { \
116 if (rc2 == 0 && r == VAL_NEG && \
117 endptr && *endptr == '\0') \
118 rc = 0; \
119 } \
120 \
121 generic_msg_strto##type(file, "negative", rc, &rc2, \
122 STR_NEG, r, endptr); \
123 \
124 /* Non decimal base: expect sucess */ \
125 r = 0; \
126 rc = 1; \
127 endptr = NULL; \
128 rc3 = ddi_strto##type(STR_BASE, &endptr, 0, &r); \
129 if (rc3 == 0 && r == VAL_BASE && endptr && *endptr == '\0') \
130 rc = 0; \
131 \
132 generic_msg_strto##type(file, "base", rc, &rc3, \
133 STR_BASE, r, endptr); \
134 \
135 /* Max out of range: failure expected, r unchanged */ \
136 r = 0; \
137 rc = 1; \
138 endptr = NULL; \
139 rc4 = ddi_strto##type(STR_RANGE_MAX, &endptr, 16, &r); \
140 if (rc4 == ERANGE && r == 0 && endptr == NULL) \
141 rc = 0; \
142 \
143 generic_msg_strto##type(file, "max", rc, &rc4, \
144 STR_RANGE_MAX, r, endptr); \
145 \
146 /* Min out of range: failure expected, r unchanged */ \
147 r = 0; \
148 rc = 1; \
149 endptr = NULL; \
150 strcpy(str, STR_RANGE_MIN); \
151 rc5 = ddi_strto##type(str, &endptr, 16, &r); \
152 if (#type[0] == 'u') { \
153 if (rc5 == 0 && r == 0 && endptr == str) \
154 rc = 0; \
155 } else { \
156 if (rc5 == ERANGE && r == 0 && endptr == NULL) \
157 rc = 0; \
158 } \
159 \
160 generic_msg_strto##type(file, "min", rc, &rc5, \
161 STR_RANGE_MIN, r, endptr); \
162 \
163 /* Invalid string: success expected, endptr == 'U' */ \
164 r = 0; \
165 rc = 1; \
166 endptr = NULL; \
167 rc6 = ddi_strto##type(STR_INVAL1, &endptr, 10, &r); \
168 if (rc6 == 0 && r == VAL_INVAL1 && endptr && *endptr == 'U') \
169 rc = 0; \
170 \
171 generic_msg_strto##type(file, "invalid", rc, &rc6, \
172 STR_INVAL1, r, endptr); \
173 \
174 /* Invalid string: failure expected, endptr == str */ \
175 r = 0; \
176 rc = 1; \
177 endptr = NULL; \
178 strcpy(str, STR_INVAL2); \
179 rc7 = ddi_strto##type(str, &endptr, 10, &r); \
180 if (rc7 == 0 && r == 0 && endptr == str) \
181 rc = 0; \
182 \
183 generic_msg_strto##type(file, "invalid", rc, &rc7, \
184 STR_INVAL2, r, endptr); \
185 \
186 return (rc1 || rc2 || rc3 || rc4 || rc5 || rc6 || rc7) ? \
187 -EINVAL : 0; \
188 }
189
190 define_splat_generic_test_strtox(ul, unsigned long);
191 define_splat_generic_test_strtox(l, long);
192 define_splat_generic_test_strtox(ull, unsigned long long);
193 define_splat_generic_test_strtox(ll, long long);
194
195 /*
196 * The entries in the table are used in all combinations and the
197 * return value is checked to ensure it is range. On 32-bit
198 * systems __udivdi3 will be invoked for the 64-bit division.
199 * On 64-bit system the native 64-bit divide will be used so
200 * __udivdi3 isn't used but we might as well stil run the test.
201 */
202 static int
203 splat_generic_test_udivdi3(struct file *file, void *arg)
204 {
205 const uint64_t tabu[] = {
206 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
207 10, 11, 12, 13, 14, 15, 16, 1000, 2003,
208 32765, 32766, 32767, 32768, 32769, 32760,
209 65533, 65534, 65535, 65536, 65537, 65538,
210 0x7ffffffeULL, 0x7fffffffULL, 0x80000000ULL, 0x80000001ULL,
211 0x7000000000000000ULL, 0x7000000080000000ULL, 0x7000000080000001ULL,
212 0x7fffffffffffffffULL, 0x7fffffff8fffffffULL, 0x7fffffff8ffffff1ULL,
213 0x7fffffff00000000ULL, 0x7fffffff80000000ULL, 0x7fffffff00000001ULL,
214 0x8000000000000000ULL, 0x8000000080000000ULL, 0x8000000080000001ULL,
215 0xc000000000000000ULL, 0xc000000080000000ULL, 0xc000000080000001ULL,
216 0xfffffffffffffffdULL, 0xfffffffffffffffeULL, 0xffffffffffffffffULL,
217 };
218 uint64_t uu, vu, qu, ru;
219 int n, i, j, errors = 0;
220
221 splat_vprint(file, SPLAT_GENERIC_TEST5_NAME, "%s",
222 "Testing unsigned 64-bit division.\n");
223 n = sizeof(tabu) / sizeof(tabu[0]);
224 for (i = 0; i < n; i++) {
225 for (j = 1; j < n; j++) {
226 uu = tabu[i];
227 vu = tabu[j];
228 qu = uu / vu; /* __udivdi3 */
229 ru = uu - qu * vu;
230 if (qu > uu || ru >= vu) {
231 splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
232 "%016llx/%016llx != %016llx rem %016llx\n",
233 uu, vu, qu, ru);
234 errors++;
235 }
236 }
237 }
238
239 if (errors) {
240 splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
241 "Failed %d/%d tests\n", errors, n * (n - 1));
242 return -ERANGE;
243 }
244
245 splat_vprint(file, SPLAT_GENERIC_TEST5_NAME,
246 "Passed all %d tests\n", n * (n - 1));
247
248 return 0;
249 }
250
251 /*
252 * The entries the table are used in all combinations, with + and - signs
253 * preceding them. The return value is checked to ensure it is range.
254 * On 32-bit systems __divdi3 will be invoked for the 64-bit division.
255 * On 64-bit system the native 64-bit divide will be used so __divdi3
256 * isn't used but we might as well stil run the test.
257 */
258 static int
259 splat_generic_test_divdi3(struct file *file, void *arg)
260 {
261 const int64_t tabs[] = {
262 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
263 10, 11, 12, 13, 14, 15, 16, 1000, 2003,
264 32765, 32766, 32767, 32768, 32769, 32760,
265 65533, 65534, 65535, 65536, 65537, 65538,
266 0x7ffffffeLL, 0x7fffffffLL, 0x80000000LL, 0x80000001LL,
267 0x7000000000000000LL, 0x7000000080000000LL, 0x7000000080000001LL,
268 0x7fffffffffffffffLL, 0x7fffffff8fffffffLL, 0x7fffffff8ffffff1LL,
269 0x7fffffff00000000LL, 0x7fffffff80000000LL, 0x7fffffff00000001LL,
270 0x0123456789abcdefLL, 0x00000000abcdef01LL, 0x0000000012345678LL,
271 #if BITS_PER_LONG == 32
272 0x8000000000000000LL, 0x8000000080000000LL, 0x8000000080000001LL,
273 #endif
274 };
275 int64_t u, v, q, r;
276 int n, i, j, k, errors = 0;
277
278 splat_vprint(file, SPLAT_GENERIC_TEST6_NAME, "%s",
279 "Testing signed 64-bit division.\n");
280 n = sizeof(tabs) / sizeof(tabs[0]);
281 for (i = 0; i < n; i++) {
282 for (j = 1; j < n; j++) {
283 for (k = 0; k <= 3; k++) {
284 u = (k & 1) ? -tabs[i] : tabs[i];
285 v = (k >= 2) ? -tabs[j] : tabs[j];
286
287 q = u / v; /* __divdi3 */
288 r = u - q * v;
289 if (abs64(q) > abs64(u) ||
290 abs64(r) >= abs64(v) ||
291 (r != 0 && (r ^ u) < 0)) {
292 splat_vprint(file,
293 SPLAT_GENERIC_TEST6_NAME,
294 "%016llx/%016llx != %016llx "
295 "rem %016llx\n", u, v, q, r);
296 errors++;
297 }
298 }
299 }
300 }
301
302 if (errors) {
303 splat_vprint(file, SPLAT_GENERIC_TEST6_NAME,
304 "Failed %d/%d tests\n", errors, n * (n - 1));
305 return -ERANGE;
306 }
307
308 splat_vprint(file, SPLAT_GENERIC_TEST6_NAME,
309 "Passed all %d tests\n", n * (n - 1));
310
311 return 0;
312 }
313
314 splat_subsystem_t *
315 splat_generic_init(void)
316 {
317 splat_subsystem_t *sub;
318
319 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
320 if (sub == NULL)
321 return NULL;
322
323 memset(sub, 0, sizeof(*sub));
324 strncpy(sub->desc.name, SPLAT_GENERIC_NAME, SPLAT_NAME_SIZE);
325 strncpy(sub->desc.desc, SPLAT_GENERIC_DESC, SPLAT_DESC_SIZE);
326 INIT_LIST_HEAD(&sub->subsystem_list);
327 INIT_LIST_HEAD(&sub->test_list);
328 spin_lock_init(&sub->test_lock);
329 sub->desc.id = SPLAT_SUBSYSTEM_GENERIC;
330
331 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST1_NAME, SPLAT_GENERIC_TEST1_DESC,
332 SPLAT_GENERIC_TEST1_ID, splat_generic_test_strtoul);
333 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST2_NAME, SPLAT_GENERIC_TEST2_DESC,
334 SPLAT_GENERIC_TEST2_ID, splat_generic_test_strtol);
335 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST3_NAME, SPLAT_GENERIC_TEST3_DESC,
336 SPLAT_GENERIC_TEST3_ID, splat_generic_test_strtoull);
337 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST4_NAME, SPLAT_GENERIC_TEST4_DESC,
338 SPLAT_GENERIC_TEST4_ID, splat_generic_test_strtoll);
339 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST5_NAME, SPLAT_GENERIC_TEST5_DESC,
340 SPLAT_GENERIC_TEST5_ID, splat_generic_test_udivdi3);
341 SPLAT_TEST_INIT(sub, SPLAT_GENERIC_TEST6_NAME, SPLAT_GENERIC_TEST6_DESC,
342 SPLAT_GENERIC_TEST6_ID, splat_generic_test_divdi3);
343
344 return sub;
345 }
346
347 void
348 splat_generic_fini(splat_subsystem_t *sub)
349 {
350 ASSERT(sub);
351
352 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST6_ID);
353 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST5_ID);
354 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST4_ID);
355 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST3_ID);
356 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST2_ID);
357 SPLAT_TEST_FINI(sub, SPLAT_GENERIC_TEST1_ID);
358
359 kfree(sub);
360 }
361
362 int
363 splat_generic_id(void)
364 {
365 return SPLAT_SUBSYSTEM_GENERIC;
366 }