1*08855964SRyan Zezeski /*
2*08855964SRyan Zezeski * This file and its contents are supplied under the terms of the
3*08855964SRyan Zezeski * Common Development and Distribution License ("CDDL"), version 1.0.
4*08855964SRyan Zezeski * You may only use this file in accordance with the terms of version
5*08855964SRyan Zezeski * 1.0 of the CDDL.
6*08855964SRyan Zezeski *
7*08855964SRyan Zezeski * A full copy of the text of the CDDL should have accompanied this
8*08855964SRyan Zezeski * source. A copy of the CDDL is also available via the Internet at
9*08855964SRyan Zezeski * http://www.illumos.org/license/CDDL.
10*08855964SRyan Zezeski */
11*08855964SRyan Zezeski
12*08855964SRyan Zezeski /*
13*08855964SRyan Zezeski * Copyright 2023 Oxide Computer Company
14*08855964SRyan Zezeski * Copyright 2024 Ryan Zezeski
15*08855964SRyan Zezeski */
16*08855964SRyan Zezeski
17*08855964SRyan Zezeski /*
18*08855964SRyan Zezeski * The Kernel Test Facility
19*08855964SRyan Zezeski * ------------------------
20*08855964SRyan Zezeski *
21*08855964SRyan Zezeski * The kernel test facility, otherwise known as "ktest", provides a
22*08855964SRyan Zezeski * means for in situ kernel testing. It allows one to write kernel
23*08855964SRyan Zezeski * modules whose purpose is to test other kernel modules (or the
24*08855964SRyan Zezeski * kernel at large). While much can be tested from userland, there are
25*08855964SRyan Zezeski * some cases where there is no substitute for running the test code
26*08855964SRyan Zezeski * in kernel context, right next to the code it's testing. In many
27*08855964SRyan Zezeski * cases it's the only way to efficiently test specific execution
28*08855964SRyan Zezeski * paths, by avoiding the brittleness of action from afar which relies
29*08855964SRyan Zezeski * on subtle interactions between userland and kernel. For these
30*08855964SRyan Zezeski * cases, and many more, ktest gives you the best chance at directly
31*08855964SRyan Zezeski * testing kernel code (short of injecting DEBUG invariant checks
32*08855964SRyan Zezeski * inline with the code itself).
33*08855964SRyan Zezeski *
34*08855964SRyan Zezeski * The kernel test facility provides the following.
35*08855964SRyan Zezeski *
36*08855964SRyan Zezeski * - The ktest kernel module (this file), which acts as a central
37*08855964SRyan Zezeski * location for all administration and execution of test modules.
38*08855964SRyan Zezeski *
39*08855964SRyan Zezeski * - The ktest(9) API, which provides the tools to write tests and
40*08855964SRyan Zezeski * register them with the ktest module.
41*08855964SRyan Zezeski *
42*08855964SRyan Zezeski * - The ktest pseudo device, which presents a control surface to
43*08855964SRyan Zezeski * userspace in the form of your typical ioctl interface.
44*08855964SRyan Zezeski *
45*08855964SRyan Zezeski * - A ktest(8) user command, which provides a user interface to the
46*08855964SRyan Zezeski * ktest facility.
47*08855964SRyan Zezeski *
48*08855964SRyan Zezeski * Ktest Architecture
49*08855964SRyan Zezeski * ------------------
50*08855964SRyan Zezeski *
51*08855964SRyan Zezeski * ## The Test Triple
52*08855964SRyan Zezeski *
53*08855964SRyan Zezeski * Ktest provides a three-level namespace for organizing tests,
54*08855964SRyan Zezeski * referred to as the "test triple". It consists of the module name,
55*08855964SRyan Zezeski * suite name, and test name, written as '<module>:<suite>:<test>'.
56*08855964SRyan Zezeski *
57*08855964SRyan Zezeski * - Module: The top of the namespace, typically named after the
58*08855964SRyan Zezeski * module-under-test (MUT). The convention is to append the '_test'
59*08855964SRyan Zezeski * suffix to the module-under-test. For example, the 'mac' module
60*08855964SRyan Zezeski * might have a 'mac_test' test module. However, there is no hard
61*08855964SRyan Zezeski * rule that a test module must be named after its
62*08855964SRyan Zezeski * module-under-test, it’s merely a suggestion. Such a convention is
63*08855964SRyan Zezeski * a bit unwieldy for large modules like genunix. In those cases it
64*08855964SRyan Zezeski * makes sense to break from the norm.
65*08855964SRyan Zezeski *
66*08855964SRyan Zezeski * - Suite: Each module consists of one or more suites. A suite groups
67*08855964SRyan Zezeski * tests of related functionality. For example, you may have several
68*08855964SRyan Zezeski * tests that verify checksum routines for which you might name the
69*08855964SRyan Zezeski * suite 'checksum'.
70*08855964SRyan Zezeski *
71*08855964SRyan Zezeski * - Test: Each suite consists of one of more tests. The name of the
72*08855964SRyan Zezeski * test can be any string which you find descriptive of the test. A
73*08855964SRyan Zezeski * unit test for a single, small function will often use the name of
74*08855964SRyan Zezeski * the function-under-test with a _test suffix added. But for
75*08855964SRyan Zezeski * testing a series of function calls, or a larger function, it may
76*08855964SRyan Zezeski * make sense to abandon this convention.
77*08855964SRyan Zezeski *
78*08855964SRyan Zezeski * A test triple can be fully or partially-qualified, depending on the
79*08855964SRyan Zezeski * context. A fully-qualified triple is one that names one test by
80*08855964SRyan Zezeski * specifying each level of the namespace and using no glob characters
81*08855964SRyan Zezeski * -- it’s unambiguous. A partially-qualified triple, on the other
82*08855964SRyan Zezeski * hand, can be ambiguous; it only names some of the namespace or
83*08855964SRyan Zezeski * makes use of glob characters.
84*08855964SRyan Zezeski *
85*08855964SRyan Zezeski * Fully qualified:
86*08855964SRyan Zezeski *
87*08855964SRyan Zezeski * 'mac:checksum:mac_sw_cksum_ipv4_tcp_test'
88*08855964SRyan Zezeski *
89*08855964SRyan Zezeski * Partially qualified
90*08855964SRyan Zezeski *
91*08855964SRyan Zezeski * '*'
92*08855964SRyan Zezeski * '*:*:*'
93*08855964SRyan Zezeski * 'mac:'
94*08855964SRyan Zezeski * 'mac:checksum'
95*08855964SRyan Zezeski * 'mac:*:mac_sw*'
96*08855964SRyan Zezeski *
97*08855964SRyan Zezeski * ## The Context Handle
98*08855964SRyan Zezeski *
99*08855964SRyan Zezeski * All communication between ktest and the individual test happens via
100*08855964SRyan Zezeski * the "context object". This object cannot be accessed directly.
101*08855964SRyan Zezeski * Instead, ktest provides a context handle to be accessed via its
102*08855964SRyan Zezeski * ktest(9) API. A test must conform to the ktest_fn_t prototype.
103*08855964SRyan Zezeski *
104*08855964SRyan Zezeski * ## Setting Test Results
105*08855964SRyan Zezeski *
106*08855964SRyan Zezeski * A test conveys its result using one of the result ktest(9) APIs. A
107*08855964SRyan Zezeski * result is typically pass or fail, but a test may also be skipped or
108*08855964SRyan Zezeski * may encounter an unforeseen error. See ktest_result_type_t for a
109*08855964SRyan Zezeski * description of the types of results. All test results should
110*08855964SRyan Zezeski * include the associated source line by way of the __LINE__ macro.
111*08855964SRyan Zezeski * The fail, error, and skip results should also include a message
112*08855964SRyan Zezeski * giving further context on the result.
113*08855964SRyan Zezeski *
114*08855964SRyan Zezeski * ktest_result_pass(ktest_ctx_hdl_t *, int)
115*08855964SRyan Zezeski *
116*08855964SRyan Zezeski * The test ran as expected and all conditions were met. The result
117*08855964SRyan Zezeski * value is set to KTEST_RESULT_PASS.
118*08855964SRyan Zezeski *
119*08855964SRyan Zezeski * ktest_result_fail(ktest_ctx_hdl_t *, int, const char *, ...)
120*08855964SRyan Zezeski *
121*08855964SRyan Zezeski * One of the test conditions was violated. The test should use the
122*08855964SRyan Zezeski * format string and arguments to create a message describing which
123*08855964SRyan Zezeski * condition failed and why. The result value is set to KTEST_RESULT_FAIL.
124*08855964SRyan Zezeski *
125*08855964SRyan Zezeski * ktest_result_error(ktest_ctx_hdl_t *, int, const char *, ...)
126*08855964SRyan Zezeski *
127*08855964SRyan Zezeski * The test encountered an unexpected error, one that is not
128*08855964SRyan Zezeski * directly related to the logic under test. For example, failure to
129*08855964SRyan Zezeski * acquire memory is often outside of the test parameters for most
130*08855964SRyan Zezeski * tests. These types of errors are often encountered when
131*08855964SRyan Zezeski * interacting with the kernel at large and when acquiring resources
132*08855964SRyan Zezeski * for test setup. Perhaps most importantly, it indicates the lack
133*08855964SRyan Zezeski * of a pass/fail determination for this test. The result value is
134*08855964SRyan Zezeski * set to KTEST_RESULT_ERROR.
135*08855964SRyan Zezeski *
136*08855964SRyan Zezeski * ktest_result_skip(ktest_ctx_hdl_t *, int, const char *, ...)
137*08855964SRyan Zezeski *
138*08855964SRyan Zezeski * The test lacks the required context to execute, typically for
139*08855964SRyan Zezeski * lack of resources or specific hardware under test. Like the error
140*08855964SRyan Zezeski * result, this lacks a pass/fail determination. The result value is
141*08855964SRyan Zezeski * set to KTEST_RESULT_SKIP.
142*08855964SRyan Zezeski *
143*08855964SRyan Zezeski * ## Result Macros
144*08855964SRyan Zezeski *
145*08855964SRyan Zezeski * Using the API above is cumbersome, requiring the repetitive use of
146*08855964SRyan Zezeski * the __LINE__ macro. The following macros are provided for ease of
147*08855964SRyan Zezeski * use.
148*08855964SRyan Zezeski *
149*08855964SRyan Zezeski * - KT_PASS(ktest_ctx_hdl_t *ctx)
150*08855964SRyan Zezeski * - KT_FAIL(ktest_ctx_hdl_t *ctx, char *msg, ...)
151*08855964SRyan Zezeski * - KT_ERROR(ktest_ctx_hdl_t *ctx, char *msg, ...)
152*08855964SRyan Zezeski * - KT_SKIP(ktest_ctx_hdl_t *ctx, char *msg, ...)
153*08855964SRyan Zezeski *
154*08855964SRyan Zezeski * ## KTest ASSERT Macros
155*08855964SRyan Zezeski *
156*08855964SRyan Zezeski * Even with the help of the result macros, writing test assertions
157*08855964SRyan Zezeski * requires quite a bit of verbosity and boilerplate; requiring an if
158*08855964SRyan Zezeski * statement, a KT_* call, and the failure message arguments. The
159*08855964SRyan Zezeski * KTest ASSERT macros provide an ASSERT3-like family of macros to
160*08855964SRyan Zezeski * reduce the boilerplate and make test writing feel more natural.
161*08855964SRyan Zezeski * However, they are different from the ASSERT3 family in two major
162*08855964SRyan Zezeski * ways.
163*08855964SRyan Zezeski *
164*08855964SRyan Zezeski * 1. They don't panic. The point is to report test failure, not
165*08855964SRyan Zezeski * preserve system state leading up to an invalid condition.
166*08855964SRyan Zezeski * However, for particularly difficult-to-debug test failures you
167*08855964SRyan Zezeski * could use DTrace to invoke a panic upon entry to
168*08855964SRyan Zezeski * ktest_result_error.
169*08855964SRyan Zezeski *
170*08855964SRyan Zezeski * 2. Following from (1), there may be test state to cleanup such as
171*08855964SRyan Zezeski * freeing memory or other resources. This cleanup needs to happen
172*08855964SRyan Zezeski * as a consequence of the assertion triggering, before returning
173*08855964SRyan Zezeski * from the test function.
174*08855964SRyan Zezeski *
175*08855964SRyan Zezeski * There are three types of KT_ASSERT macros: KTest ASSERT, KTest
176*08855964SRyan Zezeski * ASSERT Goto, and KTest ASSERT Block. The first type of assert is
177*08855964SRyan Zezeski * the closest match to the standard ASSERT macros: they provide no
178*08855964SRyan Zezeski * state cleanup, but require the context handle is passed as final
179*08855964SRyan Zezeski * argument. The goto versions allow for cleanup via a jump to a
180*08855964SRyan Zezeski * label. The block versions allow for cleanup via an attached block,
181*08855964SRyan Zezeski * much like an if statement, but requires an additional
182*08855964SRyan Zezeski * KT_ASSERTB_END to indicate the end of the block. What follows is a
183*08855964SRyan Zezeski * list of the various KT_ASSERT macros and their arguments. For each
184*08855964SRyan Zezeski * macro listed below, there is a corresponding KTEST_EASSERT macro.
185*08855964SRyan Zezeski * These later macros set a KTEST_ERROR result when tripped.
186*08855964SRyan Zezeski *
187*08855964SRyan Zezeski * KTest ASSERT (no cleanup)
188*08855964SRyan Zezeski *
189*08855964SRyan Zezeski * KTEST_ASSERT3S(left, op, right, ctx)
190*08855964SRyan Zezeski * KTEST_ASSERT3U(left, op, right, ctx)
191*08855964SRyan Zezeski * KTEST_ASSERT3P(left, op, right, ctx)
192*08855964SRyan Zezeski * KTEST_ASSERT(exp, ctx)
193*08855964SRyan Zezeski * KTEST_ASSERT0(exp, ctx)
194*08855964SRyan Zezeski *
195*08855964SRyan Zezeski * KTest ASSERT Goto (cleanup via label)
196*08855964SRyan Zezeski *
197*08855964SRyan Zezeski * KT_ASSERT3SG(left, op, right, ctx, label)
198*08855964SRyan Zezeski * KT_ASSERT3UG(left, op, right, ctx, label)
199*08855964SRyan Zezeski * KT_ASSERT3PG(left, op, right, ctx, label)
200*08855964SRyan Zezeski * KT_ASSERTG(exp, ctx, label)
201*08855964SRyan Zezeski * KT_ASSERT0G(exp, ctx, label)
202*08855964SRyan Zezeski *
203*08855964SRyan Zezeski * KTest ASSERT Block (cleanup via block)
204*08855964SRyan Zezeski *
205*08855964SRyan Zezeski * KT_ASSERT*B(left, op, right, ctx) {
206*08855964SRyan Zezeski * <... cleanup goes here ...>
207*08855964SRyan Zezeski * }
208*08855964SRyan Zezeski * KT_ASSERTB_END
209*08855964SRyan Zezeski *
210*08855964SRyan Zezeski * ## Additional Failure/Error Context
211*08855964SRyan Zezeski *
212*08855964SRyan Zezeski * Sometimes the failure message generated by the KT_ASSERT macro is
213*08855964SRyan Zezeski * not enough. You might want to prepend some information to the
214*08855964SRyan Zezeski * message to provide additional context about the failure. This would
215*08855964SRyan Zezeski * require using the ktest result API manually, which defeats the
216*08855964SRyan Zezeski * purpose of the KT_ASSERT macros. Instead, ktest offers the
217*08855964SRyan Zezeski * ktest_msg_{prepend,clear}(9F) API; allowing you to prepend
218*08855964SRyan Zezeski * additional context to the failure message (if the assertion should
219*08855964SRyan Zezeski * trip) while still using the KT_ASSERT macros.
220*08855964SRyan Zezeski *
221*08855964SRyan Zezeski * For example, if you were asserting an invariant on an array of
222*08855964SRyan Zezeski * objects, and you wanted the failure message to include the index of
223*08855964SRyan Zezeski * the object which tripped the assert, you could write something like
224*08855964SRyan Zezeski * the following.
225*08855964SRyan Zezeski *
226*08855964SRyan Zezeski * ----
227*08855964SRyan Zezeski * for (int i = 0; i < num_objs; i++) {
228*08855964SRyan Zezeski * obj_t *obj = &objs[i];
229*08855964SRyan Zezeski *
230*08855964SRyan Zezeski * ktest_msg_prepend(ctx, "objs[%d]: ", i);
231*08855964SRyan Zezeski * KT_ASSERT3P(obj->o_state, !=, NULL, ctx);
232*08855964SRyan Zezeski * }
233*08855964SRyan Zezeski *
234*08855964SRyan Zezeski * ktest_msg_clear(ctx);
235*08855964SRyan Zezeski * ----
236*08855964SRyan Zezeski *
237*08855964SRyan Zezeski * The ktest_msg_prepend() call is not additive; it always overwrites
238*08855964SRyan Zezeski * the contents of the prepend buffer.
239*08855964SRyan Zezeski *
240*08855964SRyan Zezeski * ## Test Input
241*08855964SRyan Zezeski *
242*08855964SRyan Zezeski * A test has the option to require input. The input is always in the
243*08855964SRyan Zezeski * form of a byte stream. The interpretation of those bytes is left to
244*08855964SRyan Zezeski * the test; the ktest facility at large treats the input stream as
245*08855964SRyan Zezeski * opaque. It is legal to have an input stream of zero bytes. The test
246*08855964SRyan Zezeski * retrieves its byte stream with the ktest_get_input(9F) API.
247*08855964SRyan Zezeski *
248*08855964SRyan Zezeski * ## Testing Private Functions
249*08855964SRyan Zezeski *
250*08855964SRyan Zezeski * A test module often needs to test static (private) functions.
251*08855964SRyan Zezeski * However, as the test module and module-under-test are two different
252*08855964SRyan Zezeski * modules, and a static function's linkage is local, there is no way
253*08855964SRyan Zezeski * to easily access them. Ktest works around this by offering a set of
254*08855964SRyan Zezeski * APIs to dynamically load the the function object into the test module.
255*08855964SRyan Zezeski *
256*08855964SRyan Zezeski * ktest_hold_mod(9F)
257*08855964SRyan Zezeski * ktest_get_fn(9F)
258*08855964SRyan Zezeski * ktest_release_mod(9F)
259*08855964SRyan Zezeski *
260*08855964SRyan Zezeski * The test modules must perform four steps when accessing a static
261*08855964SRyan Zezeski * function.
262*08855964SRyan Zezeski *
263*08855964SRyan Zezeski * 1. Recreate the function prototype, typically in the form of a
264*08855964SRyan Zezeski * typedef. This is then used to declare the function pointer to
265*08855964SRyan Zezeski * the static function.
266*08855964SRyan Zezeski *
267*08855964SRyan Zezeski * 2. Get a handle to the module-under-test via ktest_hold_mod(9F).
268*08855964SRyan Zezeski *
269*08855964SRyan Zezeski * 3. Fill in the function pointer with ktest_get_fn(9F), after
270*08855964SRyan Zezeski * which it can be called just as it would in the
271*08855964SRyan Zezeski * module-under-test.
272*08855964SRyan Zezeski *
273*08855964SRyan Zezeski * 4. At completion of the test release the module handle via
274*08855964SRyan Zezeski * ktest_release_mod(9F).
275*08855964SRyan Zezeski *
276*08855964SRyan Zezeski * ## Registering Tests
277*08855964SRyan Zezeski *
278*08855964SRyan Zezeski * For a test to be run it first needs to be registered with the ktest
279*08855964SRyan Zezeski * facility. This is done via the ktest(9) APIs described below. The
280*08855964SRyan Zezeski * test module should be a 'modlmisc' module and perform all test
281*08855964SRyan Zezeski * registration/unregistration in its '_init' and '_fini' callbacks.
282*08855964SRyan Zezeski * Internally, ktest tracks all registered tests via the ktest_modules
283*08855964SRyan Zezeski * list.
284*08855964SRyan Zezeski *
285*08855964SRyan Zezeski * ktest_create_module(9F)
286*08855964SRyan Zezeski * ktest_add_test(9F)
287*08855964SRyan Zezeski * ktest_add_suite(9F)
288*08855964SRyan Zezeski * ktest_register_module(9F)
289*08855964SRyan Zezeski * ktest_unregister_module(9F)
290*08855964SRyan Zezeski *
291*08855964SRyan Zezeski * The creation and registration of tests is typically done in the
292*08855964SRyan Zezeski * following order.
293*08855964SRyan Zezeski *
294*08855964SRyan Zezeski * 1. Create a new module with ktest_create_module(9F).
295*08855964SRyan Zezeski *
296*08855964SRyan Zezeski * 2. Add a new suite with ktest_add_suite(9F).
297*08855964SRyan Zezeski *
298*08855964SRyan Zezeski * 3. Add one or more tests to the suite with ktest_add_test(9F).
299*08855964SRyan Zezeski *
300*08855964SRyan Zezeski * 4. Go back to step (2) if more suites are needed.
301*08855964SRyan Zezeski *
302*08855964SRyan Zezeski * 5. Register the module with ktest_register_module(9F).
303*08855964SRyan Zezeski *
304*08855964SRyan Zezeski * For unregistering your test module it's a simple matter of calling
305*08855964SRyan Zezeski * ktest_unregister_module(9F).
306*08855964SRyan Zezeski *
307*08855964SRyan Zezeski * The ktest_add_test(9F) API does provide a flags argument for
308*08855964SRyan Zezeski * providing additional information about the test, see
309*08855964SRyan Zezeski * ktest_test_flags_t for more information.
310*08855964SRyan Zezeski */
311*08855964SRyan Zezeski #include <sys/stddef.h>
312*08855964SRyan Zezeski #include <sys/conf.h>
313*08855964SRyan Zezeski #include <sys/file.h>
314*08855964SRyan Zezeski #include <sys/stat.h>
315*08855964SRyan Zezeski #include <sys/modctl.h>
316*08855964SRyan Zezeski #include <sys/ktest_impl.h>
317*08855964SRyan Zezeski #include <sys/ddi.h>
318*08855964SRyan Zezeski #include <sys/sunddi.h>
319*08855964SRyan Zezeski
320*08855964SRyan Zezeski #define KTEST_CTL_MINOR 0
321*08855964SRyan Zezeski
322*08855964SRyan Zezeski dev_info_t *ktest_dip;
323*08855964SRyan Zezeski kmutex_t ktest_lock;
324*08855964SRyan Zezeski
325*08855964SRyan Zezeski /*
326*08855964SRyan Zezeski * The global list of registered ktest modules. A module must call
327*08855964SRyan Zezeski * ktest_register_module() to register itself with the ktest framework.
328*08855964SRyan Zezeski *
329*08855964SRyan Zezeski * Protected by ktest_lock.
330*08855964SRyan Zezeski *
331*08855964SRyan Zezeski * List modules in MDB
332*08855964SRyan Zezeski * -------------------
333*08855964SRyan Zezeski *
334*08855964SRyan Zezeski * > ktest_modules::walk list |::print ktest_module_t
335*08855964SRyan Zezeski */
336*08855964SRyan Zezeski list_t ktest_modules;
337*08855964SRyan Zezeski
338*08855964SRyan Zezeski /*
339*08855964SRyan Zezeski * Determine if the name is valid. This is probably overly
340*08855964SRyan Zezeski * restrictive, but it's easier to add additional characters later
341*08855964SRyan Zezeski * than to remove them. We want to avoid:
342*08855964SRyan Zezeski *
343*08855964SRyan Zezeski * - KTEST_SEPARATOR and KTEST_GMATCH_CHARS, as it causes ambiguity.
344*08855964SRyan Zezeski *
345*08855964SRyan Zezeski * - Characters that make it harder to use the ktest command in an
346*08855964SRyan Zezeski * interactive shell, such as whitespace and special characters like '&'.
347*08855964SRyan Zezeski */
348*08855964SRyan Zezeski static int
ktest_valid_name(const char * name)349*08855964SRyan Zezeski ktest_valid_name(const char *name)
350*08855964SRyan Zezeski {
351*08855964SRyan Zezeski size_t len = strnlen(name, KTEST_MAX_NAME_LEN);
352*08855964SRyan Zezeski
353*08855964SRyan Zezeski if (len >= KTEST_MAX_NAME_LEN) {
354*08855964SRyan Zezeski return (EOVERFLOW);
355*08855964SRyan Zezeski }
356*08855964SRyan Zezeski
357*08855964SRyan Zezeski for (uint_t i = 0; i < len; i++) {
358*08855964SRyan Zezeski char c = name[i];
359*08855964SRyan Zezeski boolean_t good_char = c == '.' || c == '_' ||
360*08855964SRyan Zezeski (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
361*08855964SRyan Zezeski (c >= '0' && c <= '9');
362*08855964SRyan Zezeski
363*08855964SRyan Zezeski if (!good_char) {
364*08855964SRyan Zezeski return (EINVAL);
365*08855964SRyan Zezeski }
366*08855964SRyan Zezeski }
367*08855964SRyan Zezeski
368*08855964SRyan Zezeski return (0);
369*08855964SRyan Zezeski }
370*08855964SRyan Zezeski
371*08855964SRyan Zezeski static ktest_module_t *
ktest_find_module(const char * module)372*08855964SRyan Zezeski ktest_find_module(const char *module)
373*08855964SRyan Zezeski {
374*08855964SRyan Zezeski ktest_module_t *km = NULL;
375*08855964SRyan Zezeski
376*08855964SRyan Zezeski VERIFY(MUTEX_HELD(&ktest_lock));
377*08855964SRyan Zezeski
378*08855964SRyan Zezeski for (km = list_head(&ktest_modules); km != NULL;
379*08855964SRyan Zezeski km = list_next(&ktest_modules, km)) {
380*08855964SRyan Zezeski if (strncmp(km->km_name, module, KTEST_MAX_NAME_LEN) == 0) {
381*08855964SRyan Zezeski return (km);
382*08855964SRyan Zezeski }
383*08855964SRyan Zezeski }
384*08855964SRyan Zezeski
385*08855964SRyan Zezeski return (NULL);
386*08855964SRyan Zezeski }
387*08855964SRyan Zezeski
388*08855964SRyan Zezeski static ktest_suite_t *
ktest_find_suite(ktest_module_t * km,const char * suite)389*08855964SRyan Zezeski ktest_find_suite(ktest_module_t *km, const char *suite)
390*08855964SRyan Zezeski {
391*08855964SRyan Zezeski ktest_suite_t *ks = NULL;
392*08855964SRyan Zezeski
393*08855964SRyan Zezeski for (ks = list_head(&km->km_suites); ks != NULL;
394*08855964SRyan Zezeski ks = list_next(&km->km_suites, ks)) {
395*08855964SRyan Zezeski if (strncmp(ks->ks_name, suite, KTEST_MAX_NAME_LEN) == 0) {
396*08855964SRyan Zezeski return (ks);
397*08855964SRyan Zezeski }
398*08855964SRyan Zezeski }
399*08855964SRyan Zezeski
400*08855964SRyan Zezeski return (NULL);
401*08855964SRyan Zezeski }
402*08855964SRyan Zezeski
403*08855964SRyan Zezeski static ktest_test_t *
ktest_find_test(ktest_suite_t * ks,const char * test)404*08855964SRyan Zezeski ktest_find_test(ktest_suite_t *ks, const char *test)
405*08855964SRyan Zezeski {
406*08855964SRyan Zezeski ktest_test_t *kt = NULL;
407*08855964SRyan Zezeski
408*08855964SRyan Zezeski for (kt = list_head(&ks->ks_tests); kt != NULL;
409*08855964SRyan Zezeski kt = list_next(&ks->ks_tests, kt)) {
410*08855964SRyan Zezeski if (strncmp(kt->kt_name, test, KTEST_MAX_NAME_LEN) == 0) {
411*08855964SRyan Zezeski return (kt);
412*08855964SRyan Zezeski }
413*08855964SRyan Zezeski }
414*08855964SRyan Zezeski
415*08855964SRyan Zezeski return (NULL);
416*08855964SRyan Zezeski }
417*08855964SRyan Zezeski
418*08855964SRyan Zezeski /*
419*08855964SRyan Zezeski * Return a pointer to the test that matches the fully-qualified
420*08855964SRyan Zezeski * triple. Return NULL if no match is found.
421*08855964SRyan Zezeski */
422*08855964SRyan Zezeski static ktest_test_t *
ktest_get_test(const char * module,const char * suite,const char * test)423*08855964SRyan Zezeski ktest_get_test(const char *module, const char *suite, const char *test)
424*08855964SRyan Zezeski {
425*08855964SRyan Zezeski ktest_module_t *km = NULL;
426*08855964SRyan Zezeski ktest_suite_t *ks = NULL;
427*08855964SRyan Zezeski
428*08855964SRyan Zezeski VERIFY(module != NULL);
429*08855964SRyan Zezeski VERIFY(suite != NULL);
430*08855964SRyan Zezeski VERIFY(test != NULL);
431*08855964SRyan Zezeski VERIFY(MUTEX_HELD(&ktest_lock));
432*08855964SRyan Zezeski
433*08855964SRyan Zezeski if ((km = ktest_find_module(module)) == NULL) {
434*08855964SRyan Zezeski return (NULL);
435*08855964SRyan Zezeski }
436*08855964SRyan Zezeski
437*08855964SRyan Zezeski if ((ks = ktest_find_suite(km, suite)) == NULL) {
438*08855964SRyan Zezeski return (NULL);
439*08855964SRyan Zezeski }
440*08855964SRyan Zezeski
441*08855964SRyan Zezeski return (ktest_find_test(ks, test));
442*08855964SRyan Zezeski }
443*08855964SRyan Zezeski
444*08855964SRyan Zezeski /*
445*08855964SRyan Zezeski * Create a new test module object named 'name'. The test module name
446*08855964SRyan Zezeski * may be the same as the module-under-test, but this isn't required.
447*08855964SRyan Zezeski *
448*08855964SRyan Zezeski * Zero indicates success and a handle to the module object is
449*08855964SRyan Zezeski * returned via 'km_hdl'.
450*08855964SRyan Zezeski *
451*08855964SRyan Zezeski * See ktest_create_module(9F).
452*08855964SRyan Zezeski */
453*08855964SRyan Zezeski int
ktest_create_module(const char * name,ktest_module_hdl_t ** km_hdl)454*08855964SRyan Zezeski ktest_create_module(const char *name, ktest_module_hdl_t **km_hdl)
455*08855964SRyan Zezeski {
456*08855964SRyan Zezeski int ret = 0;
457*08855964SRyan Zezeski ktest_module_t *km = NULL;
458*08855964SRyan Zezeski
459*08855964SRyan Zezeski if ((ret = ktest_valid_name(name)) != 0) {
460*08855964SRyan Zezeski return (ret);
461*08855964SRyan Zezeski }
462*08855964SRyan Zezeski
463*08855964SRyan Zezeski if ((km = kmem_zalloc(sizeof (*km), KM_NOSLEEP)) == NULL) {
464*08855964SRyan Zezeski return (ENOMEM);
465*08855964SRyan Zezeski }
466*08855964SRyan Zezeski
467*08855964SRyan Zezeski list_create(&km->km_suites, sizeof (ktest_suite_t),
468*08855964SRyan Zezeski offsetof(ktest_suite_t, ks_node));
469*08855964SRyan Zezeski /* The length was already checked by ktest_valid_name(). */
470*08855964SRyan Zezeski (void) strlcpy(km->km_name, name, sizeof (km->km_name));
471*08855964SRyan Zezeski *km_hdl = (ktest_module_hdl_t *)km;
472*08855964SRyan Zezeski return (0);
473*08855964SRyan Zezeski }
474*08855964SRyan Zezeski
475*08855964SRyan Zezeski /*
476*08855964SRyan Zezeski * Create a new suite object named 'name' and add it to the module.
477*08855964SRyan Zezeski *
478*08855964SRyan Zezeski * Zero indicates success and a handle to the suite object is returned
479*08855964SRyan Zezeski * via 'ks_hdl'.
480*08855964SRyan Zezeski *
481*08855964SRyan Zezeski * See ktest_add_suite(9F).
482*08855964SRyan Zezeski */
483*08855964SRyan Zezeski int
ktest_add_suite(ktest_module_hdl_t * km_hdl,const char * name,ktest_suite_hdl_t ** ks_hdl)484*08855964SRyan Zezeski ktest_add_suite(ktest_module_hdl_t *km_hdl, const char *name,
485*08855964SRyan Zezeski ktest_suite_hdl_t **ks_hdl)
486*08855964SRyan Zezeski {
487*08855964SRyan Zezeski int ret = 0;
488*08855964SRyan Zezeski ktest_module_t *km = (ktest_module_t *)km_hdl;
489*08855964SRyan Zezeski ktest_suite_t *ks = NULL;
490*08855964SRyan Zezeski
491*08855964SRyan Zezeski if ((ret = ktest_valid_name(name)) != 0) {
492*08855964SRyan Zezeski return (ret);
493*08855964SRyan Zezeski }
494*08855964SRyan Zezeski
495*08855964SRyan Zezeski if (ktest_find_suite(km, name) != NULL) {
496*08855964SRyan Zezeski return (EEXIST);
497*08855964SRyan Zezeski }
498*08855964SRyan Zezeski
499*08855964SRyan Zezeski if ((ks = kmem_zalloc(sizeof (*ks), KM_NOSLEEP)) == NULL) {
500*08855964SRyan Zezeski return (ENOMEM);
501*08855964SRyan Zezeski }
502*08855964SRyan Zezeski
503*08855964SRyan Zezeski list_create(&ks->ks_tests, sizeof (ktest_test_t),
504*08855964SRyan Zezeski offsetof(ktest_test_t, kt_node));
505*08855964SRyan Zezeski /* The length was already checked by ktest_valid_name(). */
506*08855964SRyan Zezeski (void) strlcpy(ks->ks_name, name, sizeof (ks->ks_name));
507*08855964SRyan Zezeski ks->ks_module = km;
508*08855964SRyan Zezeski list_insert_tail(&km->km_suites, ks);
509*08855964SRyan Zezeski km->km_num_suites++;
510*08855964SRyan Zezeski km->km_num_tests += ks->ks_num_tests;
511*08855964SRyan Zezeski *ks_hdl = (ktest_suite_hdl_t *)ks;
512*08855964SRyan Zezeski return (0);
513*08855964SRyan Zezeski }
514*08855964SRyan Zezeski
515*08855964SRyan Zezeski static int
ktest_create_test(ktest_test_t ** test_out,ktest_suite_t * ks,const char * name,ktest_fn_t fn,ktest_test_flags_t flags)516*08855964SRyan Zezeski ktest_create_test(ktest_test_t **test_out, ktest_suite_t *ks, const char *name,
517*08855964SRyan Zezeski ktest_fn_t fn, ktest_test_flags_t flags)
518*08855964SRyan Zezeski {
519*08855964SRyan Zezeski int ret = 0;
520*08855964SRyan Zezeski ktest_test_t *kt = NULL;
521*08855964SRyan Zezeski boolean_t requires_input = B_FALSE;
522*08855964SRyan Zezeski
523*08855964SRyan Zezeski if ((ret = ktest_valid_name(name)) != 0) {
524*08855964SRyan Zezeski return (ret);
525*08855964SRyan Zezeski }
526*08855964SRyan Zezeski
527*08855964SRyan Zezeski if ((kt = kmem_zalloc(sizeof (*kt), KM_NOSLEEP)) == NULL) {
528*08855964SRyan Zezeski return (ENOMEM);
529*08855964SRyan Zezeski }
530*08855964SRyan Zezeski
531*08855964SRyan Zezeski if ((flags & KTEST_FLAG_INPUT) != 0) {
532*08855964SRyan Zezeski requires_input = B_TRUE;
533*08855964SRyan Zezeski }
534*08855964SRyan Zezeski
535*08855964SRyan Zezeski /* The length was already checked by ktest_valid_name(). */
536*08855964SRyan Zezeski (void) strlcpy(kt->kt_name, name, sizeof (kt->kt_name));
537*08855964SRyan Zezeski kt->kt_fn = fn;
538*08855964SRyan Zezeski kt->kt_suite = ks;
539*08855964SRyan Zezeski kt->kt_requires_input = requires_input;
540*08855964SRyan Zezeski *test_out = kt;
541*08855964SRyan Zezeski return (0);
542*08855964SRyan Zezeski }
543*08855964SRyan Zezeski
544*08855964SRyan Zezeski /*
545*08855964SRyan Zezeski * Add a test function to the suite specified by 'ks_hdl'. The test is
546*08855964SRyan Zezeski * registered under the 'name' pseudonym and refers to the 'fn'
547*08855964SRyan Zezeski * function. While the name is often the same as the function symbol,
548*08855964SRyan Zezeski * this is merely a convention and not enforced. The 'flags' argument
549*08855964SRyan Zezeski * may specify additional information about the function -- see the
550*08855964SRyan Zezeski * ktest_test_flags_t definition.
551*08855964SRyan Zezeski *
552*08855964SRyan Zezeski * This function creates a new test object on the caller's behalf and
553*08855964SRyan Zezeski * registers it with the specified suite. Zero indicates success.
554*08855964SRyan Zezeski *
555*08855964SRyan Zezeski * See ktest_add_test(9F).
556*08855964SRyan Zezeski */
557*08855964SRyan Zezeski int
ktest_add_test(ktest_suite_hdl_t * ks_hdl,const char * name,ktest_fn_t fn,ktest_test_flags_t flags)558*08855964SRyan Zezeski ktest_add_test(ktest_suite_hdl_t *ks_hdl, const char *name, ktest_fn_t fn,
559*08855964SRyan Zezeski ktest_test_flags_t flags)
560*08855964SRyan Zezeski {
561*08855964SRyan Zezeski ktest_suite_t *ks = (ktest_suite_t *)ks_hdl;
562*08855964SRyan Zezeski ktest_test_t *test;
563*08855964SRyan Zezeski int ret;
564*08855964SRyan Zezeski
565*08855964SRyan Zezeski if (ktest_find_test(ks, name) != NULL) {
566*08855964SRyan Zezeski return (EEXIST);
567*08855964SRyan Zezeski }
568*08855964SRyan Zezeski
569*08855964SRyan Zezeski if ((ret = ktest_create_test(&test, ks, name, fn, flags)) != 0) {
570*08855964SRyan Zezeski return (ret);
571*08855964SRyan Zezeski }
572*08855964SRyan Zezeski
573*08855964SRyan Zezeski list_insert_tail(&ks->ks_tests, test);
574*08855964SRyan Zezeski ks->ks_num_tests++;
575*08855964SRyan Zezeski return (0);
576*08855964SRyan Zezeski }
577*08855964SRyan Zezeski
578*08855964SRyan Zezeski /*
579*08855964SRyan Zezeski * Register the test module specified by 'km_hdl' with the ktest
580*08855964SRyan Zezeski * facility.
581*08855964SRyan Zezeski *
582*08855964SRyan Zezeski * See ktest_register_module(9F).
583*08855964SRyan Zezeski */
584*08855964SRyan Zezeski int
ktest_register_module(ktest_module_hdl_t * km_hdl)585*08855964SRyan Zezeski ktest_register_module(ktest_module_hdl_t *km_hdl)
586*08855964SRyan Zezeski {
587*08855964SRyan Zezeski ktest_module_t *km = (ktest_module_t *)km_hdl;
588*08855964SRyan Zezeski
589*08855964SRyan Zezeski mutex_enter(&ktest_lock);
590*08855964SRyan Zezeski
591*08855964SRyan Zezeski if (ktest_find_module(km->km_name) != NULL) {
592*08855964SRyan Zezeski mutex_exit(&ktest_lock);
593*08855964SRyan Zezeski cmn_err(CE_NOTE, "test module already exists: %s", km->km_name);
594*08855964SRyan Zezeski return (EEXIST);
595*08855964SRyan Zezeski }
596*08855964SRyan Zezeski
597*08855964SRyan Zezeski list_insert_tail(&ktest_modules, km);
598*08855964SRyan Zezeski mutex_exit(&ktest_lock);
599*08855964SRyan Zezeski return (0);
600*08855964SRyan Zezeski }
601*08855964SRyan Zezeski
602*08855964SRyan Zezeski static void
ktest_free_test(ktest_test_t * test)603*08855964SRyan Zezeski ktest_free_test(ktest_test_t *test)
604*08855964SRyan Zezeski {
605*08855964SRyan Zezeski kmem_free(test, sizeof (*test));
606*08855964SRyan Zezeski }
607*08855964SRyan Zezeski
608*08855964SRyan Zezeski static void
ktest_free_suite(ktest_suite_t * ks)609*08855964SRyan Zezeski ktest_free_suite(ktest_suite_t *ks)
610*08855964SRyan Zezeski {
611*08855964SRyan Zezeski ktest_test_t *kt = NULL;
612*08855964SRyan Zezeski
613*08855964SRyan Zezeski while ((kt = list_remove_head(&ks->ks_tests)) != NULL) {
614*08855964SRyan Zezeski ktest_free_test(kt);
615*08855964SRyan Zezeski }
616*08855964SRyan Zezeski
617*08855964SRyan Zezeski list_destroy(&ks->ks_tests);
618*08855964SRyan Zezeski kmem_free(ks, sizeof (*ks));
619*08855964SRyan Zezeski }
620*08855964SRyan Zezeski
621*08855964SRyan Zezeski void
ktest_free_module(ktest_module_hdl_t * km_hdl)622*08855964SRyan Zezeski ktest_free_module(ktest_module_hdl_t *km_hdl)
623*08855964SRyan Zezeski {
624*08855964SRyan Zezeski ktest_module_t *km = (ktest_module_t *)km_hdl;
625*08855964SRyan Zezeski ktest_suite_t *ks = NULL;
626*08855964SRyan Zezeski
627*08855964SRyan Zezeski while ((ks = list_remove_head(&km->km_suites)) != NULL) {
628*08855964SRyan Zezeski ktest_free_suite(ks);
629*08855964SRyan Zezeski }
630*08855964SRyan Zezeski
631*08855964SRyan Zezeski list_destroy(&km->km_suites);
632*08855964SRyan Zezeski kmem_free(km, sizeof (*km));
633*08855964SRyan Zezeski }
634*08855964SRyan Zezeski
635*08855964SRyan Zezeski /*
636*08855964SRyan Zezeski * Unregister the test module named by 'name'. This walks all suites
637*08855964SRyan Zezeski * and tests registered under this module, removing them and freeing
638*08855964SRyan Zezeski * their resources.
639*08855964SRyan Zezeski *
640*08855964SRyan Zezeski * See ktest_unregister_module(9F).
641*08855964SRyan Zezeski */
642*08855964SRyan Zezeski void
ktest_unregister_module(const char * name)643*08855964SRyan Zezeski ktest_unregister_module(const char *name)
644*08855964SRyan Zezeski {
645*08855964SRyan Zezeski mutex_enter(&ktest_lock);
646*08855964SRyan Zezeski
647*08855964SRyan Zezeski for (ktest_module_t *km = list_head(&ktest_modules);
648*08855964SRyan Zezeski km != NULL;
649*08855964SRyan Zezeski km = list_next(&ktest_modules, km)) {
650*08855964SRyan Zezeski if (strncmp(name, km->km_name, KTEST_MAX_NAME_LEN) == 0) {
651*08855964SRyan Zezeski list_remove(&ktest_modules, km);
652*08855964SRyan Zezeski ktest_free_module((ktest_module_hdl_t *)km);
653*08855964SRyan Zezeski break;
654*08855964SRyan Zezeski }
655*08855964SRyan Zezeski }
656*08855964SRyan Zezeski
657*08855964SRyan Zezeski mutex_exit(&ktest_lock);
658*08855964SRyan Zezeski }
659*08855964SRyan Zezeski
660*08855964SRyan Zezeski static void
ktest_unregister_all()661*08855964SRyan Zezeski ktest_unregister_all()
662*08855964SRyan Zezeski {
663*08855964SRyan Zezeski ktest_module_t *km;
664*08855964SRyan Zezeski mutex_enter(&ktest_lock);
665*08855964SRyan Zezeski
666*08855964SRyan Zezeski while ((km = list_remove_head(&ktest_modules)) != NULL) {
667*08855964SRyan Zezeski ktest_free_module((ktest_module_hdl_t *)km);
668*08855964SRyan Zezeski }
669*08855964SRyan Zezeski
670*08855964SRyan Zezeski mutex_exit(&ktest_lock);
671*08855964SRyan Zezeski }
672*08855964SRyan Zezeski
673*08855964SRyan Zezeski /*
674*08855964SRyan Zezeski * Get a function pointer to the function with symbol 'fn_name'. This
675*08855964SRyan Zezeski * function must be a symbol in the module referenced by 'hdl',
676*08855964SRyan Zezeski * otherwise an error is returned. It's up to the caller to make sure
677*08855964SRyan Zezeski * that the 'fn' pointer is declared correctly.
678*08855964SRyan Zezeski *
679*08855964SRyan Zezeski * Zero indicates success.
680*08855964SRyan Zezeski *
681*08855964SRyan Zezeski * See ktest_get_fn(9F).
682*08855964SRyan Zezeski */
683*08855964SRyan Zezeski int
ktest_get_fn(ddi_modhandle_t hdl,const char * fn_name,void ** fn)684*08855964SRyan Zezeski ktest_get_fn(ddi_modhandle_t hdl, const char *fn_name, void **fn)
685*08855964SRyan Zezeski {
686*08855964SRyan Zezeski int err;
687*08855964SRyan Zezeski
688*08855964SRyan Zezeski if ((*fn = ddi_modsym(hdl, fn_name, &err)) == NULL) {
689*08855964SRyan Zezeski return (err);
690*08855964SRyan Zezeski }
691*08855964SRyan Zezeski
692*08855964SRyan Zezeski return (0);
693*08855964SRyan Zezeski }
694*08855964SRyan Zezeski
695*08855964SRyan Zezeski /*
696*08855964SRyan Zezeski * Get the input stream from the context handle. The contract for this
697*08855964SRyan Zezeski * API guarantees that if it is called, then there MUST be an input
698*08855964SRyan Zezeski * stream. It does this by VERIFYing that a) the test's
699*08855964SRyan Zezeski * 'kt_requires_input' flag is set, and b) that the 'ktc_input' is
700*08855964SRyan Zezeski * non-NULL. This means that failure to set an input stream on a test
701*08855964SRyan Zezeski * which requires it will result in a kernel panic. That may seem
702*08855964SRyan Zezeski * extreme, however, consider that this is meant to be discovered
703*08855964SRyan Zezeski * during development, and that the ktest cmd also takes steps to
704*08855964SRyan Zezeski * ensure that any test which requires input has an input stream
705*08855964SRyan Zezeski * specified. The impetus for this contract is to avoid checking for
706*08855964SRyan Zezeski * valid input in every test -- it allows the test to assume the input
707*08855964SRyan Zezeski * is there and categorically catch any case where it is not.
708*08855964SRyan Zezeski *
709*08855964SRyan Zezeski * This contract does not preclude the possibility of a 0-byte stream,
710*08855964SRyan Zezeski * which may be a valid test case for some tests. It only precludes a
711*08855964SRyan Zezeski * non-existent stream.
712*08855964SRyan Zezeski *
713*08855964SRyan Zezeski * See ktest_get_input(9F).
714*08855964SRyan Zezeski */
715*08855964SRyan Zezeski void
ktest_get_input(const ktest_ctx_hdl_t * hdl,uchar_t ** input,size_t * len)716*08855964SRyan Zezeski ktest_get_input(const ktest_ctx_hdl_t *hdl, uchar_t **input, size_t *len)
717*08855964SRyan Zezeski {
718*08855964SRyan Zezeski ktest_ctx_t *ctx = (ktest_ctx_t *)hdl;
719*08855964SRyan Zezeski VERIFY(ctx->ktc_test->kt_requires_input == B_TRUE);
720*08855964SRyan Zezeski VERIFY3P(ctx->ktc_input, !=, NULL);
721*08855964SRyan Zezeski *len = ctx->ktc_input_len;
722*08855964SRyan Zezeski *input = ctx->ktc_input;
723*08855964SRyan Zezeski }
724*08855964SRyan Zezeski
725*08855964SRyan Zezeski /*
726*08855964SRyan Zezeski * Grab a hold on 'module' and return it in 'hdl'. Meant to be used
727*08855964SRyan Zezeski * with ktest_get_fn(). Zero indicates success.
728*08855964SRyan Zezeski *
729*08855964SRyan Zezeski * Remember, 'ddi_modhandle_t' is a pointer, so 'hdl' is pointer to
730*08855964SRyan Zezeski * pointer.
731*08855964SRyan Zezeski *
732*08855964SRyan Zezeski * See ktest_hold_mod(9F).
733*08855964SRyan Zezeski */
734*08855964SRyan Zezeski int
ktest_hold_mod(const char * module,ddi_modhandle_t * hdl)735*08855964SRyan Zezeski ktest_hold_mod(const char *module, ddi_modhandle_t *hdl)
736*08855964SRyan Zezeski {
737*08855964SRyan Zezeski int err;
738*08855964SRyan Zezeski
739*08855964SRyan Zezeski if ((*hdl = ddi_modopen(module, KRTLD_MODE_FIRST, &err)) == NULL) {
740*08855964SRyan Zezeski return (err);
741*08855964SRyan Zezeski }
742*08855964SRyan Zezeski
743*08855964SRyan Zezeski return (0);
744*08855964SRyan Zezeski }
745*08855964SRyan Zezeski
746*08855964SRyan Zezeski /*
747*08855964SRyan Zezeski * The opposite of ktest_hold_mod().
748*08855964SRyan Zezeski *
749*08855964SRyan Zezeski * See ktest_release_mod(9F).
750*08855964SRyan Zezeski */
751*08855964SRyan Zezeski void
ktest_release_mod(ddi_modhandle_t hdl)752*08855964SRyan Zezeski ktest_release_mod(ddi_modhandle_t hdl)
753*08855964SRyan Zezeski {
754*08855964SRyan Zezeski (void) ddi_modclose(hdl);
755*08855964SRyan Zezeski }
756*08855964SRyan Zezeski
757*08855964SRyan Zezeski /*
758*08855964SRyan Zezeski * Check if the result is already set. Setting the result more than
759*08855964SRyan Zezeski * once is a bug in the test. This check catches the bug and produces
760*08855964SRyan Zezeski * an error result with a message indicating the line number of the
761*08855964SRyan Zezeski * original result which was overwritten. It replaces 'ktc_res_line'
762*08855964SRyan Zezeski * with the line number of the overwriting result.
763*08855964SRyan Zezeski *
764*08855964SRyan Zezeski * Return true when an existing result was found.
765*08855964SRyan Zezeski */
766*08855964SRyan Zezeski static boolean_t
ktest_result_check(ktest_ctx_t * ctx,int line)767*08855964SRyan Zezeski ktest_result_check(ktest_ctx_t *ctx, int line)
768*08855964SRyan Zezeski {
769*08855964SRyan Zezeski if (ctx->ktc_res->kr_type != KTEST_RESULT_NONE) {
770*08855964SRyan Zezeski char *msg = ctx->ktc_res->kr_msg;
771*08855964SRyan Zezeski int first_line = ctx->ktc_res->kr_line;
772*08855964SRyan Zezeski
773*08855964SRyan Zezeski ctx->ktc_res->kr_type = KTEST_RESULT_ERROR;
774*08855964SRyan Zezeski ctx->ktc_res->kr_line = line;
775*08855964SRyan Zezeski
776*08855964SRyan Zezeski /* We know the string is within max length. */
777*08855964SRyan Zezeski (void) snprintf(msg, KTEST_MAX_LOG_LEN, "multiple results: "
778*08855964SRyan Zezeski "prev result at line %d", first_line);
779*08855964SRyan Zezeski
780*08855964SRyan Zezeski return (B_TRUE);
781*08855964SRyan Zezeski }
782*08855964SRyan Zezeski
783*08855964SRyan Zezeski return (B_FALSE);
784*08855964SRyan Zezeski }
785*08855964SRyan Zezeski
786*08855964SRyan Zezeski /*
787*08855964SRyan Zezeski * Set result if and only if one has not already been set. Return true
788*08855964SRyan Zezeski * if the result was set. Return false if it was already set.
789*08855964SRyan Zezeski */
790*08855964SRyan Zezeski static boolean_t
ktest_set_result(ktest_ctx_hdl_t * hdl,ktest_result_type_t rt,int line)791*08855964SRyan Zezeski ktest_set_result(ktest_ctx_hdl_t *hdl, ktest_result_type_t rt, int line)
792*08855964SRyan Zezeski {
793*08855964SRyan Zezeski ktest_ctx_t *ctx = (ktest_ctx_t *)hdl;
794*08855964SRyan Zezeski
795*08855964SRyan Zezeski /* Overwriting a previous result is not allowed. */
796*08855964SRyan Zezeski if (ktest_result_check(ctx, line)) {
797*08855964SRyan Zezeski return (B_FALSE);
798*08855964SRyan Zezeski }
799*08855964SRyan Zezeski
800*08855964SRyan Zezeski ctx->ktc_res->kr_type = rt;
801*08855964SRyan Zezeski ctx->ktc_res->kr_line = line;
802*08855964SRyan Zezeski return (B_TRUE);
803*08855964SRyan Zezeski }
804*08855964SRyan Zezeski
805*08855964SRyan Zezeski static void
ktest_set_msg(ktest_ctx_hdl_t * hdl,const char * format,va_list args)806*08855964SRyan Zezeski ktest_set_msg(ktest_ctx_hdl_t *hdl, const char *format, va_list args)
807*08855964SRyan Zezeski {
808*08855964SRyan Zezeski ktest_ctx_t *ctx = (ktest_ctx_t *)hdl;
809*08855964SRyan Zezeski char *msg = ctx->ktc_res->kr_msg;
810*08855964SRyan Zezeski size_t written = 0;
811*08855964SRyan Zezeski
812*08855964SRyan Zezeski written = vsnprintf(msg, KTEST_MAX_LOG_LEN, format, args);
813*08855964SRyan Zezeski
814*08855964SRyan Zezeski /* Subtract one to account for the implicit NULL byte. */
815*08855964SRyan Zezeski if (written > (KTEST_MAX_LOG_LEN - 1)) {
816*08855964SRyan Zezeski const ktest_test_t *test = ctx->ktc_test;
817*08855964SRyan Zezeski ktest_suite_t *suite = test->kt_suite;
818*08855964SRyan Zezeski ktest_module_t *mod = suite->ks_module;
819*08855964SRyan Zezeski
820*08855964SRyan Zezeski cmn_err(CE_NOTE, "result message truncated: %s:%s:%s [%d]",
821*08855964SRyan Zezeski mod->km_name, suite->ks_name, test->kt_name,
822*08855964SRyan Zezeski ctx->ktc_res->kr_line);
823*08855964SRyan Zezeski }
824*08855964SRyan Zezeski }
825*08855964SRyan Zezeski
826*08855964SRyan Zezeski void
ktest_result_skip(ktest_ctx_hdl_t * hdl,int line,const char * format,...)827*08855964SRyan Zezeski ktest_result_skip(ktest_ctx_hdl_t *hdl, int line, const char *format, ...)
828*08855964SRyan Zezeski {
829*08855964SRyan Zezeski if (ktest_set_result(hdl, KTEST_RESULT_SKIP, line)) {
830*08855964SRyan Zezeski va_list adx;
831*08855964SRyan Zezeski
832*08855964SRyan Zezeski va_start(adx, format);
833*08855964SRyan Zezeski ktest_set_msg(hdl, format, adx);
834*08855964SRyan Zezeski va_end(adx);
835*08855964SRyan Zezeski }
836*08855964SRyan Zezeski }
837*08855964SRyan Zezeski
838*08855964SRyan Zezeski void
ktest_result_fail(ktest_ctx_hdl_t * hdl,int line,const char * format,...)839*08855964SRyan Zezeski ktest_result_fail(ktest_ctx_hdl_t *hdl, int line, const char *format, ...)
840*08855964SRyan Zezeski {
841*08855964SRyan Zezeski if (ktest_set_result(hdl, KTEST_RESULT_FAIL, line)) {
842*08855964SRyan Zezeski va_list adx;
843*08855964SRyan Zezeski
844*08855964SRyan Zezeski va_start(adx, format);
845*08855964SRyan Zezeski ktest_set_msg(hdl, format, adx);
846*08855964SRyan Zezeski va_end(adx);
847*08855964SRyan Zezeski }
848*08855964SRyan Zezeski }
849*08855964SRyan Zezeski
850*08855964SRyan Zezeski void
ktest_result_error(ktest_ctx_hdl_t * hdl,int line,const char * format,...)851*08855964SRyan Zezeski ktest_result_error(ktest_ctx_hdl_t *hdl, int line, const char *format, ...)
852*08855964SRyan Zezeski {
853*08855964SRyan Zezeski if (ktest_set_result(hdl, KTEST_RESULT_ERROR, line)) {
854*08855964SRyan Zezeski va_list adx;
855*08855964SRyan Zezeski
856*08855964SRyan Zezeski va_start(adx, format);
857*08855964SRyan Zezeski ktest_set_msg(hdl, format, adx);
858*08855964SRyan Zezeski va_end(adx);
859*08855964SRyan Zezeski }
860*08855964SRyan Zezeski }
861*08855964SRyan Zezeski
862*08855964SRyan Zezeski void
ktest_result_pass(ktest_ctx_hdl_t * hdl,int line)863*08855964SRyan Zezeski ktest_result_pass(ktest_ctx_hdl_t *hdl, int line)
864*08855964SRyan Zezeski {
865*08855964SRyan Zezeski (void) ktest_set_result(hdl, KTEST_RESULT_PASS, line);
866*08855964SRyan Zezeski }
867*08855964SRyan Zezeski
868*08855964SRyan Zezeski /*
869*08855964SRyan Zezeski * Clear the prepend message, undoing any message set by ktest_msg_prepend().
870*08855964SRyan Zezeski *
871*08855964SRyan Zezeski * See ktest_msg_clear(9F).
872*08855964SRyan Zezeski */
873*08855964SRyan Zezeski void
ktest_msg_clear(ktest_ctx_hdl_t * hdl)874*08855964SRyan Zezeski ktest_msg_clear(ktest_ctx_hdl_t *hdl)
875*08855964SRyan Zezeski {
876*08855964SRyan Zezeski ktest_ctx_t *ctx = (ktest_ctx_t *)hdl;
877*08855964SRyan Zezeski ctx->ktc_res->kr_msg_prepend[0] = '\0';
878*08855964SRyan Zezeski }
879*08855964SRyan Zezeski
880*08855964SRyan Zezeski /*
881*08855964SRyan Zezeski * Prepend formatted text to the result message. This is useful in
882*08855964SRyan Zezeski * cases where the KT_ASSERT macro's generated message doesn't convey
883*08855964SRyan Zezeski * enough context to determine the precise cause of the failure. By
884*08855964SRyan Zezeski * prepending the formatted text you can add additional context while
885*08855964SRyan Zezeski * still using the KT_ASSERT macros (and not having to reimplement
886*08855964SRyan Zezeski * them yourself). This overwrites any existing prepend text.
887*08855964SRyan Zezeski *
888*08855964SRyan Zezeski * See ktest_msg_prepend(9F).
889*08855964SRyan Zezeski */
890*08855964SRyan Zezeski void
ktest_msg_prepend(ktest_ctx_hdl_t * hdl,const char * format,...)891*08855964SRyan Zezeski ktest_msg_prepend(ktest_ctx_hdl_t *hdl, const char *format, ...)
892*08855964SRyan Zezeski {
893*08855964SRyan Zezeski ktest_ctx_t *ctx = (ktest_ctx_t *)hdl;
894*08855964SRyan Zezeski char *msg = ctx->ktc_res->kr_msg_prepend;
895*08855964SRyan Zezeski size_t written;
896*08855964SRyan Zezeski va_list adx;
897*08855964SRyan Zezeski
898*08855964SRyan Zezeski va_start(adx, format);
899*08855964SRyan Zezeski written = vsnprintf(msg, KTEST_MAX_LOG_LEN, format, adx);
900*08855964SRyan Zezeski /* Subtract one to account for the implicit NULL byte. */
901*08855964SRyan Zezeski if (written > (KTEST_MAX_LOG_LEN - 1)) {
902*08855964SRyan Zezeski const ktest_test_t *test = ctx->ktc_test;
903*08855964SRyan Zezeski ktest_suite_t *suite = test->kt_suite;
904*08855964SRyan Zezeski ktest_module_t *mod = suite->ks_module;
905*08855964SRyan Zezeski
906*08855964SRyan Zezeski cmn_err(CE_NOTE, "prepend message truncated: %s:%s:%s",
907*08855964SRyan Zezeski mod->km_name, suite->ks_name, test->kt_name);
908*08855964SRyan Zezeski }
909*08855964SRyan Zezeski va_end(adx);
910*08855964SRyan Zezeski }
911*08855964SRyan Zezeski
912*08855964SRyan Zezeski /*
913*08855964SRyan Zezeski * Each `{:}` represents an nvpair, each `[,]` represents an nvlist.
914*08855964SRyan Zezeski *
915*08855964SRyan Zezeski * Test nvlist
916*08855964SRyan Zezeski * -----------
917*08855964SRyan Zezeski *
918*08855964SRyan Zezeski * [{"name":"<test_name>"},
919*08855964SRyan Zezeski * {"input_required":boolean_t}]
920*08855964SRyan Zezeski *
921*08855964SRyan Zezeski * Tests nvlist
922*08855964SRyan Zezeski * ------------
923*08855964SRyan Zezeski *
924*08855964SRyan Zezeski * [{"test1":<test1_nvlist>},
925*08855964SRyan Zezeski * {"test2":<test2_nvlist>"},
926*08855964SRyan Zezeski * ...]
927*08855964SRyan Zezeski *
928*08855964SRyan Zezeski * Suite nvlist
929*08855964SRyan Zezeski * ------------
930*08855964SRyan Zezeski *
931*08855964SRyan Zezeski * [{"name":"<ks->ks_name>"},
932*08855964SRyan Zezeski * {"tests":<tests_nvlist>}]
933*08855964SRyan Zezeski *
934*08855964SRyan Zezeski * Suites nvlist
935*08855964SRyan Zezeski * -------------
936*08855964SRyan Zezeski *
937*08855964SRyan Zezeski * [{"suite1":<suite1_nvlist>},
938*08855964SRyan Zezeski * {"suite2":<suite2_nvlist>},
939*08855964SRyan Zezeski * ...]
940*08855964SRyan Zezeski *
941*08855964SRyan Zezeski * Module nvlist
942*08855964SRyan Zezeski * -------------
943*08855964SRyan Zezeski *
944*08855964SRyan Zezeski * [{"name":"<km->km_name>"},
945*08855964SRyan Zezeski * {"suites":<suites_nvlist>}]
946*08855964SRyan Zezeski *
947*08855964SRyan Zezeski * Modules nvlist
948*08855964SRyan Zezeski * --------------
949*08855964SRyan Zezeski *
950*08855964SRyan Zezeski * [{"ser_fmt_version":1},
951*08855964SRyan Zezeski * {"module1":<module1_nvlist>},
952*08855964SRyan Zezeski * {"module2":<module2_nvlist>},
953*08855964SRyan Zezeski * ...]
954*08855964SRyan Zezeski *
955*08855964SRyan Zezeski */
956*08855964SRyan Zezeski int
ktest_list_tests(ktest_list_op_t * klo,int mode)957*08855964SRyan Zezeski ktest_list_tests(ktest_list_op_t *klo, int mode)
958*08855964SRyan Zezeski {
959*08855964SRyan Zezeski nvlist_t *modules = fnvlist_alloc();
960*08855964SRyan Zezeski char *buf = NULL;
961*08855964SRyan Zezeski size_t len = 0;
962*08855964SRyan Zezeski int ret = 0;
963*08855964SRyan Zezeski
964*08855964SRyan Zezeski /*
965*08855964SRyan Zezeski * The first thing we add is a uint64_t ser_fmt_version field.
966*08855964SRyan Zezeski * This field allows any consumer of this nvlist (namely the
967*08855964SRyan Zezeski * ktest cmd) to know which serialization format it is in.
968*08855964SRyan Zezeski * Specifically, the format version tells the consumer which
969*08855964SRyan Zezeski * fields to expect and how they are laid out. Given that the
970*08855964SRyan Zezeski * ktest kernel facility and its user command are delivered in
971*08855964SRyan Zezeski * gate, this should never be needed. However, including a
972*08855964SRyan Zezeski * versioned format now keeps the future flexible, and costs
973*08855964SRyan Zezeski * us little.
974*08855964SRyan Zezeski */
975*08855964SRyan Zezeski fnvlist_add_uint64(modules, "ser_fmt_version", KTEST_SER_FMT_VSN);
976*08855964SRyan Zezeski mutex_enter(&ktest_lock);
977*08855964SRyan Zezeski
978*08855964SRyan Zezeski for (ktest_module_t *km = list_head(&ktest_modules);
979*08855964SRyan Zezeski km != NULL;
980*08855964SRyan Zezeski km = list_next(&ktest_modules, km)) {
981*08855964SRyan Zezeski nvlist_t *module = fnvlist_alloc();
982*08855964SRyan Zezeski nvlist_t *suites = fnvlist_alloc();
983*08855964SRyan Zezeski
984*08855964SRyan Zezeski for (ktest_suite_t *ks = list_head(&km->km_suites);
985*08855964SRyan Zezeski ks != NULL;
986*08855964SRyan Zezeski ks = list_next(&km->km_suites, ks)) {
987*08855964SRyan Zezeski nvlist_t *suite = fnvlist_alloc();
988*08855964SRyan Zezeski nvlist_t *tests = fnvlist_alloc();
989*08855964SRyan Zezeski
990*08855964SRyan Zezeski for (ktest_test_t *kt = list_head(&ks->ks_tests);
991*08855964SRyan Zezeski kt != NULL;
992*08855964SRyan Zezeski kt = list_next(&ks->ks_tests, kt)) {
993*08855964SRyan Zezeski nvlist_t *test = fnvlist_alloc();
994*08855964SRyan Zezeski
995*08855964SRyan Zezeski fnvlist_add_string(test, KTEST_NAME_KEY,
996*08855964SRyan Zezeski kt->kt_name);
997*08855964SRyan Zezeski fnvlist_add_boolean_value(test,
998*08855964SRyan Zezeski KTEST_TEST_INPUT_KEY,
999*08855964SRyan Zezeski kt->kt_requires_input);
1000*08855964SRyan Zezeski fnvlist_add_nvlist(tests, kt->kt_name, test);
1001*08855964SRyan Zezeski nvlist_free(test);
1002*08855964SRyan Zezeski }
1003*08855964SRyan Zezeski
1004*08855964SRyan Zezeski if (nvlist_empty(tests)) {
1005*08855964SRyan Zezeski nvlist_free(tests);
1006*08855964SRyan Zezeski nvlist_free(suite);
1007*08855964SRyan Zezeski continue;
1008*08855964SRyan Zezeski }
1009*08855964SRyan Zezeski
1010*08855964SRyan Zezeski fnvlist_add_string(suite, KTEST_NAME_KEY, ks->ks_name);
1011*08855964SRyan Zezeski fnvlist_add_nvlist(suite, KTEST_SUITE_TESTS_KEY, tests);
1012*08855964SRyan Zezeski fnvlist_add_nvlist(suites, ks->ks_name, suite);
1013*08855964SRyan Zezeski nvlist_free(tests);
1014*08855964SRyan Zezeski nvlist_free(suite);
1015*08855964SRyan Zezeski }
1016*08855964SRyan Zezeski
1017*08855964SRyan Zezeski if (nvlist_empty(suites)) {
1018*08855964SRyan Zezeski nvlist_free(suites);
1019*08855964SRyan Zezeski nvlist_free(module);
1020*08855964SRyan Zezeski continue;
1021*08855964SRyan Zezeski }
1022*08855964SRyan Zezeski
1023*08855964SRyan Zezeski fnvlist_add_string(module, KTEST_NAME_KEY, km->km_name);
1024*08855964SRyan Zezeski fnvlist_add_nvlist(module, KTEST_MODULE_SUITES_KEY, suites);
1025*08855964SRyan Zezeski fnvlist_add_nvlist(modules, km->km_name, module);
1026*08855964SRyan Zezeski nvlist_free(suites);
1027*08855964SRyan Zezeski nvlist_free(module);
1028*08855964SRyan Zezeski }
1029*08855964SRyan Zezeski
1030*08855964SRyan Zezeski mutex_exit(&ktest_lock);
1031*08855964SRyan Zezeski buf = fnvlist_pack(modules, &len);
1032*08855964SRyan Zezeski
1033*08855964SRyan Zezeski /*
1034*08855964SRyan Zezeski * The userspace response buffer is not large enough. Fill in
1035*08855964SRyan Zezeski * the amount needed and return ENOBUFS so that the command
1036*08855964SRyan Zezeski * may retry.
1037*08855964SRyan Zezeski */
1038*08855964SRyan Zezeski if (klo->klo_resp_len < len) {
1039*08855964SRyan Zezeski klo->klo_resp_len = len;
1040*08855964SRyan Zezeski nvlist_free(modules);
1041*08855964SRyan Zezeski ret = ENOBUFS;
1042*08855964SRyan Zezeski goto out;
1043*08855964SRyan Zezeski }
1044*08855964SRyan Zezeski
1045*08855964SRyan Zezeski klo->klo_resp_len = len;
1046*08855964SRyan Zezeski
1047*08855964SRyan Zezeski if (ddi_copyout(buf, klo->klo_resp, len, mode) != 0) {
1048*08855964SRyan Zezeski ret = EFAULT;
1049*08855964SRyan Zezeski goto out;
1050*08855964SRyan Zezeski }
1051*08855964SRyan Zezeski
1052*08855964SRyan Zezeski out:
1053*08855964SRyan Zezeski nvlist_free(modules);
1054*08855964SRyan Zezeski kmem_free(buf, len);
1055*08855964SRyan Zezeski return (ret);
1056*08855964SRyan Zezeski }
1057*08855964SRyan Zezeski
1058*08855964SRyan Zezeski static void
ktest_run_test(const ktest_test_t * kt,uchar_t * input,uint64_t input_len,ktest_result_t * res)1059*08855964SRyan Zezeski ktest_run_test(const ktest_test_t *kt, uchar_t *input, uint64_t input_len,
1060*08855964SRyan Zezeski ktest_result_t *res)
1061*08855964SRyan Zezeski {
1062*08855964SRyan Zezeski ktest_ctx_t ctx;
1063*08855964SRyan Zezeski
1064*08855964SRyan Zezeski bzero(&ctx, sizeof (ctx));
1065*08855964SRyan Zezeski res->kr_type = KTEST_RESULT_NONE;
1066*08855964SRyan Zezeski ctx.ktc_test = kt;
1067*08855964SRyan Zezeski ctx.ktc_res = res;
1068*08855964SRyan Zezeski ctx.ktc_input = input;
1069*08855964SRyan Zezeski ctx.ktc_input_len = input_len;
1070*08855964SRyan Zezeski kt->kt_fn((ktest_ctx_hdl_t *)&ctx);
1071*08855964SRyan Zezeski }
1072*08855964SRyan Zezeski
1073*08855964SRyan Zezeski static int
ktest_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)1074*08855964SRyan Zezeski ktest_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1075*08855964SRyan Zezeski {
1076*08855964SRyan Zezeski switch (cmd) {
1077*08855964SRyan Zezeski case DDI_INFO_DEVT2DEVINFO:
1078*08855964SRyan Zezeski *resultp = ktest_dip;
1079*08855964SRyan Zezeski break;
1080*08855964SRyan Zezeski case DDI_INFO_DEVT2INSTANCE:
1081*08855964SRyan Zezeski *resultp = (void *)0;
1082*08855964SRyan Zezeski break;
1083*08855964SRyan Zezeski default:
1084*08855964SRyan Zezeski return (DDI_FAILURE);
1085*08855964SRyan Zezeski }
1086*08855964SRyan Zezeski
1087*08855964SRyan Zezeski return (DDI_SUCCESS);
1088*08855964SRyan Zezeski }
1089*08855964SRyan Zezeski
1090*08855964SRyan Zezeski static int
ktest_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1091*08855964SRyan Zezeski ktest_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1092*08855964SRyan Zezeski {
1093*08855964SRyan Zezeski if (cmd != DDI_ATTACH) {
1094*08855964SRyan Zezeski return (DDI_FAILURE);
1095*08855964SRyan Zezeski }
1096*08855964SRyan Zezeski
1097*08855964SRyan Zezeski if (ddi_create_minor_node(dip, "ktest", S_IFCHR, KTEST_CTL_MINOR,
1098*08855964SRyan Zezeski DDI_PSEUDO, 0) != DDI_SUCCESS) {
1099*08855964SRyan Zezeski return (DDI_FAILURE);
1100*08855964SRyan Zezeski }
1101*08855964SRyan Zezeski
1102*08855964SRyan Zezeski ktest_dip = dip;
1103*08855964SRyan Zezeski ddi_report_dev(dip);
1104*08855964SRyan Zezeski return (DDI_SUCCESS);
1105*08855964SRyan Zezeski }
1106*08855964SRyan Zezeski
1107*08855964SRyan Zezeski static int
ktest_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1108*08855964SRyan Zezeski ktest_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1109*08855964SRyan Zezeski {
1110*08855964SRyan Zezeski if (cmd != DDI_DETACH) {
1111*08855964SRyan Zezeski return (DDI_FAILURE);
1112*08855964SRyan Zezeski }
1113*08855964SRyan Zezeski
1114*08855964SRyan Zezeski ddi_remove_minor_node(dip, NULL);
1115*08855964SRyan Zezeski ktest_dip = NULL;
1116*08855964SRyan Zezeski return (DDI_SUCCESS);
1117*08855964SRyan Zezeski }
1118*08855964SRyan Zezeski
1119*08855964SRyan Zezeski static int
ktest_open(dev_t * devp,int flag,int otype,cred_t * credp)1120*08855964SRyan Zezeski ktest_open(dev_t *devp, int flag, int otype, cred_t *credp)
1121*08855964SRyan Zezeski {
1122*08855964SRyan Zezeski if (otype != OTYP_CHR) {
1123*08855964SRyan Zezeski return (EINVAL);
1124*08855964SRyan Zezeski }
1125*08855964SRyan Zezeski
1126*08855964SRyan Zezeski /* Make sure attach(9E) has completed. */
1127*08855964SRyan Zezeski if (ktest_dip == NULL) {
1128*08855964SRyan Zezeski return (ENXIO);
1129*08855964SRyan Zezeski }
1130*08855964SRyan Zezeski
1131*08855964SRyan Zezeski if (getminor(*devp) != KTEST_CTL_MINOR) {
1132*08855964SRyan Zezeski return (ENXIO);
1133*08855964SRyan Zezeski }
1134*08855964SRyan Zezeski
1135*08855964SRyan Zezeski if (flag & FWRITE) {
1136*08855964SRyan Zezeski return (EACCES);
1137*08855964SRyan Zezeski }
1138*08855964SRyan Zezeski
1139*08855964SRyan Zezeski if (flag & FEXCL) {
1140*08855964SRyan Zezeski return (ENOTSUP);
1141*08855964SRyan Zezeski }
1142*08855964SRyan Zezeski
1143*08855964SRyan Zezeski /*
1144*08855964SRyan Zezeski * Access to the ktest facility requires the utmost respect:
1145*08855964SRyan Zezeski * test modules have full access to the kernel address space
1146*08855964SRyan Zezeski * and the user executing ktest can pipe in any arbitrary
1147*08855964SRyan Zezeski * stream of bytes to any test which takes an input stream.
1148*08855964SRyan Zezeski * Given this liability, and the fact the test facility should
1149*08855964SRyan Zezeski * mostly be used for development quality assurance or
1150*08855964SRyan Zezeski * production pre-flight checklists or healthchecks, it makes
1151*08855964SRyan Zezeski * sense to restrict the loading, listing, and execution of
1152*08855964SRyan Zezeski * tests to those with the highest of privilege: the root
1153*08855964SRyan Zezeski * role/user in the Global Zone.
1154*08855964SRyan Zezeski */
1155*08855964SRyan Zezeski if (drv_priv(credp) != 0 || crgetzoneid(credp) != GLOBAL_ZONEID) {
1156*08855964SRyan Zezeski return (EPERM);
1157*08855964SRyan Zezeski }
1158*08855964SRyan Zezeski
1159*08855964SRyan Zezeski return (0);
1160*08855964SRyan Zezeski }
1161*08855964SRyan Zezeski
1162*08855964SRyan Zezeski static int
ktest_close(dev_t dev,int flags,int otype,cred_t * credp)1163*08855964SRyan Zezeski ktest_close(dev_t dev, int flags, int otype, cred_t *credp)
1164*08855964SRyan Zezeski {
1165*08855964SRyan Zezeski return (0);
1166*08855964SRyan Zezeski }
1167*08855964SRyan Zezeski
1168*08855964SRyan Zezeski static int
ktest_ioctl_run_test(intptr_t arg,int mode)1169*08855964SRyan Zezeski ktest_ioctl_run_test(intptr_t arg, int mode)
1170*08855964SRyan Zezeski {
1171*08855964SRyan Zezeski int ret = 0;
1172*08855964SRyan Zezeski ktest_run_op_t kro;
1173*08855964SRyan Zezeski uchar_t *input_bytes = NULL;
1174*08855964SRyan Zezeski ktest_test_t *kt = NULL;
1175*08855964SRyan Zezeski
1176*08855964SRyan Zezeski bzero(&kro, sizeof (kro));
1177*08855964SRyan Zezeski if (ddi_copyin((void *)arg, &kro, sizeof (kro), mode) != 0) {
1178*08855964SRyan Zezeski return (EFAULT);
1179*08855964SRyan Zezeski }
1180*08855964SRyan Zezeski
1181*08855964SRyan Zezeski if (kro.kro_input_len > KTEST_IOCTL_MAX_LEN) {
1182*08855964SRyan Zezeski return (EINVAL);
1183*08855964SRyan Zezeski }
1184*08855964SRyan Zezeski
1185*08855964SRyan Zezeski /*
1186*08855964SRyan Zezeski * If there is input, copy it into KAS.
1187*08855964SRyan Zezeski */
1188*08855964SRyan Zezeski if (kro.kro_input_len > 0) {
1189*08855964SRyan Zezeski input_bytes = kmem_zalloc(kro.kro_input_len, KM_SLEEP);
1190*08855964SRyan Zezeski ret = ddi_copyin((void *)kro.kro_input_bytes, input_bytes,
1191*08855964SRyan Zezeski kro.kro_input_len, mode);
1192*08855964SRyan Zezeski
1193*08855964SRyan Zezeski if (ret != 0) {
1194*08855964SRyan Zezeski ret = EFAULT;
1195*08855964SRyan Zezeski goto done;
1196*08855964SRyan Zezeski }
1197*08855964SRyan Zezeski }
1198*08855964SRyan Zezeski
1199*08855964SRyan Zezeski mutex_enter(&ktest_lock);
1200*08855964SRyan Zezeski kt = ktest_get_test(kro.kro_module, kro.kro_suite, kro.kro_test);
1201*08855964SRyan Zezeski
1202*08855964SRyan Zezeski /*
1203*08855964SRyan Zezeski * We failed to find a matching test. The ktest command should
1204*08855964SRyan Zezeski * always send down a valid fully-qualified triple; but it's
1205*08855964SRyan Zezeski * good hygiene to check for this case.
1206*08855964SRyan Zezeski */
1207*08855964SRyan Zezeski if (kt == NULL) {
1208*08855964SRyan Zezeski ret = ENOENT;
1209*08855964SRyan Zezeski goto done;
1210*08855964SRyan Zezeski }
1211*08855964SRyan Zezeski
1212*08855964SRyan Zezeski /*
1213*08855964SRyan Zezeski * The test requires input but none was provided. The ktest
1214*08855964SRyan Zezeski * command should not send down such a request; but it's good
1215*08855964SRyan Zezeski * hygiene to check for it.
1216*08855964SRyan Zezeski */
1217*08855964SRyan Zezeski if (kt->kt_requires_input && kro.kro_input_len == 0) {
1218*08855964SRyan Zezeski ret = EINVAL;
1219*08855964SRyan Zezeski goto done;
1220*08855964SRyan Zezeski }
1221*08855964SRyan Zezeski
1222*08855964SRyan Zezeski ktest_run_test(kt, input_bytes, kro.kro_input_len, &kro.kro_result);
1223*08855964SRyan Zezeski
1224*08855964SRyan Zezeski done:
1225*08855964SRyan Zezeski mutex_exit(&ktest_lock);
1226*08855964SRyan Zezeski kmem_free(input_bytes, kro.kro_input_len);
1227*08855964SRyan Zezeski
1228*08855964SRyan Zezeski if (ret == 0 &&
1229*08855964SRyan Zezeski ddi_copyout(&kro, (void *)arg, sizeof (kro), mode) != 0) {
1230*08855964SRyan Zezeski ret = EFAULT;
1231*08855964SRyan Zezeski }
1232*08855964SRyan Zezeski
1233*08855964SRyan Zezeski return (ret);
1234*08855964SRyan Zezeski }
1235*08855964SRyan Zezeski
1236*08855964SRyan Zezeski static int
ktest_ioctl_list_tests(intptr_t arg,int mode)1237*08855964SRyan Zezeski ktest_ioctl_list_tests(intptr_t arg, int mode)
1238*08855964SRyan Zezeski {
1239*08855964SRyan Zezeski int ret = 0;
1240*08855964SRyan Zezeski ktest_list_op_t klo;
1241*08855964SRyan Zezeski
1242*08855964SRyan Zezeski bzero(&klo, sizeof (klo));
1243*08855964SRyan Zezeski if (ddi_copyin((void *)arg, &klo, sizeof (klo), mode) != 0) {
1244*08855964SRyan Zezeski return (EFAULT);
1245*08855964SRyan Zezeski }
1246*08855964SRyan Zezeski
1247*08855964SRyan Zezeski if ((ret = ktest_list_tests(&klo, mode)) == 0) {
1248*08855964SRyan Zezeski if (ddi_copyout(&klo, (void *)arg, sizeof (klo), mode) != 0) {
1249*08855964SRyan Zezeski return (EFAULT);
1250*08855964SRyan Zezeski }
1251*08855964SRyan Zezeski }
1252*08855964SRyan Zezeski
1253*08855964SRyan Zezeski return (ret);
1254*08855964SRyan Zezeski }
1255*08855964SRyan Zezeski
1256*08855964SRyan Zezeski static int
ktest_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)1257*08855964SRyan Zezeski ktest_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
1258*08855964SRyan Zezeski int *rvalp)
1259*08855964SRyan Zezeski {
1260*08855964SRyan Zezeski int ret = 0;
1261*08855964SRyan Zezeski
1262*08855964SRyan Zezeski /*
1263*08855964SRyan Zezeski * We make two assumptions:
1264*08855964SRyan Zezeski *
1265*08855964SRyan Zezeski * 1. That only the ktest command interacts with the ktest driver.
1266*08855964SRyan Zezeski *
1267*08855964SRyan Zezeski * 2. The the ktest command is 64-bit.
1268*08855964SRyan Zezeski */
1269*08855964SRyan Zezeski if (ddi_model_convert_from(mode) != DDI_MODEL_NONE) {
1270*08855964SRyan Zezeski return (ENOSYS);
1271*08855964SRyan Zezeski }
1272*08855964SRyan Zezeski
1273*08855964SRyan Zezeski switch (cmd) {
1274*08855964SRyan Zezeski case KTEST_IOCTL_RUN_TEST:
1275*08855964SRyan Zezeski ret = ktest_ioctl_run_test(arg, mode);
1276*08855964SRyan Zezeski break;
1277*08855964SRyan Zezeski
1278*08855964SRyan Zezeski case KTEST_IOCTL_LIST_TESTS:
1279*08855964SRyan Zezeski ret = ktest_ioctl_list_tests(arg, mode);
1280*08855964SRyan Zezeski break;
1281*08855964SRyan Zezeski
1282*08855964SRyan Zezeski default:
1283*08855964SRyan Zezeski ret = EINVAL;
1284*08855964SRyan Zezeski break;
1285*08855964SRyan Zezeski }
1286*08855964SRyan Zezeski
1287*08855964SRyan Zezeski return (ret);
1288*08855964SRyan Zezeski }
1289*08855964SRyan Zezeski
1290*08855964SRyan Zezeski static struct cb_ops ktest_cb_ops = {
1291*08855964SRyan Zezeski .cb_open = ktest_open,
1292*08855964SRyan Zezeski .cb_close = ktest_close,
1293*08855964SRyan Zezeski .cb_strategy = nodev,
1294*08855964SRyan Zezeski .cb_print = nodev,
1295*08855964SRyan Zezeski .cb_dump = nodev,
1296*08855964SRyan Zezeski .cb_read = nodev,
1297*08855964SRyan Zezeski .cb_write = nodev,
1298*08855964SRyan Zezeski .cb_ioctl = ktest_ioctl,
1299*08855964SRyan Zezeski .cb_devmap = nodev,
1300*08855964SRyan Zezeski .cb_mmap = nodev,
1301*08855964SRyan Zezeski .cb_segmap = nodev,
1302*08855964SRyan Zezeski .cb_chpoll = nochpoll,
1303*08855964SRyan Zezeski .cb_prop_op = ddi_prop_op,
1304*08855964SRyan Zezeski .cb_flag = D_MP | D_64BIT,
1305*08855964SRyan Zezeski .cb_rev = CB_REV,
1306*08855964SRyan Zezeski .cb_aread = nodev,
1307*08855964SRyan Zezeski .cb_awrite = nodev,
1308*08855964SRyan Zezeski .cb_str = NULL
1309*08855964SRyan Zezeski };
1310*08855964SRyan Zezeski
1311*08855964SRyan Zezeski static struct dev_ops ktest_dev_ops = {
1312*08855964SRyan Zezeski .devo_rev = DEVO_REV,
1313*08855964SRyan Zezeski .devo_refcnt = 0,
1314*08855964SRyan Zezeski .devo_getinfo = ktest_getinfo,
1315*08855964SRyan Zezeski .devo_identify = nulldev,
1316*08855964SRyan Zezeski .devo_probe = nulldev,
1317*08855964SRyan Zezeski .devo_attach = ktest_attach,
1318*08855964SRyan Zezeski .devo_detach = ktest_detach,
1319*08855964SRyan Zezeski .devo_reset = nodev,
1320*08855964SRyan Zezeski .devo_power = NULL,
1321*08855964SRyan Zezeski .devo_quiesce = ddi_quiesce_not_supported,
1322*08855964SRyan Zezeski .devo_cb_ops = &ktest_cb_ops,
1323*08855964SRyan Zezeski .devo_bus_ops = NULL
1324*08855964SRyan Zezeski };
1325*08855964SRyan Zezeski
1326*08855964SRyan Zezeski static struct modldrv ktest_modldrv = {
1327*08855964SRyan Zezeski .drv_modops = &mod_driverops,
1328*08855964SRyan Zezeski .drv_linkinfo = "Kernel Test Driver v1",
1329*08855964SRyan Zezeski .drv_dev_ops = &ktest_dev_ops
1330*08855964SRyan Zezeski };
1331*08855964SRyan Zezeski
1332*08855964SRyan Zezeski static struct modlinkage ktest_modlinkage = {
1333*08855964SRyan Zezeski .ml_rev = MODREV_1,
1334*08855964SRyan Zezeski .ml_linkage = { &ktest_modldrv, NULL }
1335*08855964SRyan Zezeski };
1336*08855964SRyan Zezeski
1337*08855964SRyan Zezeski static void
ktest_fini()1338*08855964SRyan Zezeski ktest_fini()
1339*08855964SRyan Zezeski {
1340*08855964SRyan Zezeski ktest_unregister_all();
1341*08855964SRyan Zezeski list_destroy(&ktest_modules);
1342*08855964SRyan Zezeski mutex_destroy(&ktest_lock);
1343*08855964SRyan Zezeski }
1344*08855964SRyan Zezeski
1345*08855964SRyan Zezeski /*
1346*08855964SRyan Zezeski * This is a pseudo device driver with a single instance, therefore
1347*08855964SRyan Zezeski * all state is allocated/freed during init/fini. We delay the
1348*08855964SRyan Zezeski * creation of the taskq until attach, since tests cannot be executed
1349*08855964SRyan Zezeski * until the driver is attached.
1350*08855964SRyan Zezeski */
1351*08855964SRyan Zezeski int
_init(void)1352*08855964SRyan Zezeski _init(void)
1353*08855964SRyan Zezeski {
1354*08855964SRyan Zezeski int ret;
1355*08855964SRyan Zezeski
1356*08855964SRyan Zezeski mutex_init(&ktest_lock, NULL, MUTEX_DRIVER, NULL);
1357*08855964SRyan Zezeski list_create(&ktest_modules, sizeof (ktest_module_t),
1358*08855964SRyan Zezeski offsetof(ktest_module_t, km_node));
1359*08855964SRyan Zezeski ret = mod_install(&ktest_modlinkage);
1360*08855964SRyan Zezeski
1361*08855964SRyan Zezeski if (ret != DDI_SUCCESS) {
1362*08855964SRyan Zezeski ktest_fini();
1363*08855964SRyan Zezeski }
1364*08855964SRyan Zezeski
1365*08855964SRyan Zezeski return (ret);
1366*08855964SRyan Zezeski }
1367*08855964SRyan Zezeski
1368*08855964SRyan Zezeski int
_fini(void)1369*08855964SRyan Zezeski _fini(void)
1370*08855964SRyan Zezeski {
1371*08855964SRyan Zezeski int ret = mod_remove(&ktest_modlinkage);
1372*08855964SRyan Zezeski
1373*08855964SRyan Zezeski if (ret == DDI_SUCCESS) {
1374*08855964SRyan Zezeski ktest_fini();
1375*08855964SRyan Zezeski }
1376*08855964SRyan Zezeski
1377*08855964SRyan Zezeski return (ret);
1378*08855964SRyan Zezeski }
1379*08855964SRyan Zezeski
1380*08855964SRyan Zezeski int
_info(struct modinfo * modinfop)1381*08855964SRyan Zezeski _info(struct modinfo *modinfop)
1382*08855964SRyan Zezeski {
1383*08855964SRyan Zezeski return (mod_info(&ktest_modlinkage, modinfop));
1384*08855964SRyan Zezeski }
1385