1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright (c) 2018, Joyent, Inc.
28 * Copyright 2021 Oxide Computer Company
29 */
30
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/param.h>
34 #include <sys/user.h>
35 #include <sys/vm.h>
36 #include <sys/conf.h>
37 #include <sys/class.h>
38 #include <sys/vfs.h>
39 #include <sys/vnode.h>
40 #include <sys/mount.h>
41 #include <sys/systm.h>
42 #include <sys/modctl.h>
43 #include <sys/exec.h>
44 #include <sys/exechdr.h>
45 #include <sys/devops.h>
46 #include <sys/ddi.h>
47 #include <sys/sunddi.h>
48 #include <sys/cmn_err.h>
49 #include <sys/hwconf.h>
50 #include <sys/ddi_impldefs.h>
51 #include <sys/autoconf.h>
52 #include <sys/disp.h>
53 #include <sys/kmem.h>
54 #include <sys/instance.h>
55 #include <sys/modhash.h>
56 #include <sys/dacf.h>
57 #include <sys/debug.h>
58 #include <ipp/ipp.h>
59 #include <sys/strsubr.h>
60 #include <sys/kcpc.h>
61 #include <sys/brand.h>
62 #include <sys/cpc_pcbe.h>
63 #include <sys/kstat.h>
64 #include <sys/socketvar.h>
65 #include <sys/kiconv.h>
66
67 extern int moddebug;
68
69 extern struct cb_ops no_cb_ops;
70 extern struct dev_ops nodev_ops;
71 extern struct dev_ops mod_nodev_ops;
72
73 extern struct modctl *mod_getctl(struct modlinkage *);
74 extern int errsys(), nodev(), nulldev();
75
76 extern int findmodbyname(char *);
77 extern int mod_getsysnum(const char *);
78
79 extern struct execsw execsw[];
80
81 /*
82 * Define dev_ops for unused devopsp entry.
83 */
84 struct dev_ops mod_nodev_ops = {
85 DEVO_REV, /* devo_rev */
86 0, /* refcnt */
87 ddi_no_info, /* info */
88 nulldev, /* identify */
89 nulldev, /* probe */
90 ddifail, /* attach */
91 nodev, /* detach */
92 nulldev, /* reset */
93 &no_cb_ops, /* character/block driver operations */
94 (struct bus_ops *)0 /* bus operations for nexus drivers */
95 };
96
97 /*
98 * Define mod_ops for each supported module type
99 */
100
101 /*
102 * Null operations; used for uninitialized and "misc" modules.
103 */
104 static int mod_null(struct modldrv *, struct modlinkage *);
105 static int mod_infonull(void *, struct modlinkage *, int *);
106
107 struct mod_ops mod_miscops = {
108 mod_null, mod_null, mod_infonull
109 };
110
111 /* CPU Modules */
112 struct mod_ops mod_cpuops = {
113 mod_null, mod_null, mod_infonull
114 };
115
116 /*
117 * Cryptographic Modules
118 */
119 struct mod_ops mod_cryptoops = {
120 mod_null, mod_null, mod_infonull
121 };
122
123 /*
124 * IP Policy Modules
125 */
126 static int mod_installipp(struct modlipp *, struct modlinkage *);
127 static int mod_removeipp(struct modlipp *, struct modlinkage *);
128 static int mod_infoipp(struct modlipp *, struct modlinkage *, int *);
129
130 struct mod_ops mod_ippops = {
131 mod_installipp, mod_removeipp, mod_infoipp
132 };
133
134 /*
135 * Device drivers
136 */
137 static int mod_infodrv(struct modldrv *, struct modlinkage *, int *);
138 static int mod_installdrv(struct modldrv *, struct modlinkage *);
139 static int mod_removedrv(struct modldrv *, struct modlinkage *);
140
141 struct mod_ops mod_driverops = {
142 mod_installdrv, mod_removedrv, mod_infodrv
143 };
144
145 /*
146 * System calls (new interface)
147 */
148 static int mod_infosys(struct modlsys *, struct modlinkage *, int *);
149 static int mod_installsys(struct modlsys *, struct modlinkage *);
150 static int mod_removesys(struct modlsys *, struct modlinkage *);
151
152 struct mod_ops mod_syscallops = {
153 mod_installsys, mod_removesys, mod_infosys
154 };
155
156 #ifdef _SYSCALL32_IMPL
157 /*
158 * 32-bit system calls in 64-bit kernel
159 */
160 static int mod_infosys32(struct modlsys *, struct modlinkage *, int *);
161 static int mod_installsys32(struct modlsys *, struct modlinkage *);
162 static int mod_removesys32(struct modlsys *, struct modlinkage *);
163
164 struct mod_ops mod_syscallops32 = {
165 mod_installsys32, mod_removesys32, mod_infosys32
166 };
167 #endif /* _SYSCALL32_IMPL */
168
169 /*
170 * Filesystems
171 */
172 static int mod_infofs(struct modlfs *, struct modlinkage *, int *);
173 static int mod_installfs(struct modlfs *, struct modlinkage *);
174 static int mod_removefs(struct modlfs *, struct modlinkage *);
175
176 struct mod_ops mod_fsops = {
177 mod_installfs, mod_removefs, mod_infofs
178 };
179
180 /*
181 * Streams modules.
182 */
183 static int mod_infostrmod(struct modlstrmod *, struct modlinkage *, int *);
184 static int mod_installstrmod(struct modlstrmod *, struct modlinkage *);
185 static int mod_removestrmod(struct modlstrmod *, struct modlinkage *);
186
187 struct mod_ops mod_strmodops = {
188 mod_installstrmod, mod_removestrmod, mod_infostrmod
189 };
190
191 /*
192 * Socket modules.
193 */
194 static int mod_infosockmod(struct modlsockmod *, struct modlinkage *, int *);
195 static int mod_installsockmod(struct modlsockmod *, struct modlinkage *);
196 static int mod_removesockmod(struct modlsockmod *, struct modlinkage *);
197
198 struct mod_ops mod_sockmodops = {
199 mod_installsockmod, mod_removesockmod, mod_infosockmod
200 };
201
202 /*
203 * Scheduling classes.
204 */
205 static int mod_infosched(struct modlsched *, struct modlinkage *, int *);
206 static int mod_installsched(struct modlsched *, struct modlinkage *);
207 static int mod_removesched(struct modlsched *, struct modlinkage *);
208
209 struct mod_ops mod_schedops = {
210 mod_installsched, mod_removesched, mod_infosched
211 };
212
213 /*
214 * Exec file type (like ELF, ...).
215 */
216 static int mod_infoexec(struct modlexec *, struct modlinkage *, int *);
217 static int mod_installexec(struct modlexec *, struct modlinkage *);
218 static int mod_removeexec(struct modlexec *, struct modlinkage *);
219
220 struct mod_ops mod_execops = {
221 mod_installexec, mod_removeexec, mod_infoexec
222 };
223
224 /*
225 * Dacf (Dynamic Autoconfiguration) modules.
226 */
227 static int mod_infodacf(struct modldacf *, struct modlinkage *, int *);
228 static int mod_installdacf(struct modldacf *, struct modlinkage *);
229 static int mod_removedacf(struct modldacf *, struct modlinkage *);
230
231 struct mod_ops mod_dacfops = {
232 mod_installdacf, mod_removedacf, mod_infodacf
233 };
234
235 /*
236 * PCBE (Performance Counter BackEnd) modules.
237 */
238 static int mod_installpcbe(struct modlpcbe *, struct modlinkage *);
239 static int mod_removepcbe(struct modlpcbe *, struct modlinkage *);
240
241 struct mod_ops mod_pcbeops = {
242 mod_installpcbe, mod_removepcbe, mod_infonull
243 };
244
245 /*
246 * Brand modules.
247 */
248 static int mod_installbrand(struct modlbrand *, struct modlinkage *);
249 static int mod_removebrand(struct modlbrand *, struct modlinkage *);
250
251 struct mod_ops mod_brandops = {
252 mod_installbrand, mod_removebrand, mod_infonull
253 };
254
255 /*
256 * kiconv modules.
257 */
258 static int mod_installkiconv(struct modlkiconv *, struct modlinkage *);
259 static int mod_removekiconv(struct modlkiconv *, struct modlinkage *);
260
261 struct mod_ops mod_kiconvops = {
262 mod_installkiconv, mod_removekiconv, mod_infonull
263 };
264
265 static struct sysent *mod_getsysent(struct modlinkage *, struct sysent *);
266
267 static char uninstall_err[] = "Cannot uninstall %s; not installed";
268
269 /*
270 * Debugging support
271 */
272 #define DRV_DBG MODDEBUG_LOADMSG2
273
274 /*PRINTFLIKE2*/
275 static void mod_dprintf(int flag, const char *format, ...) __KPRINTFLIKE(2);
276
277 static void
mod_dprintf(int flag,const char * format,...)278 mod_dprintf(int flag, const char *format, ...)
279 {
280 va_list alist;
281
282 if ((moddebug & flag) != 0) {
283 va_start(alist, format);
284 (void) vprintf(format, alist);
285 va_end(alist);
286 }
287 }
288
289 /*
290 * Install a module.
291 * (This routine is in the Solaris SPARC DDI/DKI)
292 */
293 int
mod_install(struct modlinkage * modlp)294 mod_install(struct modlinkage *modlp)
295 {
296 int retval = -1; /* No linkage structures */
297 struct modlmisc **linkpp;
298 struct modlmisc **linkpp1;
299
300 if (modlp->ml_rev != MODREV_1) {
301 printf("mod_install: modlinkage structure is not MODREV_1\n");
302 return (EINVAL);
303 }
304 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
305
306 while (*linkpp != NULL) {
307 if ((retval = MODL_INSTALL(*linkpp, modlp)) != 0) {
308 linkpp1 = (struct modlmisc **)&modlp->ml_linkage[0];
309
310 while (linkpp1 != linkpp) {
311 MODL_REMOVE(*linkpp1, modlp); /* clean up */
312 linkpp1++;
313 }
314 break;
315 }
316 linkpp++;
317 }
318 return (retval);
319 }
320
321 static char *reins_err =
322 "Could not reinstall %s\nReboot to correct the problem";
323
324 /*
325 * Remove a module. This is called by the module wrapper routine.
326 * (This routine is in the Solaris SPARC DDI/DKI)
327 */
328 int
mod_remove(struct modlinkage * modlp)329 mod_remove(struct modlinkage *modlp)
330 {
331 int retval = 0;
332 struct modlmisc **linkpp, *last_linkp;
333
334 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
335
336 while (*linkpp != NULL) {
337 if ((retval = MODL_REMOVE(*linkpp, modlp)) != 0) {
338 last_linkp = *linkpp;
339 linkpp = (struct modlmisc **)&modlp->ml_linkage[0];
340 while (*linkpp != last_linkp) {
341 if (MODL_INSTALL(*linkpp, modlp) != 0) {
342 cmn_err(CE_WARN, reins_err,
343 (*linkpp)->misc_linkinfo);
344 break;
345 }
346 linkpp++;
347 }
348 break;
349 }
350 linkpp++;
351 }
352 return (retval);
353 }
354
355 /*
356 * Get module status.
357 * (This routine is in the Solaris SPARC DDI/DKI)
358 */
359 int
mod_info(struct modlinkage * modlp,struct modinfo * modinfop)360 mod_info(struct modlinkage *modlp, struct modinfo *modinfop)
361 {
362 int i;
363 int retval = 0;
364 struct modspecific_info *msip;
365 struct modlmisc **linkpp;
366
367 modinfop->mi_rev = modlp->ml_rev;
368
369 linkpp = (struct modlmisc **)modlp->ml_linkage;
370 msip = &modinfop->mi_msinfo[0];
371
372 for (i = 0; i < MODMAXLINK; i++) {
373 if (*linkpp == NULL) {
374 msip->msi_linkinfo[0] = '\0';
375 } else {
376 (void) strncpy(msip->msi_linkinfo,
377 (*linkpp)->misc_linkinfo, MODMAXLINKINFOLEN);
378 retval = MODL_INFO(*linkpp, modlp, &msip->msi_p0);
379 if (retval != 0)
380 break;
381 linkpp++;
382 }
383 msip++;
384 }
385
386 if (modinfop->mi_info == MI_INFO_LINKAGE) {
387 /*
388 * Slight kludge used to extract the address of the
389 * modlinkage structure from the module (just after
390 * loading a module for the very first time)
391 */
392 modinfop->mi_base = (void *)modlp;
393 }
394
395 if (retval == 0)
396 return (1);
397 return (0);
398 }
399
400 /*
401 * Get module name.
402 */
403 const char *
mod_modname(struct modlinkage * modlp)404 mod_modname(struct modlinkage *modlp)
405 {
406 struct modctl *mcp;
407
408 if ((mcp = mod_getctl(modlp)) == NULL)
409 return (NULL);
410
411 return (mcp->mod_modname);
412 }
413
414 /*
415 * Null operation; return 0.
416 */
417 /*ARGSUSED*/
418 static int
mod_null(struct modldrv * modl,struct modlinkage * modlp)419 mod_null(struct modldrv *modl, struct modlinkage *modlp)
420 {
421 return (0);
422 }
423
424 /*
425 * Status for User modules.
426 */
427 /*ARGSUSED*/
428 static int
mod_infonull(void * modl,struct modlinkage * modlp,int * p0)429 mod_infonull(void *modl, struct modlinkage *modlp, int *p0)
430 {
431 *p0 = -1; /* for modinfo display */
432 return (0);
433 }
434
435 /*
436 * Driver status info
437 */
438 /*ARGSUSED*/
439 static int
mod_infodrv(struct modldrv * modl,struct modlinkage * modlp,int * p0)440 mod_infodrv(struct modldrv *modl, struct modlinkage *modlp, int *p0)
441 {
442 struct modctl *mcp;
443 char *mod_name;
444
445 if ((mcp = mod_getctl(modlp)) == NULL) {
446 *p0 = -1;
447 return (0); /* driver is not yet installed */
448 }
449
450 mod_name = mcp->mod_modname;
451
452 *p0 = ddi_name_to_major(mod_name);
453 return (0);
454 }
455
456 /*
457 * Manage dacf (device autoconfiguration) modules
458 */
459
460 /*ARGSUSED*/
461 static int
mod_infodacf(struct modldacf * modl,struct modlinkage * modlp,int * p0)462 mod_infodacf(struct modldacf *modl, struct modlinkage *modlp, int *p0)
463 {
464 if (mod_getctl(modlp) == NULL) {
465 *p0 = -1;
466 return (0); /* module is not yet installed */
467 }
468
469 *p0 = 0;
470 return (0);
471 }
472
473 static int
mod_installdacf(struct modldacf * modl,struct modlinkage * modlp)474 mod_installdacf(struct modldacf *modl, struct modlinkage *modlp)
475 {
476 struct modctl *mcp;
477
478 if ((mcp = mod_getctl(modlp)) == NULL)
479 return (EINVAL);
480 return (dacf_module_register(mcp->mod_modname, modl->dacf_dacfsw));
481 }
482
483 /*ARGSUSED*/
484 static int
mod_removedacf(struct modldacf * modl,struct modlinkage * modlp)485 mod_removedacf(struct modldacf *modl, struct modlinkage *modlp)
486 {
487 struct modctl *mcp;
488
489 if ((mcp = mod_getctl(modlp)) == NULL)
490 return (EINVAL);
491 return (dacf_module_unregister(mcp->mod_modname));
492 }
493
494 /*
495 * Manage PCBE (Performance Counter BackEnd) modules.
496 */
497 /*ARGSUSED*/
498 static int
mod_installpcbe(struct modlpcbe * modl,struct modlinkage * modlp)499 mod_installpcbe(struct modlpcbe *modl, struct modlinkage *modlp)
500 {
501 if (modl->pcbe_ops->pcbe_ver != PCBE_VER_1) {
502 cmn_err(CE_WARN, "pcbe '%s' version mismatch",
503 modl->pcbe_linkinfo);
504 return (EINVAL);
505 }
506
507 kcpc_register_pcbe(modl->pcbe_ops);
508 return (0);
509 }
510
511 /*
512 * PCBEs may not be unloaded. It would make CPC locking too complex, and since
513 * PCBEs are loaded once and used for life, there is no harm done in leaving
514 * them in the system.
515 */
516 /*ARGSUSED*/
517 static int
mod_removepcbe(struct modlpcbe * modl,struct modlinkage * modlp)518 mod_removepcbe(struct modlpcbe *modl, struct modlinkage *modlp)
519 {
520 return (EBUSY);
521 }
522
523 /*
524 * Manage BrandZ modules.
525 */
526 /*ARGSUSED*/
527 static int
mod_installbrand(struct modlbrand * modl,struct modlinkage * modlp)528 mod_installbrand(struct modlbrand *modl, struct modlinkage *modlp)
529 {
530 return (brand_register(modl->brand_branddef));
531 }
532
533 /*ARGSUSED*/
534 static int
mod_removebrand(struct modlbrand * modl,struct modlinkage * modlp)535 mod_removebrand(struct modlbrand *modl, struct modlinkage *modlp)
536 {
537 return (brand_unregister(modl->brand_branddef));
538 }
539
540 /*
541 * Install a new driver
542 */
543 static int
mod_installdrv(struct modldrv * modl,struct modlinkage * modlp)544 mod_installdrv(struct modldrv *modl, struct modlinkage *modlp)
545 {
546 struct modctl *mcp;
547 struct dev_ops *ops;
548 char *modname;
549 major_t major;
550 struct dev_ops *dp;
551 struct devnames *dnp;
552 struct streamtab *str;
553 cdevsw_impl_t *cdp;
554 uint_t sqtype;
555 uint_t qflag;
556 uint_t flag;
557 int err = 0;
558
559 /* sanity check module */
560 if ((mcp = mod_getctl(modlp)) == NULL) {
561 cmn_err(CE_WARN, "mod_install: bad module linkage data");
562 err = ENXIO;
563 goto done;
564 }
565 modname = mcp->mod_modname;
566
567 /* Sanity check modname */
568 if ((major = ddi_name_to_major(modname)) == DDI_MAJOR_T_NONE) {
569 cmn_err(CE_WARN,
570 "mod_installdrv: no major number for %s", modname);
571 err = ENXIO;
572 goto done;
573 }
574
575 /* Verify MP safety flag */
576 ops = modl->drv_dev_ops;
577 if (ops->devo_bus_ops == NULL && ops->devo_cb_ops != NULL &&
578 !(ops->devo_cb_ops->cb_flag & D_MP)) {
579 cmn_err(CE_WARN,
580 "mod_installdrv: MT-unsafe driver '%s' rejected", modname);
581 err = ENXIO;
582 goto done;
583 }
584
585
586 /* Is bus_map_fault signature correct (version 8 and higher)? */
587 if (ops->devo_bus_ops != NULL &&
588 ops->devo_bus_ops->bus_map_fault != NULL &&
589 ops->devo_bus_ops->bus_map_fault != i_ddi_map_fault &&
590 ops->devo_bus_ops->busops_rev < BUSO_REV_8) {
591
592 cmn_err(CE_WARN,
593 "mod_installdrv: busops' revision of '%s' is too low"
594 " (must be at least 8)", modname);
595 err = ENXIO;
596 goto done;
597 }
598
599
600 /* Make sure the driver is uninstalled */
601 dnp = &devnamesp[major];
602 LOCK_DEV_OPS(&dnp->dn_lock);
603 dp = devopsp[major];
604
605 if (dnp->dn_flags & (DN_DRIVER_REMOVED|DN_DRIVER_INACTIVE)) {
606 #ifdef DEBUG
607 cmn_err(CE_CONT,
608 "mod_installdrv: driver %s not installed", modname);
609 #endif
610 err = ENXIO;
611 goto unlock;
612 }
613
614 if (dp != &nodev_ops && dp != &mod_nodev_ops) {
615 cmn_err(CE_WARN,
616 "mod_installdrv: driver already installed %s", modname);
617 err = EALREADY;
618 goto unlock;
619 }
620
621 devopsp[major] = ops; /* setup devopsp */
622
623 if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */
624 flag = CBFLAG(major);
625 if ((err = devflg_to_qflag(str, flag, &qflag, &sqtype)) != 0)
626 goto unlock;
627 cdp = &devimpl[major];
628 ASSERT(cdp->d_str == NULL);
629 cdp->d_str = str;
630 cdp->d_qflag = qflag | QISDRV;
631 cdp->d_sqtype = sqtype;
632 }
633
634 if (ops->devo_bus_ops == NULL)
635 dnp->dn_flags |= DN_LEAF_DRIVER;
636
637 unlock:
638 UNLOCK_DEV_OPS(&dnp->dn_lock);
639 done:
640 return (err);
641 }
642
643 static int
mod_removedrv(struct modldrv * modl,struct modlinkage * modlp)644 mod_removedrv(struct modldrv *modl, struct modlinkage *modlp)
645 {
646 struct modctl *mcp;
647 struct dev_ops *ops;
648 struct devnames *dnp;
649 struct dev_ops *dp;
650 major_t major;
651 char *modname;
652 extern kthread_id_t mod_aul_thread;
653 struct streamtab *str;
654 cdevsw_impl_t *cdp;
655 int err = 0;
656
657 /* Don't auto unload modules on if moddebug flag is set */
658 if ((moddebug & MODDEBUG_NOAUL_DRV) && (mod_aul_thread == curthread)) {
659 err = EBUSY;
660 goto done;
661 }
662
663 /* Verify modname has a driver major */
664 mcp = mod_getctl(modlp);
665 ASSERT(mcp != NULL);
666 modname = mcp->mod_modname;
667
668 if ((major = ddi_name_to_major(modname)) == -1) {
669 cmn_err(CE_WARN, uninstall_err, modname);
670 err = EINVAL;
671 goto done;
672 }
673
674 ops = modl->drv_dev_ops;
675 dnp = &(devnamesp[major]);
676 LOCK_DEV_OPS(&(dnp->dn_lock));
677
678 dp = devopsp[major];
679
680 if (dp != ops) {
681 cmn_err(CE_NOTE, "mod_removedrv: mismatched driver for %s",
682 modname);
683 err = EBUSY;
684 goto unlock;
685 }
686
687 /*
688 * A driver is not unloadable if its dev_ops are held
689 */
690 if (!DRV_UNLOADABLE(dp)) {
691 mod_dprintf(DRV_DBG, "Cannot unload device driver <%s>,"
692 " refcnt %d\n", modname, dp->devo_refcnt);
693 err = EBUSY;
694 goto unlock;
695 }
696
697 /*
698 * OK to unload.
699 */
700 if ((str = STREAMSTAB(major)) != NULL) { /* streams driver */
701 cdp = &devimpl[major];
702 ASSERT(cdp->d_str == str);
703 cdp->d_str = NULL;
704
705 /* check for reference to per-dev syncq */
706 if (cdp->d_dmp != NULL) {
707 rele_dm(cdp->d_dmp);
708 cdp->d_dmp = NULL;
709 }
710 }
711
712 devopsp[major] = &mod_nodev_ops;
713 dnp->dn_flags &= ~(DN_DRIVER_HELD|DN_NO_AUTODETACH);
714
715 unlock:
716 UNLOCK_DEV_OPS(&(dnp->dn_lock));
717 done:
718 return (err);
719 }
720
721 /*
722 * System call subroutines
723 */
724
725 /*
726 * Compute system call number for given sysent and sysent table
727 */
728 static int
mod_infosysnum(struct modlinkage * modlp,struct sysent table[])729 mod_infosysnum(struct modlinkage *modlp, struct sysent table[])
730 {
731 struct sysent *sysp;
732
733 if ((sysp = mod_getsysent(modlp, table)) == NULL)
734 return (-1);
735 return ((int)(sysp - table));
736 }
737
738 /*
739 * Put a loadable system call entry into a sysent table.
740 */
741 static int
mod_installsys_sysent(struct modlsys * modl,struct modlinkage * modlp,struct sysent table[])742 mod_installsys_sysent(
743 struct modlsys *modl,
744 struct modlinkage *modlp,
745 struct sysent table[])
746 {
747 struct sysent *sysp;
748 struct sysent *mp;
749
750 #ifdef DEBUG
751 /*
752 * Before we even play with the sysent table, sanity check the
753 * incoming flags to make sure the entry is valid
754 */
755 switch (modl->sys_sysent->sy_flags & SE_RVAL_MASK) {
756 case SE_32RVAL1:
757 /* only r_val1 returned */
758 case SE_32RVAL1 | SE_32RVAL2:
759 /* r_val1 and r_val2 returned */
760 case SE_64RVAL:
761 /* 64-bit rval returned */
762 break;
763 default:
764 cmn_err(CE_WARN, "loadable syscall: %p: bad rval flags %x",
765 (void *)modl, modl->sys_sysent->sy_flags);
766 return (ENOSYS);
767 }
768 #endif
769 if ((sysp = mod_getsysent(modlp, table)) == NULL)
770 return (ENOSPC);
771
772 /*
773 * We should only block here until the reader in syscall gives
774 * up the lock. Multiple writers are prevented in the mod layer.
775 */
776 rw_enter(sysp->sy_lock, RW_WRITER);
777 mp = modl->sys_sysent;
778 sysp->sy_narg = mp->sy_narg;
779 sysp->sy_call = mp->sy_call;
780
781 /*
782 * clear the old call method flag, and get the new one from the module.
783 */
784 sysp->sy_flags &= ~SE_ARGC;
785 sysp->sy_flags |= SE_LOADED |
786 (mp->sy_flags & (SE_ARGC | SE_NOUNLOAD | SE_RVAL_MASK));
787
788 /*
789 * If the syscall doesn't need or want unloading, it can avoid
790 * the locking overhead on each entry. Convert the sysent to a
791 * normal non-loadable entry in that case.
792 */
793 if (mp->sy_flags & SE_NOUNLOAD) {
794 if (mp->sy_flags & SE_ARGC) {
795 sysp->sy_callc = (int64_t (*)())(uintptr_t)mp->sy_call;
796 } else {
797 sysp->sy_callc = syscall_ap;
798 }
799 sysp->sy_flags &= ~SE_LOADABLE;
800 }
801 rw_exit(sysp->sy_lock);
802 return (0);
803 }
804
805 /*
806 * Remove a loadable system call entry from a sysent table.
807 */
808 static int
mod_removesys_sysent(struct modlsys * modl,struct modlinkage * modlp,struct sysent table[])809 mod_removesys_sysent(
810 struct modlsys *modl,
811 struct modlinkage *modlp,
812 struct sysent table[])
813 {
814 struct sysent *sysp;
815
816 if ((sysp = mod_getsysent(modlp, table)) == NULL ||
817 (sysp->sy_flags & (SE_LOADABLE | SE_NOUNLOAD)) == 0 ||
818 sysp->sy_call != modl->sys_sysent->sy_call) {
819
820 struct modctl *mcp = mod_getctl(modlp);
821 char *modname = mcp->mod_modname;
822
823 cmn_err(CE_WARN, uninstall_err, modname);
824 return (EINVAL);
825 }
826
827 /* If we can't get the write lock, we can't unlink from the system */
828
829 if (!(moddebug & MODDEBUG_NOAUL_SYS) &&
830 rw_tryenter(sysp->sy_lock, RW_WRITER)) {
831 /*
832 * Check the flags to be sure the syscall is still
833 * (un)loadable.
834 * If SE_NOUNLOAD is set, SE_LOADABLE will not be.
835 */
836 if ((sysp->sy_flags & (SE_LOADED | SE_LOADABLE)) ==
837 (SE_LOADED | SE_LOADABLE)) {
838 sysp->sy_flags &= ~SE_LOADED;
839 sysp->sy_callc = loadable_syscall;
840 sysp->sy_call = nosys32;
841 rw_exit(sysp->sy_lock);
842 return (0);
843 }
844 rw_exit(sysp->sy_lock);
845 }
846 return (EBUSY);
847 }
848
849 /*
850 * System call status info
851 */
852 /*ARGSUSED*/
853 static int
mod_infosys(struct modlsys * modl,struct modlinkage * modlp,int * p0)854 mod_infosys(struct modlsys *modl, struct modlinkage *modlp, int *p0)
855 {
856 *p0 = mod_infosysnum(modlp, sysent);
857 return (0);
858 }
859
860 /*
861 * Link a system call into the system by setting the proper sysent entry.
862 * Called from the module's _init routine.
863 */
864 static int
mod_installsys(struct modlsys * modl,struct modlinkage * modlp)865 mod_installsys(struct modlsys *modl, struct modlinkage *modlp)
866 {
867 return (mod_installsys_sysent(modl, modlp, sysent));
868 }
869
870 /*
871 * Unlink a system call from the system.
872 * Called from a modules _fini routine.
873 */
874 static int
mod_removesys(struct modlsys * modl,struct modlinkage * modlp)875 mod_removesys(struct modlsys *modl, struct modlinkage *modlp)
876 {
877 return (mod_removesys_sysent(modl, modlp, sysent));
878 }
879
880 #ifdef _SYSCALL32_IMPL
881
882 /*
883 * 32-bit system call status info
884 */
885 /*ARGSUSED*/
886 static int
mod_infosys32(struct modlsys * modl,struct modlinkage * modlp,int * p0)887 mod_infosys32(struct modlsys *modl, struct modlinkage *modlp, int *p0)
888 {
889 *p0 = mod_infosysnum(modlp, sysent32);
890 return (0);
891 }
892
893 /*
894 * Link the 32-bit syscall into the system by setting the proper sysent entry.
895 * Also called from the module's _init routine.
896 */
897 static int
mod_installsys32(struct modlsys * modl,struct modlinkage * modlp)898 mod_installsys32(struct modlsys *modl, struct modlinkage *modlp)
899 {
900 return (mod_installsys_sysent(modl, modlp, sysent32));
901 }
902
903 /*
904 * Unlink the 32-bit flavor of a system call from the system.
905 * Also called from a module's _fini routine.
906 */
907 static int
mod_removesys32(struct modlsys * modl,struct modlinkage * modlp)908 mod_removesys32(struct modlsys *modl, struct modlinkage *modlp)
909 {
910 return (mod_removesys_sysent(modl, modlp, sysent32));
911 }
912
913 #endif /* _SYSCALL32_IMPL */
914
915 /*
916 * Filesystem status info
917 */
918 /*ARGSUSED*/
919 static int
mod_infofs(struct modlfs * modl,struct modlinkage * modlp,int * p0)920 mod_infofs(struct modlfs *modl, struct modlinkage *modlp, int *p0)
921 {
922 struct vfssw *vswp;
923
924 RLOCK_VFSSW();
925 if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL)
926 *p0 = -1;
927 else {
928 *p0 = vswp - vfssw;
929 vfs_unrefvfssw(vswp);
930 }
931 RUNLOCK_VFSSW();
932 return (0);
933 }
934
935 /*
936 * Install a filesystem.
937 */
938 /*ARGSUSED1*/
939 static int
mod_installfs(struct modlfs * modl,struct modlinkage * modlp)940 mod_installfs(struct modlfs *modl, struct modlinkage *modlp)
941 {
942 struct vfssw *vswp;
943 struct modctl *mcp;
944 char *fsname;
945 char ksname[KSTAT_STRLEN + 1];
946 int fstype; /* index into vfssw[] and vsanchor_fstype[] */
947 int allocated;
948 int err;
949 int vsw_stats_enabled;
950 /* Not for public consumption so these aren't in a header file */
951 extern int vopstats_enabled;
952 extern vopstats_t **vopstats_fstype;
953 extern kstat_t *new_vskstat(char *, vopstats_t *);
954 extern void initialize_vopstats(vopstats_t *);
955
956 if (modl->fs_vfsdef->def_version == VFSDEF_VERSION) {
957 /* Version matched */
958 fsname = modl->fs_vfsdef->name;
959 } else {
960 if ((modl->fs_vfsdef->def_version > 0) &&
961 (modl->fs_vfsdef->def_version < VFSDEF_VERSION)) {
962 /* Older VFSDEF_VERSION */
963 fsname = modl->fs_vfsdef->name;
964 } else if ((mcp = mod_getctl(modlp)) != NULL) {
965 /* Pre-VFSDEF_VERSION */
966 fsname = mcp->mod_modname;
967 } else {
968 /* If all else fails... */
969 fsname = "<unknown file system type>";
970 }
971
972 cmn_err(CE_WARN, "file system '%s' version mismatch", fsname);
973 return (ENXIO);
974 }
975
976 allocated = 0;
977
978 WLOCK_VFSSW();
979 if ((vswp = vfs_getvfsswbyname(fsname)) == NULL) {
980 if ((vswp = allocate_vfssw(fsname)) == NULL) {
981 WUNLOCK_VFSSW();
982 /*
983 * See 1095689. If this message appears, then
984 * we either need to make the vfssw table bigger
985 * statically, or make it grow dynamically.
986 */
987 cmn_err(CE_WARN, "no room for '%s' in vfssw!", fsname);
988 return (ENXIO);
989 }
990 allocated = 1;
991 }
992 ASSERT(vswp != NULL);
993
994 fstype = vswp - vfssw; /* Pointer arithmetic to get the fstype */
995
996 /* Turn on everything by default *except* VSW_STATS */
997 vswp->vsw_flag = modl->fs_vfsdef->flags & ~(VSW_STATS);
998
999 if (modl->fs_vfsdef->flags & VSW_HASPROTO) {
1000 vfs_mergeopttbl(&vfs_mntopts, modl->fs_vfsdef->optproto,
1001 &vswp->vsw_optproto);
1002 } else {
1003 vfs_copyopttbl(&vfs_mntopts, &vswp->vsw_optproto);
1004 }
1005
1006 if (modl->fs_vfsdef->flags & VSW_CANRWRO) {
1007 /*
1008 * This obviously implies VSW_CANREMOUNT.
1009 */
1010 vswp->vsw_flag |= VSW_CANREMOUNT;
1011 }
1012
1013 /*
1014 * If stats are enabled system wide and for this fstype, then
1015 * set the VSW_STATS flag in the proper vfssw[] table entry.
1016 */
1017 if (vopstats_enabled && modl->fs_vfsdef->flags & VSW_STATS) {
1018 vswp->vsw_flag |= VSW_STATS;
1019 }
1020
1021 if (modl->fs_vfsdef->init == NULL)
1022 err = EFAULT;
1023 else
1024 err = (*(modl->fs_vfsdef->init))(fstype, fsname);
1025
1026 if (err != 0) {
1027 if (allocated) {
1028 kmem_free(vswp->vsw_name, strlen(vswp->vsw_name)+1);
1029 vswp->vsw_name = "";
1030 }
1031 vswp->vsw_flag = 0;
1032 vswp->vsw_init = NULL;
1033 }
1034
1035 /* We don't want to hold the vfssw[] write lock over a kmem_alloc() */
1036 vsw_stats_enabled = vswp->vsw_flag & VSW_STATS;
1037
1038 vfs_unrefvfssw(vswp);
1039 WUNLOCK_VFSSW();
1040
1041 /* If everything is on, set up the per-fstype vopstats */
1042 if (vsw_stats_enabled && vopstats_enabled &&
1043 vopstats_fstype && vopstats_fstype[fstype] == NULL) {
1044 (void) strlcpy(ksname, VOPSTATS_STR, sizeof (ksname));
1045 (void) strlcat(ksname, vfssw[fstype].vsw_name, sizeof (ksname));
1046 vopstats_fstype[fstype] =
1047 kmem_alloc(sizeof (vopstats_t), KM_SLEEP);
1048 initialize_vopstats(vopstats_fstype[fstype]);
1049 (void) new_vskstat(ksname, vopstats_fstype[fstype]);
1050 }
1051 return (err);
1052 }
1053
1054 /*
1055 * Remove a filesystem
1056 */
1057 static int
mod_removefs(struct modlfs * modl,struct modlinkage * modlp)1058 mod_removefs(struct modlfs *modl, struct modlinkage *modlp)
1059 {
1060 struct vfssw *vswp;
1061 struct modctl *mcp;
1062 char *modname;
1063
1064 if (moddebug & MODDEBUG_NOAUL_FS)
1065 return (EBUSY);
1066
1067 WLOCK_VFSSW();
1068 if ((vswp = vfs_getvfsswbyname(modl->fs_vfsdef->name)) == NULL) {
1069 mcp = mod_getctl(modlp);
1070 ASSERT(mcp != NULL);
1071 modname = mcp->mod_modname;
1072 WUNLOCK_VFSSW();
1073 cmn_err(CE_WARN, uninstall_err, modname);
1074 return (EINVAL);
1075 }
1076 if (vswp->vsw_count != 1) {
1077 vfs_unrefvfssw(vswp);
1078 WUNLOCK_VFSSW();
1079 return (EBUSY);
1080 }
1081
1082 /*
1083 * A mounted filesystem could still have vsw_count = 0
1084 * so we must check whether anyone is actually using our ops
1085 */
1086 if (vfs_opsinuse(&vswp->vsw_vfsops)) {
1087 vfs_unrefvfssw(vswp);
1088 WUNLOCK_VFSSW();
1089 return (EBUSY);
1090 }
1091
1092 vfs_freeopttbl(&vswp->vsw_optproto);
1093 vswp->vsw_optproto.mo_count = 0;
1094
1095 vswp->vsw_flag = 0;
1096 vswp->vsw_init = NULL;
1097 vfs_unrefvfssw(vswp);
1098 WUNLOCK_VFSSW();
1099 return (0);
1100 }
1101
1102 /*
1103 * Get status of a streams module.
1104 */
1105 /*ARGSUSED*/
1106 static int
mod_infostrmod(struct modlstrmod * modl,struct modlinkage * modlp,int * p0)1107 mod_infostrmod(struct modlstrmod *modl, struct modlinkage *modlp, int *p0)
1108 {
1109 *p0 = -1; /* no useful info */
1110 return (0);
1111 }
1112
1113
1114 /*
1115 * Install a streams module.
1116 */
1117 /*ARGSUSED*/
1118 static int
mod_installstrmod(struct modlstrmod * modl,struct modlinkage * modlp)1119 mod_installstrmod(struct modlstrmod *modl, struct modlinkage *modlp)
1120 {
1121 struct fmodsw *fp = modl->strmod_fmodsw;
1122
1123 if (!(fp->f_flag & D_MP)) {
1124 cmn_err(CE_WARN, "mod_install: MT-unsafe strmod '%s' rejected",
1125 fp->f_name);
1126 return (ENXIO);
1127 }
1128
1129 return (fmodsw_register(fp->f_name, fp->f_str, fp->f_flag));
1130 }
1131
1132 /*
1133 * Remove a streams module.
1134 */
1135 /*ARGSUSED*/
1136 static int
mod_removestrmod(struct modlstrmod * modl,struct modlinkage * modlp)1137 mod_removestrmod(struct modlstrmod *modl, struct modlinkage *modlp)
1138 {
1139 if (moddebug & MODDEBUG_NOAUL_STR)
1140 return (EBUSY);
1141
1142 return (fmodsw_unregister(modl->strmod_fmodsw->f_name));
1143 }
1144
1145 /*
1146 * Get status of a socket module.
1147 */
1148 /*ARGSUSED*/
1149 static int
mod_infosockmod(struct modlsockmod * modl,struct modlinkage * modlp,int * p0)1150 mod_infosockmod(struct modlsockmod *modl, struct modlinkage *modlp, int *p0)
1151 {
1152 *p0 = -1; /* no useful info */
1153 return (0);
1154 }
1155
1156 /*
1157 * Install a socket module.
1158 */
1159 /*ARGSUSED*/
1160 static int
mod_installsockmod(struct modlsockmod * modl,struct modlinkage * modlp)1161 mod_installsockmod(struct modlsockmod *modl, struct modlinkage *modlp)
1162 {
1163 struct modctl *mcp;
1164 char *mod_name;
1165
1166 mcp = mod_getctl(modlp);
1167 ASSERT(mcp != NULL);
1168 mod_name = mcp->mod_modname;
1169 if (strcmp(mod_name, modl->sockmod_reg_info->smod_name) != 0) {
1170 #ifdef DEBUG
1171 cmn_err(CE_CONT, "mod_installsockmod: different names"
1172 " %s != %s \n", mod_name,
1173 modl->sockmod_reg_info->smod_name);
1174 #endif
1175 return (EINVAL);
1176 }
1177
1178 /*
1179 * Register module.
1180 */
1181 return (smod_register(modl->sockmod_reg_info));
1182 }
1183
1184 /*
1185 * Remove a socket module.
1186 */
1187 /*ARGSUSED*/
1188 static int
mod_removesockmod(struct modlsockmod * modl,struct modlinkage * modlp)1189 mod_removesockmod(struct modlsockmod *modl, struct modlinkage *modlp)
1190 {
1191 /*
1192 * unregister from the global socket creation table
1193 * check the refcnt in the lookup table
1194 */
1195 return (smod_unregister(modl->sockmod_reg_info->smod_name));
1196 }
1197
1198 /*
1199 * Get status of a scheduling class module.
1200 */
1201 /*ARGSUSED1*/
1202 static int
mod_infosched(struct modlsched * modl,struct modlinkage * modlp,int * p0)1203 mod_infosched(struct modlsched *modl, struct modlinkage *modlp, int *p0)
1204 {
1205 int status;
1206 auto id_t cid;
1207
1208 status = getcidbyname(modl->sched_class->cl_name, &cid);
1209
1210 if (status != 0)
1211 *p0 = -1;
1212 else
1213 *p0 = cid;
1214
1215 return (0);
1216 }
1217
1218 /*
1219 * Install a scheduling class module.
1220 */
1221 /*ARGSUSED1*/
1222 static int
mod_installsched(struct modlsched * modl,struct modlinkage * modlp)1223 mod_installsched(struct modlsched *modl, struct modlinkage *modlp)
1224 {
1225 sclass_t *clp;
1226 int status;
1227 id_t cid;
1228
1229 /*
1230 * See if module is already installed.
1231 */
1232 mutex_enter(&class_lock);
1233 status = alloc_cid(modl->sched_class->cl_name, &cid);
1234 mutex_exit(&class_lock);
1235 ASSERT(status == 0);
1236 clp = &sclass[cid];
1237 rw_enter(clp->cl_lock, RW_WRITER);
1238 if (SCHED_INSTALLED(clp)) {
1239 printf("scheduling class %s is already installed\n",
1240 modl->sched_class->cl_name);
1241 rw_exit(clp->cl_lock);
1242 return (EBUSY); /* it's already there */
1243 }
1244
1245 clp->cl_init = modl->sched_class->cl_init;
1246 clp->cl_funcs = modl->sched_class->cl_funcs;
1247 modl->sched_class = clp;
1248 disp_add(clp);
1249 loaded_classes++; /* for priocntl system call */
1250 rw_exit(clp->cl_lock);
1251 return (0);
1252 }
1253
1254 /*
1255 * Remove a scheduling class module.
1256 *
1257 * we only null out the init func and the class functions because
1258 * once a class has been loaded it has that slot in the class
1259 * array until the next reboot. We don't decrement loaded_classes
1260 * because this keeps count of the number of classes that have
1261 * been loaded for this session. It will have to be this way until
1262 * we implement the class array as a linked list and do true
1263 * dynamic allocation.
1264 */
1265 static int
mod_removesched(struct modlsched * modl,struct modlinkage * modlp)1266 mod_removesched(struct modlsched *modl, struct modlinkage *modlp)
1267 {
1268 int status;
1269 sclass_t *clp;
1270 struct modctl *mcp;
1271 char *modname;
1272 id_t cid;
1273
1274 status = getcidbyname(modl->sched_class->cl_name, &cid);
1275 if (status != 0) {
1276 mcp = mod_getctl(modlp);
1277 ASSERT(mcp != NULL);
1278 modname = mcp->mod_modname;
1279 cmn_err(CE_WARN, uninstall_err, modname);
1280 return (EINVAL);
1281 }
1282 clp = &sclass[cid];
1283 if (moddebug & MODDEBUG_NOAUL_SCHED ||
1284 !rw_tryenter(clp->cl_lock, RW_WRITER))
1285 return (EBUSY);
1286
1287 clp->cl_init = NULL;
1288 clp->cl_funcs = NULL;
1289 rw_exit(clp->cl_lock);
1290 return (0);
1291 }
1292
1293 /*
1294 * Get status of an exec module.
1295 */
1296 /*ARGSUSED1*/
1297 static int
mod_infoexec(struct modlexec * modl,struct modlinkage * modlp,int * p0)1298 mod_infoexec(struct modlexec *modl, struct modlinkage *modlp, int *p0)
1299 {
1300 struct execsw *eswp;
1301
1302 if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL)
1303 *p0 = -1;
1304 else
1305 *p0 = eswp - execsw;
1306
1307 return (0);
1308 }
1309
1310 /*
1311 * Install an exec module.
1312 */
1313 static int
mod_installexec(struct modlexec * modl,struct modlinkage * modlp)1314 mod_installexec(struct modlexec *modl, struct modlinkage *modlp)
1315 {
1316 struct execsw *eswp;
1317 struct modctl *mcp;
1318 char *modname;
1319 char *magic;
1320 size_t magic_size;
1321
1322 /*
1323 * See if execsw entry is already allocated. Can't use findexectype()
1324 * because we may get a recursive call to here.
1325 */
1326
1327 if ((eswp = findexecsw(modl->exec_execsw->exec_magic)) == NULL) {
1328 mcp = mod_getctl(modlp);
1329 ASSERT(mcp != NULL);
1330 modname = mcp->mod_modname;
1331 magic = modl->exec_execsw->exec_magic;
1332 magic_size = modl->exec_execsw->exec_maglen;
1333 if ((eswp = allocate_execsw(modname, magic, magic_size)) ==
1334 NULL) {
1335 printf("no unused entries in 'execsw'\n");
1336 return (ENOSPC);
1337 }
1338 }
1339 if (eswp->exec_func != NULL) {
1340 printf("exec type %x is already installed\n",
1341 *eswp->exec_magic);
1342 return (EBUSY); /* it's already there! */
1343 }
1344
1345 rw_enter(eswp->exec_lock, RW_WRITER);
1346 eswp->exec_func = modl->exec_execsw->exec_func;
1347 eswp->exec_core = modl->exec_execsw->exec_core;
1348 rw_exit(eswp->exec_lock);
1349
1350 return (0);
1351 }
1352
1353 /*
1354 * Remove an exec module.
1355 */
1356 static int
mod_removeexec(struct modlexec * modl,struct modlinkage * modlp)1357 mod_removeexec(struct modlexec *modl, struct modlinkage *modlp)
1358 {
1359 struct execsw *eswp;
1360 struct modctl *mcp;
1361 char *modname;
1362
1363 eswp = findexecsw(modl->exec_execsw->exec_magic);
1364 if (eswp == NULL) {
1365 mcp = mod_getctl(modlp);
1366 ASSERT(mcp != NULL);
1367 modname = mcp->mod_modname;
1368 cmn_err(CE_WARN, uninstall_err, modname);
1369 return (EINVAL);
1370 }
1371 if (moddebug & MODDEBUG_NOAUL_EXEC ||
1372 !rw_tryenter(eswp->exec_lock, RW_WRITER))
1373 return (EBUSY);
1374 eswp->exec_func = NULL;
1375 eswp->exec_core = NULL;
1376 rw_exit(eswp->exec_lock);
1377 return (0);
1378 }
1379
1380 /*
1381 * Find a free sysent entry or check if the specified one is free.
1382 */
1383 static struct sysent *
mod_getsysent(struct modlinkage * modlp,struct sysent * se)1384 mod_getsysent(struct modlinkage *modlp, struct sysent *se)
1385 {
1386 int sysnum;
1387 struct modctl *mcp;
1388 char *mod_name;
1389
1390 if ((mcp = mod_getctl(modlp)) == NULL) {
1391 /*
1392 * This happens when we're looking up the module
1393 * pointer as part of a stub installation. So
1394 * there's no need to whine at this point.
1395 */
1396 return (NULL);
1397 }
1398
1399 mod_name = mcp->mod_modname;
1400
1401 if ((sysnum = mod_getsysnum(mod_name)) == -1) {
1402 cmn_err(CE_WARN, "system call missing from bind file");
1403 return (NULL);
1404 }
1405
1406 if (sysnum > 0 && sysnum < NSYSCALL &&
1407 (se[sysnum].sy_flags & (SE_LOADABLE | SE_NOUNLOAD)))
1408 return (se + sysnum);
1409
1410 cmn_err(CE_WARN, "system call entry %d is already in use", sysnum);
1411 return (NULL);
1412 }
1413
1414 /*
1415 * IP Policy Modules.
1416 */
1417 /*ARGSUSED*/
1418 static int
mod_infoipp(struct modlipp * modl,struct modlinkage * modlp,int * p0)1419 mod_infoipp(struct modlipp *modl, struct modlinkage *modlp, int *p0)
1420 {
1421 struct modctl *mcp = mod_getctl(modlp);
1422 ipp_mod_id_t mid;
1423
1424 if (mcp == NULL) {
1425 *p0 = -1;
1426 return (0); /* module is not yet installed */
1427 }
1428
1429 mid = ipp_mod_lookup(mcp->mod_modname);
1430
1431 *p0 = mid;
1432 return (0);
1433 }
1434
1435 static int
mod_installipp(struct modlipp * modl,struct modlinkage * modlp)1436 mod_installipp(struct modlipp *modl, struct modlinkage *modlp)
1437 {
1438 struct modctl *mcp = mod_getctl(modlp);
1439
1440 ASSERT(mcp != NULL);
1441 return (ipp_mod_register(mcp->mod_modname, modl->ipp_ops));
1442 }
1443
1444 /*ARGSUSED*/
1445 static int
mod_removeipp(struct modlipp * modl,struct modlinkage * modlp)1446 mod_removeipp(struct modlipp *modl, struct modlinkage *modlp)
1447 {
1448 struct modctl *mcp = mod_getctl(modlp);
1449 extern kthread_id_t mod_aul_thread;
1450 ipp_mod_id_t mid;
1451
1452 ASSERT(mcp != NULL);
1453
1454 if ((moddebug & MODDEBUG_NOAUL_IPP) && (mod_aul_thread == curthread))
1455 return (EBUSY);
1456
1457 mid = ipp_mod_lookup(mcp->mod_modname);
1458 ASSERT(mid != IPP_MOD_INVAL);
1459
1460 return (ipp_mod_unregister(mid));
1461 }
1462
1463 /*
1464 * Manage kiconv modules.
1465 */
1466 /*ARGSUSED*/
1467 static int
mod_installkiconv(struct modlkiconv * modl,struct modlinkage * modlp)1468 mod_installkiconv(struct modlkiconv *modl, struct modlinkage *modlp)
1469 {
1470 return (kiconv_register_module(modl->kiconv_moddef));
1471 }
1472
1473 /*ARGSUSED*/
1474 static int
mod_removekiconv(struct modlkiconv * modl,struct modlinkage * modlp)1475 mod_removekiconv(struct modlkiconv *modl, struct modlinkage *modlp)
1476 {
1477 return (kiconv_unregister_module(modl->kiconv_moddef));
1478 }
1479