1/* $NetBSD: module.h,v 1.41 2016/11/16 10:42:14 pgoyette Exp $ */
2
3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef _SYS_MODULE_H_
30#define _SYS_MODULE_H_
31
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/cdefs.h>
35#include <sys/queue.h>
36#include <sys/uio.h>
37
38#define MAXMODNAME 32
39#define MAXMODDEPS 10
40
41/* Module classes, provided only for system boot and cosmetic purposes. */
42typedef enum modclass {
43 MODULE_CLASS_ANY,
44 MODULE_CLASS_MISC,
45 MODULE_CLASS_VFS,
46 MODULE_CLASS_DRIVER,
47 MODULE_CLASS_EXEC,
48 MODULE_CLASS_SECMODEL,
49 MODULE_CLASS_BUFQ
50} modclass_t;
51
52/* Module sources: where did it come from? */
53typedef enum modsrc {
54 MODULE_SOURCE_KERNEL,
55 MODULE_SOURCE_BOOT,
56 MODULE_SOURCE_FILESYS
57} modsrc_t;
58
59/* Commands passed to module control routine. */
60typedef enum modcmd {
61 MODULE_CMD_INIT, /* mandatory */
62 MODULE_CMD_FINI, /* mandatory */
63 MODULE_CMD_STAT, /* optional */
64 MODULE_CMD_AUTOUNLOAD, /* optional */
65} modcmd_t;
66
67#ifdef _KERNEL
68
69#include <sys/kernel.h>
70#include <sys/mutex.h>
71
72#include <prop/proplib.h>
73
74/* Module header structure. */
75typedef struct modinfo {
76 u_int mi_version;
77 modclass_t mi_class;
78 int (*mi_modcmd)(modcmd_t, void *);
79 const char *mi_name;
80 const char *mi_required;
81} const modinfo_t;
82
83/* Per module information, maintained by kern_module.c */
84typedef struct module {
85 u_int mod_refcnt;
86 const modinfo_t *mod_info;
87 struct kobj *mod_kobj;
88 TAILQ_ENTRY(module) mod_chain;
89 struct module *mod_required[MAXMODDEPS];
90 u_int mod_nrequired;
91 modsrc_t mod_source;
92 time_t mod_autotime;
93 void *mod_ctf;
94 u_int mod_fbtentries; /* DTrace FBT entry count */
95 int mod_flags;
96#define MODFLG_MUST_FORCE 0x01
97#define MODFLG_AUTO_LOADED 0x02
98
99} module_t;
100
101/*
102 * Per-module linkage. Loadable modules have a `link_set_modules' section
103 * containing only one entry, pointing to the module's modinfo_t record.
104 * For the kernel, `link_set_modules' can contain multiple entries and
105 * records all modules built into the kernel at link time.
106 *
107 * Alternatively, in some environments rump kernels use
108 * __attribute__((constructor)) due to link sets being
109 * difficult (impossible?) to implement (e.g. GNU gold, OS X, etc.)
110 * If we're cold (read: rump_init() has not been called), we lob the
111 * module onto the list to be handled when rump_init() runs.
112 * nb. it's not possible to use in-kernel locking mechanisms here since
113 * the code runs before rump_init(). We solve the problem by decreeing
114 * that thou shalt not call dlopen()/dlclose() for rump kernel components
115 * from multiple threads before calling rump_init().
116 */
117
118#ifdef RUMP_USE_CTOR
119struct modinfo_chain {
120 const struct modinfo *mc_info;
121 LIST_ENTRY(modinfo_chain) mc_entries;
122};
123LIST_HEAD(modinfo_boot_chain, modinfo_chain);
124#define _MODULE_REGISTER(name) \
125static struct modinfo_chain __CONCAT(mc,name) = { \
126 .mc_info = &__CONCAT(name,_modinfo), \
127}; \
128static void __CONCAT(modctor_,name)(void) __attribute__((__constructor__));\
129static void __CONCAT(modctor_,name)(void) \
130{ \
131 extern struct modinfo_boot_chain modinfo_boot_chain; \
132 if (cold) { \
133 struct modinfo_chain *mc = &__CONCAT(mc,name); \
134 LIST_INSERT_HEAD(&modinfo_boot_chain, mc, mc_entries); \
135 } \
136} \
137 \
138static void __CONCAT(moddtor_,name)(void) __attribute__((__destructor__));\
139static void __CONCAT(moddtor_,name)(void) \
140{ \
141 struct modinfo_chain *mc = &__CONCAT(mc,name); \
142 if (cold) { \
143 LIST_REMOVE(mc, mc_entries); \
144 } \
145}
146
147#else /* RUMP_USE_CTOR */
148
149#define _MODULE_REGISTER(name) __link_set_add_rodata(modules, __CONCAT(name,_modinfo));
150
151#endif /* RUMP_USE_CTOR */
152
153#define MODULE(class, name, required) \
154static int __CONCAT(name,_modcmd)(modcmd_t, void *); \
155static const modinfo_t __CONCAT(name,_modinfo) = { \
156 .mi_version = __NetBSD_Version__, \
157 .mi_class = (class), \
158 .mi_modcmd = __CONCAT(name,_modcmd), \
159 .mi_name = __STRING(name), \
160 .mi_required = (required) \
161}; \
162_MODULE_REGISTER(name)
163
164TAILQ_HEAD(modlist, module);
165
166extern struct vm_map *module_map;
167extern u_int module_count;
168extern u_int module_builtinlist;
169extern struct modlist module_list;
170extern struct modlist module_builtins;
171extern u_int module_gen;
172
173void module_init(void);
174void module_start_unload_thread(void);
175void module_builtin_require_force(void);
176void module_init_md(void);
177void module_init_class(modclass_t);
178int module_prime(const char *, void *, size_t);
179
180bool module_compatible(int, int);
181int module_load(const char *, int, prop_dictionary_t, modclass_t);
182int module_builtin_add(modinfo_t * const *, size_t, bool);
183int module_builtin_remove(modinfo_t *, bool);
184int module_autoload(const char *, modclass_t);
185int module_unload(const char *);
186int module_hold(const char *);
187void module_rele(const char *);
188int module_find_section(const char *, void **, size_t *);
189void module_thread_kick(void);
190void module_load_vfs_init(void);
191
192void module_whatis(uintptr_t, void (*)(const char *, ...)
193 __printflike(1, 2));
194void module_print_list(void (*)(const char *, ...) __printflike(1, 2));
195
196#ifdef _MODULE_INTERNAL
197extern
198int (*module_load_vfs_vec)(const char *, int, bool, module_t *,
199 prop_dictionary_t *);
200int module_load_vfs(const char *, int, bool, module_t *,
201 prop_dictionary_t *);
202void module_error(const char *, ...) __printflike(1, 2);
203void module_print(const char *, ...) __printflike(1, 2);
204#endif /* _MODULE_INTERNAL */
205
206#define MODULE_BASE_SIZE 64
207extern char module_base[MODULE_BASE_SIZE];
208extern const char *module_machine;
209
210#else /* _KERNEL */
211
212#include <stdint.h>
213
214#endif /* _KERNEL */
215
216typedef struct modctl_load {
217 const char *ml_filename;
218
219#define MODCTL_NO_PROP 0x2
220#define MODCTL_LOAD_FORCE 0x1
221 int ml_flags;
222
223 const char *ml_props;
224 size_t ml_propslen;
225} modctl_load_t;
226
227typedef enum modctl {
228 MODCTL_LOAD, /* modctl_load_t *ml */
229 MODCTL_UNLOAD, /* char *name */
230 MODCTL_STAT, /* struct iovec *buffer */
231 MODCTL_EXISTS /* enum: 0: load, 1: autoload */
232} modctl_t;
233
234/*
235 * This structure intentionally has the same layout for 32 and 64
236 * bit builds.
237 */
238typedef struct modstat {
239 char ms_name[MAXMODNAME];
240 char ms_required[MAXMODNAME * MAXMODDEPS];
241 uint64_t ms_addr;
242 modsrc_t ms_source;
243 modclass_t ms_class;
244 u_int ms_size;
245 u_int ms_refcnt;
246 u_int ms_flags;
247 u_int ms_reserved[3];
248} modstat_t;
249
250int modctl(int, void *);
251
252#ifdef _KERNEL
253/* attention: pointers passed are userland pointers!,
254 see modctl_load_t */
255int handle_modctl_load(const char *, int, const char *, size_t);
256#endif
257
258#endif /* !_SYS_MODULE_H_ */
259