1 /* $NetBSD: kern_subr.c,v 1.202 2009/11/04 16:54:00 pooka Exp $ */
4 * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, and by Luke Mewburn.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1982, 1986, 1991, 1993
35 * The Regents of the University of California. All rights reserved.
36 * (c) UNIX System Laboratories, Inc.
37 * All or some portions of this file are derived from material licensed
38 * to the University of California by American Telephone and Telegraph
39 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
40 * the permission of UNIX System Laboratories, Inc.
42 * Copyright (c) 1992, 1993
43 * The Regents of the University of California. All rights reserved.
45 * This software was developed by the Computer Systems Engineering group
46 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
47 * contributed to Berkeley.
49 * All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Lawrence Berkeley Laboratory.
54 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions
57 * 1. Redistributions of source code must retain the above copyright
58 * notice, this list of conditions and the following disclaimer.
59 * 2. Redistributions in binary form must reproduce the above copyright
60 * notice, this list of conditions and the following disclaimer in the
61 * documentation and/or other materials provided with the distribution.
62 * 3. Neither the name of the University nor the names of its contributors
63 * may be used to endorse or promote products derived from this software
64 * without specific prior written permission.
66 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
69 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
70 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
74 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
78 * @(#)kern_subr.c 8.4 (Berkeley) 2/14/95
81 #include <sys/cdefs.h>
82 __KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.202 2009/11/04 16:54:00 pooka Exp $");
86 #include "opt_syscall_debug.h"
87 #include "opt_ktrace.h"
88 #include "opt_ptrace.h"
89 #include "opt_powerhook.h"
90 #include "opt_tftproot.h"
92 #include <sys/param.h>
93 #include <sys/systm.h>
95 #include <sys/malloc.h>
96 #include <sys/mount.h>
97 #include <sys/device.h>
98 #include <sys/reboot.h>
100 #include <sys/disk.h>
101 #include <sys/disklabel.h>
102 #include <sys/queue.h>
103 #include <sys/ktrace.h>
104 #include <sys/ptrace.h>
105 #include <sys/fcntl.h>
106 #include <sys/kauth.h>
107 #include <sys/vnode.h>
108 #include <sys/syscallvar.h>
109 #include <sys/xcall.h>
110 #include <sys/module.h>
112 #include <uvm/uvm_extern.h>
114 #include <dev/cons.h>
118 /* XXX these should eventually move to subr_autoconf.c */
119 static device_t
finddevice(const char *);
120 static device_t
getdisk(char *, int, int, dev_t
*, int);
121 static device_t
parsedisk(char *, int, int, dev_t
*);
122 static const char *getwedgename(const char *, int);
125 * A generic linear hook.
128 LIST_ENTRY(hook_desc
) hk_list
;
129 void (*hk_fn
)(void *);
132 typedef LIST_HEAD(, hook_desc
) hook_list_t
;
135 int tftproot_dhcpboot(device_t
);
138 dev_t dumpcdev
; /* for savecore */
141 hook_establish(hook_list_t
*list
, void (*fn
)(void *), void *arg
)
143 struct hook_desc
*hd
;
145 hd
= malloc(sizeof(*hd
), M_DEVBUF
, M_NOWAIT
);
151 LIST_INSERT_HEAD(list
, hd
, hk_list
);
157 hook_disestablish(hook_list_t
*list
, void *vhook
)
160 struct hook_desc
*hd
;
162 LIST_FOREACH(hd
, list
, hk_list
) {
168 panic("hook_disestablish: hook %p not established", vhook
);
170 LIST_REMOVE((struct hook_desc
*)vhook
, hk_list
);
171 free(vhook
, M_DEVBUF
);
175 hook_destroy(hook_list_t
*list
)
177 struct hook_desc
*hd
;
179 while ((hd
= LIST_FIRST(list
)) != NULL
) {
180 LIST_REMOVE(hd
, hk_list
);
186 hook_proc_run(hook_list_t
*list
, struct proc
*p
)
188 struct hook_desc
*hd
;
190 LIST_FOREACH(hd
, list
, hk_list
)
191 ((void (*)(struct proc
*, void *))*hd
->hk_fn
)(p
, hd
->hk_arg
);
195 * "Shutdown hook" types, functions, and variables.
197 * Should be invoked immediately before the
198 * system is halted or rebooted, i.e. after file systems unmounted,
199 * after crash dump done, etc.
201 * Each shutdown hook is removed from the list before it's run, so that
202 * it won't be run again.
205 static hook_list_t shutdownhook_list
;
208 shutdownhook_establish(void (*fn
)(void *), void *arg
)
210 return hook_establish(&shutdownhook_list
, fn
, arg
);
214 shutdownhook_disestablish(void *vhook
)
216 hook_disestablish(&shutdownhook_list
, vhook
);
220 * Run shutdown hooks. Should be invoked immediately before the
221 * system is halted or rebooted, i.e. after file systems unmounted,
222 * after crash dump done, etc.
224 * Each shutdown hook is removed from the list before it's run, so that
225 * it won't be run again.
228 doshutdownhooks(void)
230 struct hook_desc
*dp
;
232 while ((dp
= LIST_FIRST(&shutdownhook_list
)) != NULL
) {
233 LIST_REMOVE(dp
, hk_list
);
234 (*dp
->hk_fn
)(dp
->hk_arg
);
237 * Don't bother freeing the hook structure,, since we may
238 * be rebooting because of a memory corruption problem,
239 * and this might only make things worse. It doesn't
240 * matter, anyway, since the system is just about to
249 * "Mountroot hook" types, functions, and variables.
252 static hook_list_t mountroothook_list
;
255 mountroothook_establish(void (*fn
)(device_t
), device_t dev
)
257 return hook_establish(&mountroothook_list
, (void (*)(void *))fn
, dev
);
261 mountroothook_disestablish(void *vhook
)
263 hook_disestablish(&mountroothook_list
, vhook
);
267 mountroothook_destroy(void)
269 hook_destroy(&mountroothook_list
);
273 domountroothook(void)
275 struct hook_desc
*hd
;
277 LIST_FOREACH(hd
, &mountroothook_list
, hk_list
) {
278 if (hd
->hk_arg
== (void *)root_device
) {
279 (*hd
->hk_fn
)(hd
->hk_arg
);
285 static hook_list_t exechook_list
;
288 exechook_establish(void (*fn
)(struct proc
*, void *), void *arg
)
290 return hook_establish(&exechook_list
, (void (*)(void *))fn
, arg
);
294 exechook_disestablish(void *vhook
)
296 hook_disestablish(&exechook_list
, vhook
);
303 doexechooks(struct proc
*p
)
305 hook_proc_run(&exechook_list
, p
);
308 static hook_list_t exithook_list
;
309 extern krwlock_t exec_lock
;
312 exithook_establish(void (*fn
)(struct proc
*, void *), void *arg
)
316 rw_enter(&exec_lock
, RW_WRITER
);
317 rv
= hook_establish(&exithook_list
, (void (*)(void *))fn
, arg
);
323 exithook_disestablish(void *vhook
)
326 rw_enter(&exec_lock
, RW_WRITER
);
327 hook_disestablish(&exithook_list
, vhook
);
335 doexithooks(struct proc
*p
)
337 hook_proc_run(&exithook_list
, p
);
340 static hook_list_t forkhook_list
;
343 forkhook_establish(void (*fn
)(struct proc
*, struct proc
*))
345 return hook_establish(&forkhook_list
, (void (*)(void *))fn
, NULL
);
349 forkhook_disestablish(void *vhook
)
351 hook_disestablish(&forkhook_list
, vhook
);
358 doforkhooks(struct proc
*p2
, struct proc
*p1
)
360 struct hook_desc
*hd
;
362 LIST_FOREACH(hd
, &forkhook_list
, hk_list
) {
363 ((void (*)(struct proc
*, struct proc
*))*hd
->hk_fn
)
369 * "Power hook" types, functions, and variables.
370 * The list of power hooks is kept ordered with the last registered hook
372 * When running the hooks on power down the hooks are called in reverse
373 * registration order, when powering up in registration order.
375 struct powerhook_desc
{
376 CIRCLEQ_ENTRY(powerhook_desc
) sfd_list
;
377 void (*sfd_fn
)(int, void *);
382 static CIRCLEQ_HEAD(, powerhook_desc
) powerhook_list
=
383 CIRCLEQ_HEAD_INITIALIZER(powerhook_list
);
386 powerhook_establish(const char *name
, void (*fn
)(int, void *), void *arg
)
388 struct powerhook_desc
*ndp
;
390 ndp
= (struct powerhook_desc
*)
391 malloc(sizeof(*ndp
), M_DEVBUF
, M_NOWAIT
);
397 strlcpy(ndp
->sfd_name
, name
, sizeof(ndp
->sfd_name
));
398 CIRCLEQ_INSERT_HEAD(&powerhook_list
, ndp
, sfd_list
);
400 aprint_error("%s: WARNING: powerhook_establish is deprecated\n", name
);
405 powerhook_disestablish(void *vhook
)
408 struct powerhook_desc
*dp
;
410 CIRCLEQ_FOREACH(dp
, &powerhook_list
, sfd_list
)
413 panic("powerhook_disestablish: hook %p not established", vhook
);
417 CIRCLEQ_REMOVE(&powerhook_list
, (struct powerhook_desc
*)vhook
,
419 free(vhook
, M_DEVBUF
);
426 dopowerhooks(int why
)
428 struct powerhook_desc
*dp
;
430 #ifdef POWERHOOK_DEBUG
431 const char *why_name
;
432 static const char * pwr_names
[] = {PWR_NAMES
};
433 why_name
= why
< __arraycount(pwr_names
) ? pwr_names
[why
] : "???";
436 if (why
== PWR_RESUME
|| why
== PWR_SOFTRESUME
) {
437 CIRCLEQ_FOREACH_REVERSE(dp
, &powerhook_list
, sfd_list
) {
438 #ifdef POWERHOOK_DEBUG
439 printf("dopowerhooks %s: %s (%p)\n", why_name
, dp
->sfd_name
, dp
);
441 (*dp
->sfd_fn
)(why
, dp
->sfd_arg
);
444 CIRCLEQ_FOREACH(dp
, &powerhook_list
, sfd_list
) {
445 #ifdef POWERHOOK_DEBUG
446 printf("dopowerhooks %s: %s (%p)\n", why_name
, dp
->sfd_name
, dp
);
448 (*dp
->sfd_fn
)(why
, dp
->sfd_arg
);
452 #ifdef POWERHOOK_DEBUG
453 printf("dopowerhooks: %s done\n", why_name
);
460 struct dkwedge_info wi
;
464 if (device_class(dv
) != DV_DISK
|| !device_is_a(dv
, "dk"))
467 if ((vn
= opendisk(dv
)) == NULL
)
470 error
= VOP_IOCTL(vn
, DIOCGWEDGEINFO
, &wi
, FREAD
, NOCRED
);
471 VOP_CLOSE(vn
, FREAD
, NOCRED
);
475 printf("%s: Get wedge info returned %d\n", device_xname(dv
), error
);
479 return strcmp(wi
.dkw_ptype
, DKW_PTYPE_SWAP
) == 0;
483 * Determine the root device and, if instructed to, the root file system.
489 extern struct cfdriver md_cd
;
490 #ifdef MEMORY_DISK_IS_ROOT
498 * The device and wedge that we booted from. If booted_wedge is NULL,
499 * the we might consult booted_partition.
501 device_t booted_device
;
502 device_t booted_wedge
;
503 int booted_partition
;
506 * Use partition letters if it's a disk class but not a wedge.
507 * XXX Check for wedge is kinda gross.
509 #define DEV_USES_PARTITIONS(dv) \
510 (device_class((dv)) == DV_DISK && \
511 !device_is_a((dv), "dk"))
514 setroot(device_t bootdv
, int bootpartition
)
520 dev_t ndumpdev
= NODEV
;
522 const char *rootdevname
;
523 const char *dumpdevname
;
524 device_t rootdv
= NULL
; /* XXX gcc -Wuninitialized */
525 device_t dumpdv
= NULL
;
527 const char *deffsname
;
531 if (tftproot_dhcpboot(bootdv
) != 0)
532 boothowto
|= RB_ASKNAME
;
538 * XXX there should be "root on md0" in the config file,
539 * but it isn't always
541 bootdv
= md_cd
.cd_devs
[0];
547 * If NFS is specified as the file system, and we found
548 * a DV_DISK boot device (or no boot device at all), then
549 * find a reasonable network interface for "rootspec".
551 vops
= vfs_getopsbyname(MOUNT_NFS
);
552 if (vops
!= NULL
&& strcmp(rootfstype
, MOUNT_NFS
) == 0 &&
554 (bootdv
== NULL
|| device_class(bootdv
) != DV_IFNET
)) {
557 (IFF_LOOPBACK
|IFF_POINTOPOINT
)) == 0)
562 * Can't find a suitable interface; ask the
565 boothowto
|= RB_ASKNAME
;
568 * Have a suitable interface; behave as if
569 * the user specified this interface.
571 rootspec
= (const char *)ifp
->if_xname
;
578 * If wildcarded root and we the boot device wasn't determined,
581 if (rootspec
== NULL
&& bootdv
== NULL
)
582 boothowto
|= RB_ASKNAME
;
585 if (boothowto
& RB_ASKNAME
) {
589 printf("root device");
590 if (bootdv
!= NULL
) {
591 printf(" (default %s", device_xname(bootdv
));
592 if (DEV_USES_PARTITIONS(bootdv
))
593 printf("%c", bootpartition
+ 'a');
597 len
= cngetsn(buf
, sizeof(buf
));
598 if (len
== 0 && bootdv
!= NULL
) {
599 strlcpy(buf
, device_xname(bootdv
), sizeof(buf
));
602 if (len
> 0 && buf
[len
- 1] == '*') {
604 dv
= getdisk(buf
, len
, 1, &nrootdev
, 0);
610 dv
= getdisk(buf
, len
, bootpartition
, &nrootdev
, 0);
618 * Set up the default dump device. If root is on
619 * a network device, there is no default dump
620 * device, since we don't support dumps to the
623 if (DEV_USES_PARTITIONS(rootdv
) == 0)
629 printf("dump device");
630 if (defdumpdv
!= NULL
) {
632 * Note, we know it's a disk if we get here.
634 printf(" (default %sb)", device_xname(defdumpdv
));
637 len
= cngetsn(buf
, sizeof(buf
));
639 if (defdumpdv
!= NULL
) {
640 ndumpdev
= MAKEDISKDEV(major(nrootdev
),
641 DISKUNIT(nrootdev
), 1);
646 if (len
== 4 && strcmp(buf
, "none") == 0) {
650 dv
= getdisk(buf
, len
, 1, &ndumpdev
, 1);
660 for (vops
= LIST_FIRST(&vfs_list
); vops
!= NULL
;
661 vops
= LIST_NEXT(vops
, vfs_list
)) {
662 if (vops
->vfs_mountroot
!= NULL
&&
663 strcmp(rootfstype
, vops
->vfs_name
) == 0)
668 deffsname
= "generic";
670 deffsname
= vops
->vfs_name
;
673 printf("file system (default %s): ", deffsname
);
674 len
= cngetsn(buf
, sizeof(buf
));
676 if (strcmp(deffsname
, "generic") == 0)
677 rootfstype
= ROOT_FSTYPE_ANY
;
680 if (len
== 4 && strcmp(buf
, "halt") == 0)
681 cpu_reboot(RB_HALT
, NULL
);
682 else if (len
== 6 && strcmp(buf
, "reboot") == 0)
685 else if (len
== 3 && strcmp(buf
, "ddb") == 0) {
689 else if (len
== 7 && strcmp(buf
, "generic") == 0) {
690 rootfstype
= ROOT_FSTYPE_ANY
;
693 vops
= vfs_getopsbyname(buf
);
694 if (vops
== NULL
|| vops
->vfs_mountroot
== NULL
) {
695 printf("use one of: generic");
696 for (vops
= LIST_FIRST(&vfs_list
);
698 vops
= LIST_NEXT(vops
, vfs_list
)) {
699 if (vops
->vfs_mountroot
!= NULL
)
700 printf(" %s", vops
->vfs_name
);
707 printf(" halt reboot\n");
710 * XXX If *vops gets freed between here and
711 * the call to mountroot(), rootfstype will
712 * point to something unexpected. But in
713 * this case the system will fail anyway.
715 rootfstype
= vops
->vfs_name
;
721 } else if (rootspec
== NULL
) {
723 * Wildcarded root; use the boot device.
728 majdev
= devsw_name2blk(device_xname(bootdv
), NULL
, 0);
733 * Root is on a disk. `bootpartition' is root,
734 * unless the device does not use partitions.
736 if (DEV_USES_PARTITIONS(bootdv
))
737 rootdev
= MAKEDISKDEV(majdev
,
741 rootdev
= makedev(majdev
, device_unit(bootdv
));
746 * `root on <dev> ...'
750 * If it's a network interface, we can bail out
753 dv
= finddevice(rootspec
);
754 if (dv
!= NULL
&& device_class(dv
) == DV_IFNET
) {
759 if (rootdev
== NODEV
&&
760 device_class(dv
) == DV_DISK
&& device_is_a(dv
, "dk") &&
761 (majdev
= devsw_name2blk(device_xname(dv
), NULL
, 0)) >= 0)
762 rootdev
= makedev(majdev
, device_unit(dv
));
764 rootdevname
= devsw_blk2name(major(rootdev
));
765 if (rootdevname
== NULL
) {
766 printf("unknown device major 0x%llx\n",
767 (unsigned long long)rootdev
);
768 boothowto
|= RB_ASKNAME
;
771 memset(buf
, 0, sizeof(buf
));
772 snprintf(buf
, sizeof(buf
), "%s%llu", rootdevname
,
773 (unsigned long long)DISKUNIT(rootdev
));
775 rootdv
= finddevice(buf
);
776 if (rootdv
== NULL
) {
777 printf("device %s (0x%llx) not configured\n",
778 buf
, (unsigned long long)rootdev
);
779 boothowto
|= RB_ASKNAME
;
786 root_device
= rootdv
;
788 switch (device_class(rootdv
)) {
791 aprint_normal("root on %s", device_xname(rootdv
));
792 if (DEV_USES_PARTITIONS(rootdv
))
793 aprint_normal("%c", (int)DISKPART(rootdev
) + 'a');
797 printf("can't determine root device\n");
798 boothowto
|= RB_ASKNAME
;
803 * Now configure the dump device.
805 * If we haven't figured out the dump device, do so, with
806 * the following rules:
808 * (a) We already know dumpdv in the RB_ASKNAME case.
810 * (b) If dumpspec is set, try to use it. If the device
811 * is not available, punt.
813 * (c) If dumpspec is not set, the dump device is
814 * wildcarded or unspecified. If the root device
815 * is DV_IFNET, punt. Otherwise, use partition b
816 * of the root device.
819 if (boothowto
& RB_ASKNAME
) { /* (a) */
822 } else if (dumpspec
!= NULL
) { /* (b) */
823 if (strcmp(dumpspec
, "none") == 0 || dumpdev
== NODEV
) {
825 * Operator doesn't want a dump device.
826 * Or looks like they tried to pick a network
832 dumpdevname
= devsw_blk2name(major(dumpdev
));
833 if (dumpdevname
== NULL
)
835 memset(buf
, 0, sizeof(buf
));
836 snprintf(buf
, sizeof(buf
), "%s%llu", dumpdevname
,
837 (unsigned long long)DISKUNIT(dumpdev
));
839 dumpdv
= finddevice(buf
);
840 if (dumpdv
== NULL
) {
842 * Device not configured.
847 if (DEV_USES_PARTITIONS(rootdv
) == 0) {
848 for (dv
= deviter_first(&di
, DEVITER_F_ROOT_FIRST
);
850 dv
= deviter_next(&di
))
853 deviter_release(&di
);
857 majdev
= devsw_name2blk(device_xname(dv
), NULL
, 0);
861 dumpdev
= makedev(majdev
, device_unit(dumpdv
));
864 dumpdev
= MAKEDISKDEV(major(rootdev
),
865 device_unit(dumpdv
), 1);
869 dumpcdev
= devsw_blk2chr(dumpdev
);
870 aprint_normal(" dumps on %s", device_xname(dumpdv
));
871 if (DEV_USES_PARTITIONS(dumpdv
))
872 aprint_normal("%c", (int)DISKPART(dumpdev
) + 'a');
883 finddevice(const char *name
)
887 if ((wname
= getwedgename(name
, strlen(name
))) != NULL
)
888 return dkwedge_find_by_wname(wname
);
890 return device_find_by_xname(name
);
894 getdisk(char *str
, int len
, int defpart
, dev_t
*devp
, int isdump
)
899 if ((dv
= parsedisk(str
, len
, defpart
, devp
)) == NULL
) {
900 printf("use one of:");
901 for (dv
= deviter_first(&di
, DEVITER_F_ROOT_FIRST
); dv
!= NULL
;
902 dv
= deviter_next(&di
)) {
903 if (DEV_USES_PARTITIONS(dv
))
904 printf(" %s[a-%c]", device_xname(dv
),
905 'a' + MAXPARTITIONS
- 1);
906 else if (device_class(dv
) == DV_DISK
)
907 printf(" %s", device_xname(dv
));
908 if (isdump
== 0 && device_class(dv
) == DV_IFNET
)
909 printf(" %s", device_xname(dv
));
911 deviter_release(&di
);
912 dkwedge_print_wnames();
918 printf(" halt reboot\n");
924 getwedgename(const char *name
, int namelen
)
926 const char *wpfx
= "wedge:";
927 const int wpfxlen
= strlen(wpfx
);
929 if (namelen
< wpfxlen
|| strncmp(name
, wpfx
, wpfxlen
) != 0)
932 return name
+ wpfxlen
;
936 parsedisk(char *str
, int len
, int defpart
, dev_t
*devp
)
945 if (len
== 4 && strcmp(str
, "halt") == 0)
946 cpu_reboot(RB_HALT
, NULL
);
947 else if (len
== 6 && strcmp(str
, "reboot") == 0)
950 else if (len
== 3 && strcmp(str
, "ddb") == 0)
957 if ((wname
= getwedgename(str
, len
)) != NULL
) {
958 if ((dv
= dkwedge_find_by_wname(wname
)) == NULL
)
962 } else if (c
>= 'a' && c
<= ('a' + MAXPARTITIONS
- 1)) {
968 dv
= finddevice(str
);
970 if (device_class(dv
) == DV_DISK
) {
972 majdev
= devsw_name2blk(device_xname(dv
), NULL
, 0);
975 if (DEV_USES_PARTITIONS(dv
))
976 *devp
= MAKEDISKDEV(majdev
, device_unit(dv
),
979 *devp
= makedev(majdev
, device_unit(dv
));
982 if (device_class(dv
) == DV_IFNET
)
991 * Return true if system call tracing is enabled for the specified process.
994 trace_is_enabled(struct proc
*p
)
1000 if (ISSET(p
->p_traceflag
, (KTRFAC_SYSCALL
| KTRFAC_SYSRET
)))
1004 if (ISSET(p
->p_slflag
, PSL_SYSCALL
))
1012 * Start trace of particular system call. If process is being traced,
1013 * this routine is called by MD syscall dispatch code just before
1014 * a system call is actually executed.
1017 trace_enter(register_t code
, const register_t
*args
, int narg
)
1019 #ifdef SYSCALL_DEBUG
1020 scdebug_call(code
, args
);
1021 #endif /* SYSCALL_DEBUG */
1023 ktrsyscall(code
, args
, narg
);
1026 if ((curlwp
->l_proc
->p_slflag
& (PSL_SYSCALL
|PSL_TRACED
)) ==
1027 (PSL_SYSCALL
|PSL_TRACED
))
1028 process_stoptrace();
1034 * End trace of particular system call. If process is being traced,
1035 * this routine is called by MD syscall dispatch code just after
1036 * a system call finishes.
1037 * MD caller guarantees the passed 'code' is within the supported
1038 * system call number range for emulation the process runs under.
1041 trace_exit(register_t code
, register_t rval
[], int error
)
1043 #ifdef SYSCALL_DEBUG
1044 scdebug_ret(code
, error
, rval
);
1045 #endif /* SYSCALL_DEBUG */
1047 ktrsysret(code
, error
, rval
);
1050 if ((curlwp
->l_proc
->p_slflag
& (PSL_SYSCALL
|PSL_TRACED
)) ==
1051 (PSL_SYSCALL
|PSL_TRACED
))
1052 process_stoptrace();
1057 syscall_establish(const struct emul
*em
, const struct syscall_package
*sp
)
1062 KASSERT(mutex_owned(&module_lock
));
1070 * Ensure that all preconditions are valid, since this is
1071 * an all or nothing deal. Once a system call is entered,
1072 * it can become busy and we could be unable to remove it
1075 for (i
= 0; sp
[i
].sp_call
!= NULL
; i
++) {
1076 if (sy
[sp
[i
].sp_code
].sy_call
!= sys_nomodule
) {
1078 printf("syscall %d is busy\n", sp
[i
].sp_code
);
1083 /* Everything looks good, patch them in. */
1084 for (i
= 0; sp
[i
].sp_call
!= NULL
; i
++) {
1085 sy
[sp
[i
].sp_code
].sy_call
= sp
[i
].sp_call
;
1092 syscall_disestablish(const struct emul
*em
, const struct syscall_package
*sp
)
1099 KASSERT(mutex_owned(&module_lock
));
1107 * First, patch the system calls to sys_nomodule to gate further
1110 for (i
= 0; sp
[i
].sp_call
!= NULL
; i
++) {
1111 KASSERT(sy
[sp
[i
].sp_code
].sy_call
== sp
[i
].sp_call
);
1112 sy
[sp
[i
].sp_code
].sy_call
= sys_nomodule
;
1116 * Run a cross call to cycle through all CPUs. This does two
1117 * things: lock activity provides a barrier and makes our update
1118 * of sy_call visible to all CPUs, and upon return we can be sure
1119 * that we see pertinent values of l_sysent posted by remote CPUs.
1121 where
= xc_broadcast(0, (xcfunc_t
)nullop
, NULL
, NULL
);
1125 * Now it's safe to check l_sysent. Run through all LWPs and see
1126 * if anyone is still using the system call.
1128 for (i
= 0; sp
[i
].sp_call
!= NULL
; i
++) {
1129 mutex_enter(proc_lock
);
1130 LIST_FOREACH(l
, &alllwp
, l_list
) {
1131 if (l
->l_sysent
== &sy
[sp
[i
].sp_code
]) {
1135 mutex_exit(proc_lock
);
1140 * We lose: one or more calls are still in use. Put back
1141 * the old entrypoints and act like nothing happened.
1142 * When we drop module_lock, any system calls held in
1143 * sys_nomodule() will be restarted.
1145 for (i
= 0; sp
[i
].sp_call
!= NULL
; i
++) {
1146 sy
[sp
[i
].sp_code
].sy_call
= sp
[i
].sp_call
;