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