The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kern_subr.c,v 1.192.4.1 2008/11/17 18:56:05 snj Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    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.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   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.
   19  *
   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.
   31  */
   32 
   33 /*
   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.
   41  *
   42  * Copyright (c) 1992, 1993
   43  *      The Regents of the University of California.  All rights reserved.
   44  *
   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.
   48  *
   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.
   53  *
   54  * Redistribution and use in source and binary forms, with or without
   55  * modification, are permitted provided that the following conditions
   56  * are met:
   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.
   65  *
   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
   76  * SUCH DAMAGE.
   77  *
   78  *      @(#)kern_subr.c 8.4 (Berkeley) 2/14/95
   79  */
   80 
   81 #include <sys/cdefs.h>
   82 __KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.192.4.1 2008/11/17 18:56:05 snj Exp $");
   83 
   84 #include "opt_ddb.h"
   85 #include "opt_md.h"
   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"
   91 
   92 #include <sys/param.h>
   93 #include <sys/systm.h>
   94 #include <sys/proc.h>
   95 #include <sys/malloc.h>
   96 #include <sys/mount.h>
   97 #include <sys/device.h>
   98 #include <sys/reboot.h>
   99 #include <sys/conf.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/pmf.h>
  109 
  110 #include <uvm/uvm_extern.h>
  111 
  112 #include <dev/cons.h>
  113 
  114 #include <net/if.h>
  115 
  116 /* XXX these should eventually move to subr_autoconf.c */
  117 static struct device *finddevice(const char *);
  118 static struct device *getdisk(char *, int, int, dev_t *, int);
  119 static struct device *parsedisk(char *, int, int, dev_t *);
  120 static const char *getwedgename(const char *, int);
  121 
  122 /*
  123  * A generic linear hook.
  124  */
  125 struct hook_desc {
  126         LIST_ENTRY(hook_desc) hk_list;
  127         void    (*hk_fn)(void *);
  128         void    *hk_arg;
  129 };
  130 typedef LIST_HEAD(, hook_desc) hook_list_t;
  131 
  132 #ifdef TFTPROOT
  133 int tftproot_dhcpboot(struct device *);
  134 #endif
  135 
  136 dev_t   dumpcdev;       /* for savecore */
  137 
  138 void
  139 uio_setup_sysspace(struct uio *uio)
  140 {
  141 
  142         uio->uio_vmspace = vmspace_kernel();
  143 }
  144 
  145 int
  146 uiomove(void *buf, size_t n, struct uio *uio)
  147 {
  148         struct vmspace *vm = uio->uio_vmspace;
  149         struct iovec *iov;
  150         size_t cnt;
  151         int error = 0;
  152         char *cp = buf;
  153 
  154         ASSERT_SLEEPABLE();
  155 
  156 #ifdef DIAGNOSTIC
  157         if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
  158                 panic("uiomove: mode");
  159 #endif
  160         while (n > 0 && uio->uio_resid) {
  161                 iov = uio->uio_iov;
  162                 cnt = iov->iov_len;
  163                 if (cnt == 0) {
  164                         KASSERT(uio->uio_iovcnt > 0);
  165                         uio->uio_iov++;
  166                         uio->uio_iovcnt--;
  167                         continue;
  168                 }
  169                 if (cnt > n)
  170                         cnt = n;
  171                 if (!VMSPACE_IS_KERNEL_P(vm)) {
  172                         if (curcpu()->ci_schedstate.spc_flags &
  173                             SPCF_SHOULDYIELD)
  174                                 preempt();
  175                 }
  176 
  177                 if (uio->uio_rw == UIO_READ) {
  178                         error = copyout_vmspace(vm, cp, iov->iov_base,
  179                             cnt);
  180                 } else {
  181                         error = copyin_vmspace(vm, iov->iov_base, cp,
  182                             cnt);
  183                 }
  184                 if (error) {
  185                         break;
  186                 }
  187                 iov->iov_base = (char *)iov->iov_base + cnt;
  188                 iov->iov_len -= cnt;
  189                 uio->uio_resid -= cnt;
  190                 uio->uio_offset += cnt;
  191                 cp += cnt;
  192                 KDASSERT(cnt <= n);
  193                 n -= cnt;
  194         }
  195 
  196         return (error);
  197 }
  198 
  199 /*
  200  * Wrapper for uiomove() that validates the arguments against a known-good
  201  * kernel buffer.
  202  */
  203 int
  204 uiomove_frombuf(void *buf, size_t buflen, struct uio *uio)
  205 {
  206         size_t offset;
  207 
  208         if (uio->uio_offset < 0 || /* uio->uio_resid < 0 || */
  209             (offset = uio->uio_offset) != uio->uio_offset)
  210                 return (EINVAL);
  211         if (offset >= buflen)
  212                 return (0);
  213         return (uiomove((char *)buf + offset, buflen - offset, uio));
  214 }
  215 
  216 /*
  217  * Give next character to user as result of read.
  218  */
  219 int
  220 ureadc(int c, struct uio *uio)
  221 {
  222         struct iovec *iov;
  223 
  224         if (uio->uio_resid <= 0)
  225                 panic("ureadc: non-positive resid");
  226 again:
  227         if (uio->uio_iovcnt <= 0)
  228                 panic("ureadc: non-positive iovcnt");
  229         iov = uio->uio_iov;
  230         if (iov->iov_len <= 0) {
  231                 uio->uio_iovcnt--;
  232                 uio->uio_iov++;
  233                 goto again;
  234         }
  235         if (!VMSPACE_IS_KERNEL_P(uio->uio_vmspace)) {
  236                 if (subyte(iov->iov_base, c) < 0)
  237                         return (EFAULT);
  238         } else {
  239                 *(char *)iov->iov_base = c;
  240         }
  241         iov->iov_base = (char *)iov->iov_base + 1;
  242         iov->iov_len--;
  243         uio->uio_resid--;
  244         uio->uio_offset++;
  245         return (0);
  246 }
  247 
  248 /*
  249  * Like copyin(), but operates on an arbitrary vmspace.
  250  */
  251 int
  252 copyin_vmspace(struct vmspace *vm, const void *uaddr, void *kaddr, size_t len)
  253 {
  254         struct iovec iov;
  255         struct uio uio;
  256         int error;
  257 
  258         if (len == 0)
  259                 return (0);
  260 
  261         if (VMSPACE_IS_KERNEL_P(vm)) {
  262                 return kcopy(uaddr, kaddr, len);
  263         }
  264         if (__predict_true(vm == curproc->p_vmspace)) {
  265                 return copyin(uaddr, kaddr, len);
  266         }
  267 
  268         iov.iov_base = kaddr;
  269         iov.iov_len = len;
  270         uio.uio_iov = &iov;
  271         uio.uio_iovcnt = 1;
  272         uio.uio_offset = (off_t)(uintptr_t)uaddr;
  273         uio.uio_resid = len;
  274         uio.uio_rw = UIO_READ;
  275         UIO_SETUP_SYSSPACE(&uio);
  276         error = uvm_io(&vm->vm_map, &uio);
  277 
  278         return (error);
  279 }
  280 
  281 /*
  282  * Like copyout(), but operates on an arbitrary vmspace.
  283  */
  284 int
  285 copyout_vmspace(struct vmspace *vm, const void *kaddr, void *uaddr, size_t len)
  286 {
  287         struct iovec iov;
  288         struct uio uio;
  289         int error;
  290 
  291         if (len == 0)
  292                 return (0);
  293 
  294         if (VMSPACE_IS_KERNEL_P(vm)) {
  295                 return kcopy(kaddr, uaddr, len);
  296         }
  297         if (__predict_true(vm == curproc->p_vmspace)) {
  298                 return copyout(kaddr, uaddr, len);
  299         }
  300 
  301         iov.iov_base = __UNCONST(kaddr); /* XXXUNCONST cast away const */
  302         iov.iov_len = len;
  303         uio.uio_iov = &iov;
  304         uio.uio_iovcnt = 1;
  305         uio.uio_offset = (off_t)(uintptr_t)uaddr;
  306         uio.uio_resid = len;
  307         uio.uio_rw = UIO_WRITE;
  308         UIO_SETUP_SYSSPACE(&uio);
  309         error = uvm_io(&vm->vm_map, &uio);
  310 
  311         return (error);
  312 }
  313 
  314 /*
  315  * Like copyin(), but operates on an arbitrary process.
  316  */
  317 int
  318 copyin_proc(struct proc *p, const void *uaddr, void *kaddr, size_t len)
  319 {
  320         struct vmspace *vm;
  321         int error;
  322 
  323         error = proc_vmspace_getref(p, &vm);
  324         if (error) {
  325                 return error;
  326         }
  327         error = copyin_vmspace(vm, uaddr, kaddr, len);
  328         uvmspace_free(vm);
  329 
  330         return error;
  331 }
  332 
  333 /*
  334  * Like copyout(), but operates on an arbitrary process.
  335  */
  336 int
  337 copyout_proc(struct proc *p, const void *kaddr, void *uaddr, size_t len)
  338 {
  339         struct vmspace *vm;
  340         int error;
  341 
  342         error = proc_vmspace_getref(p, &vm);
  343         if (error) {
  344                 return error;
  345         }
  346         error = copyout_vmspace(vm, kaddr, uaddr, len);
  347         uvmspace_free(vm);
  348 
  349         return error;
  350 }
  351 
  352 /*
  353  * Like copyin(), except it operates on kernel addresses when the FKIOCTL
  354  * flag is passed in `ioctlflags' from the ioctl call.
  355  */
  356 int
  357 ioctl_copyin(int ioctlflags, const void *src, void *dst, size_t len)
  358 {
  359         if (ioctlflags & FKIOCTL)
  360                 return kcopy(src, dst, len);
  361         return copyin(src, dst, len);
  362 }
  363 
  364 /*
  365  * Like copyout(), except it operates on kernel addresses when the FKIOCTL
  366  * flag is passed in `ioctlflags' from the ioctl call.
  367  */
  368 int
  369 ioctl_copyout(int ioctlflags, const void *src, void *dst, size_t len)
  370 {
  371         if (ioctlflags & FKIOCTL)
  372                 return kcopy(src, dst, len);
  373         return copyout(src, dst, len);
  374 }
  375 
  376 static void *
  377 hook_establish(hook_list_t *list, void (*fn)(void *), void *arg)
  378 {
  379         struct hook_desc *hd;
  380 
  381         hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT);
  382         if (hd == NULL)
  383                 return (NULL);
  384 
  385         hd->hk_fn = fn;
  386         hd->hk_arg = arg;
  387         LIST_INSERT_HEAD(list, hd, hk_list);
  388 
  389         return (hd);
  390 }
  391 
  392 static void
  393 hook_disestablish(hook_list_t *list, void *vhook)
  394 {
  395 #ifdef DIAGNOSTIC
  396         struct hook_desc *hd;
  397 
  398         LIST_FOREACH(hd, list, hk_list) {
  399                 if (hd == vhook)
  400                         break;
  401         }
  402 
  403         if (hd == NULL)
  404                 panic("hook_disestablish: hook %p not established", vhook);
  405 #endif
  406         LIST_REMOVE((struct hook_desc *)vhook, hk_list);
  407         free(vhook, M_DEVBUF);
  408 }
  409 
  410 static void
  411 hook_destroy(hook_list_t *list)
  412 {
  413         struct hook_desc *hd;
  414 
  415         while ((hd = LIST_FIRST(list)) != NULL) {
  416                 LIST_REMOVE(hd, hk_list);
  417                 free(hd, M_DEVBUF);
  418         }
  419 }
  420 
  421 static void
  422 hook_proc_run(hook_list_t *list, struct proc *p)
  423 {
  424         struct hook_desc *hd;
  425 
  426         LIST_FOREACH(hd, list, hk_list)
  427                 ((void (*)(struct proc *, void *))*hd->hk_fn)(p, hd->hk_arg);
  428 }
  429 
  430 /*
  431  * "Shutdown hook" types, functions, and variables.
  432  *
  433  * Should be invoked immediately before the
  434  * system is halted or rebooted, i.e. after file systems unmounted,
  435  * after crash dump done, etc.
  436  *
  437  * Each shutdown hook is removed from the list before it's run, so that
  438  * it won't be run again.
  439  */
  440 
  441 static hook_list_t shutdownhook_list;
  442 
  443 void *
  444 shutdownhook_establish(void (*fn)(void *), void *arg)
  445 {
  446         return hook_establish(&shutdownhook_list, fn, arg);
  447 }
  448 
  449 void
  450 shutdownhook_disestablish(void *vhook)
  451 {
  452         hook_disestablish(&shutdownhook_list, vhook);
  453 }
  454 
  455 /*
  456  * Run shutdown hooks.  Should be invoked immediately before the
  457  * system is halted or rebooted, i.e. after file systems unmounted,
  458  * after crash dump done, etc.
  459  *
  460  * Each shutdown hook is removed from the list before it's run, so that
  461  * it won't be run again.
  462  */
  463 void
  464 doshutdownhooks(void)
  465 {
  466         struct hook_desc *dp;
  467 
  468         while ((dp = LIST_FIRST(&shutdownhook_list)) != NULL) {
  469                 LIST_REMOVE(dp, hk_list);
  470                 (*dp->hk_fn)(dp->hk_arg);
  471 #if 0
  472                 /*
  473                  * Don't bother freeing the hook structure,, since we may
  474                  * be rebooting because of a memory corruption problem,
  475                  * and this might only make things worse.  It doesn't
  476                  * matter, anyway, since the system is just about to
  477                  * reboot.
  478                  */
  479                 free(dp, M_DEVBUF);
  480 #endif
  481         }
  482 
  483         pmf_system_shutdown(boothowto);
  484 }
  485 
  486 /*
  487  * "Mountroot hook" types, functions, and variables.
  488  */
  489 
  490 static hook_list_t mountroothook_list;
  491 
  492 void *
  493 mountroothook_establish(void (*fn)(struct device *), struct device *dev)
  494 {
  495         return hook_establish(&mountroothook_list, (void (*)(void *))fn, dev);
  496 }
  497 
  498 void
  499 mountroothook_disestablish(void *vhook)
  500 {
  501         hook_disestablish(&mountroothook_list, vhook);
  502 }
  503 
  504 void
  505 mountroothook_destroy(void)
  506 {
  507         hook_destroy(&mountroothook_list);
  508 }
  509 
  510 void
  511 domountroothook(void)
  512 {
  513         struct hook_desc *hd;
  514 
  515         LIST_FOREACH(hd, &mountroothook_list, hk_list) {
  516                 if (hd->hk_arg == (void *)root_device) {
  517                         (*hd->hk_fn)(hd->hk_arg);
  518                         return;
  519                 }
  520         }
  521 }
  522 
  523 static hook_list_t exechook_list;
  524 
  525 void *
  526 exechook_establish(void (*fn)(struct proc *, void *), void *arg)
  527 {
  528         return hook_establish(&exechook_list, (void (*)(void *))fn, arg);
  529 }
  530 
  531 void
  532 exechook_disestablish(void *vhook)
  533 {
  534         hook_disestablish(&exechook_list, vhook);
  535 }
  536 
  537 /*
  538  * Run exec hooks.
  539  */
  540 void
  541 doexechooks(struct proc *p)
  542 {
  543         hook_proc_run(&exechook_list, p);
  544 }
  545 
  546 static hook_list_t exithook_list;
  547 extern krwlock_t exec_lock;
  548 
  549 void *
  550 exithook_establish(void (*fn)(struct proc *, void *), void *arg)
  551 {
  552         void *rv;
  553 
  554         rw_enter(&exec_lock, RW_WRITER);
  555         rv = hook_establish(&exithook_list, (void (*)(void *))fn, arg);
  556         rw_exit(&exec_lock);
  557         return rv;
  558 }
  559 
  560 void
  561 exithook_disestablish(void *vhook)
  562 {
  563 
  564         rw_enter(&exec_lock, RW_WRITER);
  565         hook_disestablish(&exithook_list, vhook);
  566         rw_exit(&exec_lock);
  567 }
  568 
  569 /*
  570  * Run exit hooks.
  571  */
  572 void
  573 doexithooks(struct proc *p)
  574 {
  575         hook_proc_run(&exithook_list, p);
  576 }
  577 
  578 static hook_list_t forkhook_list;
  579 
  580 void *
  581 forkhook_establish(void (*fn)(struct proc *, struct proc *))
  582 {
  583         return hook_establish(&forkhook_list, (void (*)(void *))fn, NULL);
  584 }
  585 
  586 void
  587 forkhook_disestablish(void *vhook)
  588 {
  589         hook_disestablish(&forkhook_list, vhook);
  590 }
  591 
  592 /*
  593  * Run fork hooks.
  594  */
  595 void
  596 doforkhooks(struct proc *p2, struct proc *p1)
  597 {
  598         struct hook_desc *hd;
  599 
  600         LIST_FOREACH(hd, &forkhook_list, hk_list) {
  601                 ((void (*)(struct proc *, struct proc *))*hd->hk_fn)
  602                     (p2, p1);
  603         }
  604 }
  605 
  606 /*
  607  * "Power hook" types, functions, and variables.
  608  * The list of power hooks is kept ordered with the last registered hook
  609  * first.
  610  * When running the hooks on power down the hooks are called in reverse
  611  * registration order, when powering up in registration order.
  612  */
  613 struct powerhook_desc {
  614         CIRCLEQ_ENTRY(powerhook_desc) sfd_list;
  615         void    (*sfd_fn)(int, void *);
  616         void    *sfd_arg;
  617         char    sfd_name[16];
  618 };
  619 
  620 static CIRCLEQ_HEAD(, powerhook_desc) powerhook_list =
  621     CIRCLEQ_HEAD_INITIALIZER(powerhook_list);
  622 
  623 void *
  624 powerhook_establish(const char *name, void (*fn)(int, void *), void *arg)
  625 {
  626         struct powerhook_desc *ndp;
  627 
  628         ndp = (struct powerhook_desc *)
  629             malloc(sizeof(*ndp), M_DEVBUF, M_NOWAIT);
  630         if (ndp == NULL)
  631                 return (NULL);
  632 
  633         ndp->sfd_fn = fn;
  634         ndp->sfd_arg = arg;
  635         strlcpy(ndp->sfd_name, name, sizeof(ndp->sfd_name));
  636         CIRCLEQ_INSERT_HEAD(&powerhook_list, ndp, sfd_list);
  637 
  638         aprint_error("%s: WARNING: powerhook_establish is deprecated\n", name);
  639         return (ndp);
  640 }
  641 
  642 void
  643 powerhook_disestablish(void *vhook)
  644 {
  645 #ifdef DIAGNOSTIC
  646         struct powerhook_desc *dp;
  647 
  648         CIRCLEQ_FOREACH(dp, &powerhook_list, sfd_list)
  649                 if (dp == vhook)
  650                         goto found;
  651         panic("powerhook_disestablish: hook %p not established", vhook);
  652  found:
  653 #endif
  654 
  655         CIRCLEQ_REMOVE(&powerhook_list, (struct powerhook_desc *)vhook,
  656             sfd_list);
  657         free(vhook, M_DEVBUF);
  658 }
  659 
  660 /*
  661  * Run power hooks.
  662  */
  663 void
  664 dopowerhooks(int why)
  665 {
  666         struct powerhook_desc *dp;
  667 
  668 #ifdef POWERHOOK_DEBUG
  669         const char *why_name;
  670         static const char * pwr_names[] = {PWR_NAMES};
  671         why_name = why < __arraycount(pwr_names) ? pwr_names[why] : "???";
  672 #endif
  673 
  674         if (why == PWR_RESUME || why == PWR_SOFTRESUME) {
  675                 CIRCLEQ_FOREACH_REVERSE(dp, &powerhook_list, sfd_list) {
  676 #ifdef POWERHOOK_DEBUG
  677                         printf("dopowerhooks %s: %s (%p)\n", why_name, dp->sfd_name, dp);
  678 #endif
  679                         (*dp->sfd_fn)(why, dp->sfd_arg);
  680                 }
  681         } else {
  682                 CIRCLEQ_FOREACH(dp, &powerhook_list, sfd_list) {
  683 #ifdef POWERHOOK_DEBUG
  684                         printf("dopowerhooks %s: %s (%p)\n", why_name, dp->sfd_name, dp);
  685 #endif
  686                         (*dp->sfd_fn)(why, dp->sfd_arg);
  687                 }
  688         }
  689 
  690 #ifdef POWERHOOK_DEBUG
  691         printf("dopowerhooks: %s done\n", why_name);
  692 #endif
  693 }
  694 
  695 static int
  696 isswap(struct device *dv)
  697 {
  698         struct dkwedge_info wi;
  699         struct vnode *vn;
  700         int error;
  701 
  702         if (device_class(dv) != DV_DISK || !device_is_a(dv, "dk"))
  703                 return 0;
  704 
  705         if ((vn = opendisk(dv)) == NULL)
  706                 return 0;
  707 
  708         error = VOP_IOCTL(vn, DIOCGWEDGEINFO, &wi, FREAD, NOCRED);
  709         VOP_CLOSE(vn, FREAD, NOCRED);
  710         vput(vn);
  711         if (error) {
  712 #ifdef DEBUG_WEDGE
  713                 printf("%s: Get wedge info returned %d\n", device_xname(dv), error);
  714 #endif
  715                 return 0;
  716         }
  717         return strcmp(wi.dkw_ptype, DKW_PTYPE_SWAP) == 0;
  718 }
  719 
  720 /*
  721  * Determine the root device and, if instructed to, the root file system.
  722  */
  723 
  724 #include "md.h"
  725 
  726 #if NMD > 0
  727 extern struct cfdriver md_cd;
  728 #ifdef MEMORY_DISK_IS_ROOT
  729 int md_is_root = 1;
  730 #else
  731 int md_is_root = 0;
  732 #endif
  733 #endif
  734 
  735 /*
  736  * The device and wedge that we booted from.  If booted_wedge is NULL,
  737  * the we might consult booted_partition.
  738  */
  739 struct device *booted_device;
  740 struct device *booted_wedge;
  741 int booted_partition;
  742 
  743 /*
  744  * Use partition letters if it's a disk class but not a wedge.
  745  * XXX Check for wedge is kinda gross.
  746  */
  747 #define DEV_USES_PARTITIONS(dv)                                         \
  748         (device_class((dv)) == DV_DISK &&                               \
  749          !device_is_a((dv), "dk"))
  750 
  751 void
  752 setroot(struct device *bootdv, int bootpartition)
  753 {
  754         struct device *dv;
  755         int len, majdev;
  756         dev_t nrootdev;
  757         dev_t ndumpdev = NODEV;
  758         char buf[128];
  759         const char *rootdevname;
  760         const char *dumpdevname;
  761         struct device *rootdv = NULL;           /* XXX gcc -Wuninitialized */
  762         struct device *dumpdv = NULL;
  763         struct ifnet *ifp;
  764         const char *deffsname;
  765         struct vfsops *vops;
  766 
  767 #ifdef TFTPROOT
  768         if (tftproot_dhcpboot(bootdv) != 0)
  769                 boothowto |= RB_ASKNAME;
  770 #endif
  771 
  772 #if NMD > 0
  773         if (md_is_root) {
  774                 /*
  775                  * XXX there should be "root on md0" in the config file,
  776                  * but it isn't always
  777                  */
  778                 bootdv = md_cd.cd_devs[0];
  779                 bootpartition = 0;
  780         }
  781 #endif
  782 
  783         /*
  784          * If NFS is specified as the file system, and we found
  785          * a DV_DISK boot device (or no boot device at all), then
  786          * find a reasonable network interface for "rootspec".
  787          */
  788         vops = vfs_getopsbyname("nfs");
  789         if (vops != NULL && vops->vfs_mountroot == mountroot &&
  790             rootspec == NULL &&
  791             (bootdv == NULL || device_class(bootdv) != DV_IFNET)) {
  792                 IFNET_FOREACH(ifp) {
  793                         if ((ifp->if_flags &
  794                              (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
  795                                 break;
  796                 }
  797                 if (ifp == NULL) {
  798                         /*
  799                          * Can't find a suitable interface; ask the
  800                          * user.
  801                          */
  802                         boothowto |= RB_ASKNAME;
  803                 } else {
  804                         /*
  805                          * Have a suitable interface; behave as if
  806                          * the user specified this interface.
  807                          */
  808                         rootspec = (const char *)ifp->if_xname;
  809                 }
  810         }
  811         if (vops != NULL)
  812                 vfs_delref(vops);
  813 
  814         /*
  815          * If wildcarded root and we the boot device wasn't determined,
  816          * ask the user.
  817          */
  818         if (rootspec == NULL && bootdv == NULL)
  819                 boothowto |= RB_ASKNAME;
  820 
  821  top:
  822         if (boothowto & RB_ASKNAME) {
  823                 struct device *defdumpdv;
  824 
  825                 for (;;) {
  826                         printf("root device");
  827                         if (bootdv != NULL) {
  828                                 printf(" (default %s", device_xname(bootdv));
  829                                 if (DEV_USES_PARTITIONS(bootdv))
  830                                         printf("%c", bootpartition + 'a');
  831                                 printf(")");
  832                         }
  833                         printf(": ");
  834                         len = cngetsn(buf, sizeof(buf));
  835                         if (len == 0 && bootdv != NULL) {
  836                                 strlcpy(buf, device_xname(bootdv), sizeof(buf));
  837                                 len = strlen(buf);
  838                         }
  839                         if (len > 0 && buf[len - 1] == '*') {
  840                                 buf[--len] = '\0';
  841                                 dv = getdisk(buf, len, 1, &nrootdev, 0);
  842                                 if (dv != NULL) {
  843                                         rootdv = dv;
  844                                         break;
  845                                 }
  846                         }
  847                         dv = getdisk(buf, len, bootpartition, &nrootdev, 0);
  848                         if (dv != NULL) {
  849                                 rootdv = dv;
  850                                 break;
  851                         }
  852                 }
  853 
  854                 /*
  855                  * Set up the default dump device.  If root is on
  856                  * a network device, there is no default dump
  857                  * device, since we don't support dumps to the
  858                  * network.
  859                  */
  860                 if (DEV_USES_PARTITIONS(rootdv) == 0)
  861                         defdumpdv = NULL;
  862                 else
  863                         defdumpdv = rootdv;
  864 
  865                 for (;;) {
  866                         printf("dump device");
  867                         if (defdumpdv != NULL) {
  868                                 /*
  869                                  * Note, we know it's a disk if we get here.
  870                                  */
  871                                 printf(" (default %sb)", device_xname(defdumpdv));
  872                         }
  873                         printf(": ");
  874                         len = cngetsn(buf, sizeof(buf));
  875                         if (len == 0) {
  876                                 if (defdumpdv != NULL) {
  877                                         ndumpdev = MAKEDISKDEV(major(nrootdev),
  878                                             DISKUNIT(nrootdev), 1);
  879                                 }
  880                                 dumpdv = defdumpdv;
  881                                 break;
  882                         }
  883                         if (len == 4 && strcmp(buf, "none") == 0) {
  884                                 dumpdv = NULL;
  885                                 break;
  886                         }
  887                         dv = getdisk(buf, len, 1, &ndumpdev, 1);
  888                         if (dv != NULL) {
  889                                 dumpdv = dv;
  890                                 break;
  891                         }
  892                 }
  893 
  894                 rootdev = nrootdev;
  895                 dumpdev = ndumpdev;
  896 
  897                 for (vops = LIST_FIRST(&vfs_list); vops != NULL;
  898                      vops = LIST_NEXT(vops, vfs_list)) {
  899                         if (vops->vfs_mountroot != NULL &&
  900                             vops->vfs_mountroot == mountroot)
  901                         break;
  902                 }
  903 
  904                 if (vops == NULL) {
  905                         mountroot = NULL;
  906                         deffsname = "generic";
  907                 } else
  908                         deffsname = vops->vfs_name;
  909 
  910                 for (;;) {
  911                         printf("file system (default %s): ", deffsname);
  912                         len = cngetsn(buf, sizeof(buf));
  913                         if (len == 0)
  914                                 break;
  915                         if (len == 4 && strcmp(buf, "halt") == 0)
  916                                 cpu_reboot(RB_HALT, NULL);
  917                         else if (len == 6 && strcmp(buf, "reboot") == 0)
  918                                 cpu_reboot(0, NULL);
  919 #if defined(DDB)
  920                         else if (len == 3 && strcmp(buf, "ddb") == 0) {
  921                                 console_debugger();
  922                         }
  923 #endif
  924                         else if (len == 7 && strcmp(buf, "generic") == 0) {
  925                                 mountroot = NULL;
  926                                 break;
  927                         }
  928                         vops = vfs_getopsbyname(buf);
  929                         if (vops == NULL || vops->vfs_mountroot == NULL) {
  930                                 printf("use one of: generic");
  931                                 for (vops = LIST_FIRST(&vfs_list);
  932                                      vops != NULL;
  933                                      vops = LIST_NEXT(vops, vfs_list)) {
  934                                         if (vops->vfs_mountroot != NULL)
  935                                                 printf(" %s", vops->vfs_name);
  936                                 }
  937 #if defined(DDB)
  938                                 printf(" ddb");
  939 #endif
  940                                 printf(" halt reboot\n");
  941                         } else {
  942                                 mountroot = vops->vfs_mountroot;
  943                                 vfs_delref(vops);
  944                                 break;
  945                         }
  946                 }
  947 
  948         } else if (rootspec == NULL) {
  949                 /*
  950                  * Wildcarded root; use the boot device.
  951                  */
  952                 rootdv = bootdv;
  953 
  954                 if (bootdv)
  955                         majdev = devsw_name2blk(device_xname(bootdv), NULL, 0);
  956                 else
  957                         majdev = -1;
  958                 if (majdev >= 0) {
  959                         /*
  960                          * Root is on a disk.  `bootpartition' is root,
  961                          * unless the device does not use partitions.
  962                          */
  963                         if (DEV_USES_PARTITIONS(bootdv))
  964                                 rootdev = MAKEDISKDEV(majdev,
  965                                                       device_unit(bootdv),
  966                                                       bootpartition);
  967                         else
  968                                 rootdev = makedev(majdev, device_unit(bootdv));
  969                 }
  970         } else {
  971 
  972                 /*
  973                  * `root on <dev> ...'
  974                  */
  975 
  976                 /*
  977                  * If it's a network interface, we can bail out
  978                  * early.
  979                  */
  980                 dv = finddevice(rootspec);
  981                 if (dv != NULL && device_class(dv) == DV_IFNET) {
  982                         rootdv = dv;
  983                         goto haveroot;
  984                 }
  985 
  986                 if (rootdev == NODEV &&
  987                     device_class(dv) == DV_DISK && device_is_a(dv, "dk") &&
  988                     (majdev = devsw_name2blk(device_xname(dv), NULL, 0)) >= 0)
  989                         rootdev = makedev(majdev, device_unit(dv));
  990 
  991                 rootdevname = devsw_blk2name(major(rootdev));
  992                 if (rootdevname == NULL) {
  993                         printf("unknown device major 0x%x\n", rootdev);
  994                         boothowto |= RB_ASKNAME;
  995                         goto top;
  996                 }
  997                 memset(buf, 0, sizeof(buf));
  998                 snprintf(buf, sizeof(buf), "%s%d", rootdevname,
  999                     DISKUNIT(rootdev));
 1000 
 1001                 rootdv = finddevice(buf);
 1002                 if (rootdv == NULL) {
 1003                         printf("device %s (0x%x) not configured\n",
 1004                             buf, rootdev);
 1005                         boothowto |= RB_ASKNAME;
 1006                         goto top;
 1007                 }
 1008         }
 1009 
 1010  haveroot:
 1011 
 1012         root_device = rootdv;
 1013 
 1014         switch (device_class(rootdv)) {
 1015         case DV_IFNET:
 1016         case DV_DISK:
 1017                 aprint_normal("root on %s", device_xname(rootdv));
 1018                 if (DEV_USES_PARTITIONS(rootdv))
 1019                         aprint_normal("%c", DISKPART(rootdev) + 'a');
 1020                 break;
 1021 
 1022         default:
 1023                 printf("can't determine root device\n");
 1024                 boothowto |= RB_ASKNAME;
 1025                 goto top;
 1026         }
 1027 
 1028         /*
 1029          * Now configure the dump device.
 1030          *
 1031          * If we haven't figured out the dump device, do so, with
 1032          * the following rules:
 1033          *
 1034          *      (a) We already know dumpdv in the RB_ASKNAME case.
 1035          *
 1036          *      (b) If dumpspec is set, try to use it.  If the device
 1037          *          is not available, punt.
 1038          *
 1039          *      (c) If dumpspec is not set, the dump device is
 1040          *          wildcarded or unspecified.  If the root device
 1041          *          is DV_IFNET, punt.  Otherwise, use partition b
 1042          *          of the root device.
 1043          */
 1044 
 1045         if (boothowto & RB_ASKNAME) {           /* (a) */
 1046                 if (dumpdv == NULL)
 1047                         goto nodumpdev;
 1048         } else if (dumpspec != NULL) {          /* (b) */
 1049                 if (strcmp(dumpspec, "none") == 0 || dumpdev == NODEV) {
 1050                         /*
 1051                          * Operator doesn't want a dump device.
 1052                          * Or looks like they tried to pick a network
 1053                          * device.  Oops.
 1054                          */
 1055                         goto nodumpdev;
 1056                 }
 1057 
 1058                 dumpdevname = devsw_blk2name(major(dumpdev));
 1059                 if (dumpdevname == NULL)
 1060                         goto nodumpdev;
 1061                 memset(buf, 0, sizeof(buf));
 1062                 snprintf(buf, sizeof(buf), "%s%d", dumpdevname,
 1063                     DISKUNIT(dumpdev));
 1064 
 1065                 dumpdv = finddevice(buf);
 1066                 if (dumpdv == NULL) {
 1067                         /*
 1068                          * Device not configured.
 1069                          */
 1070                         goto nodumpdev;
 1071                 }
 1072         } else {                                /* (c) */
 1073                 if (DEV_USES_PARTITIONS(rootdv) == 0) {
 1074                         for (dv = TAILQ_FIRST(&alldevs); dv != NULL;
 1075                             dv = TAILQ_NEXT(dv, dv_list))
 1076                                 if (isswap(dv))
 1077                                         break;
 1078                         if (dv == NULL)
 1079                                 goto nodumpdev;
 1080 
 1081                         majdev = devsw_name2blk(device_xname(dv), NULL, 0);
 1082                         if (majdev < 0)
 1083                                 goto nodumpdev;
 1084                         dumpdv = dv;
 1085                         dumpdev = makedev(majdev, device_unit(dumpdv));
 1086                 } else {
 1087                         dumpdv = rootdv;
 1088                         dumpdev = MAKEDISKDEV(major(rootdev),
 1089                             device_unit(dumpdv), 1);
 1090                 }
 1091         }
 1092 
 1093         dumpcdev = devsw_blk2chr(dumpdev);
 1094         aprint_normal(" dumps on %s", device_xname(dumpdv));
 1095         if (DEV_USES_PARTITIONS(dumpdv))
 1096                 aprint_normal("%c", DISKPART(dumpdev) + 'a');
 1097         aprint_normal("\n");
 1098         return;
 1099 
 1100  nodumpdev:
 1101         dumpdev = NODEV;
 1102         dumpcdev = NODEV;
 1103         aprint_normal("\n");
 1104 }
 1105 
 1106 static struct device *
 1107 finddevice(const char *name)
 1108 {
 1109         const char *wname;
 1110 
 1111         if ((wname = getwedgename(name, strlen(name))) != NULL)
 1112                 return dkwedge_find_by_wname(wname);
 1113 
 1114         return device_find_by_xname(name);
 1115 }
 1116 
 1117 static struct device *
 1118 getdisk(char *str, int len, int defpart, dev_t *devp, int isdump)
 1119 {
 1120         struct device   *dv;
 1121 
 1122         if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
 1123                 printf("use one of:");
 1124                 TAILQ_FOREACH(dv, &alldevs, dv_list) {
 1125                         if (DEV_USES_PARTITIONS(dv))
 1126                                 printf(" %s[a-%c]", device_xname(dv),
 1127                                     'a' + MAXPARTITIONS - 1);
 1128                         else if (device_class(dv) == DV_DISK)
 1129                                 printf(" %s", device_xname(dv));
 1130                         if (isdump == 0 && device_class(dv) == DV_IFNET)
 1131                                 printf(" %s", device_xname(dv));
 1132                 }
 1133                 dkwedge_print_wnames();
 1134                 if (isdump)
 1135                         printf(" none");
 1136 #if defined(DDB)
 1137                 printf(" ddb");
 1138 #endif
 1139                 printf(" halt reboot\n");
 1140         }
 1141         return dv;
 1142 }
 1143 
 1144 static const char *
 1145 getwedgename(const char *name, int namelen)
 1146 {
 1147         const char *wpfx = "wedge:";
 1148         const int wpfxlen = strlen(wpfx);
 1149 
 1150         if (namelen < wpfxlen || strncmp(name, wpfx, wpfxlen) != 0)
 1151                 return NULL;
 1152 
 1153         return name + wpfxlen;
 1154 }
 1155 
 1156 static struct device *
 1157 parsedisk(char *str, int len, int defpart, dev_t *devp)
 1158 {
 1159         struct device *dv;
 1160         const char *wname;
 1161         char *cp, c;
 1162         int majdev, part;
 1163         if (len == 0)
 1164                 return (NULL);
 1165 
 1166         if (len == 4 && strcmp(str, "halt") == 0)
 1167                 cpu_reboot(RB_HALT, NULL);
 1168         else if (len == 6 && strcmp(str, "reboot") == 0)
 1169                 cpu_reboot(0, NULL);
 1170 #if defined(DDB)
 1171         else if (len == 3 && strcmp(str, "ddb") == 0)
 1172                 console_debugger();
 1173 #endif
 1174 
 1175         cp = str + len - 1;
 1176         c = *cp;
 1177 
 1178         if ((wname = getwedgename(str, len)) != NULL) {
 1179                 if ((dv = dkwedge_find_by_wname(wname)) == NULL)
 1180                         return NULL;
 1181                 part = defpart;
 1182                 goto gotdisk;
 1183         } else if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
 1184                 part = c - 'a';
 1185                 *cp = '\0';
 1186         } else
 1187                 part = defpart;
 1188 
 1189         dv = finddevice(str);
 1190         if (dv != NULL) {
 1191                 if (device_class(dv) == DV_DISK) {
 1192  gotdisk:
 1193                         majdev = devsw_name2blk(device_xname(dv), NULL, 0);
 1194                         if (majdev < 0)
 1195                                 panic("parsedisk");
 1196                         if (DEV_USES_PARTITIONS(dv))
 1197                                 *devp = MAKEDISKDEV(majdev, device_unit(dv),
 1198                                                     part);
 1199                         else
 1200                                 *devp = makedev(majdev, device_unit(dv));
 1201                 }
 1202 
 1203                 if (device_class(dv) == DV_IFNET)
 1204                         *devp = NODEV;
 1205         }
 1206 
 1207         *cp = c;
 1208         return (dv);
 1209 }
 1210 
 1211 /*
 1212  * snprintf() `bytes' into `buf', reformatting it so that the number,
 1213  * plus a possible `x' + suffix extension) fits into len bytes (including
 1214  * the terminating NUL).
 1215  * Returns the number of bytes stored in buf, or -1 if there was a problem.
 1216  * E.g, given a len of 9 and a suffix of `B':
 1217  *      bytes           result
 1218  *      -----           ------
 1219  *      99999           `99999 B'
 1220  *      100000          `97 kB'
 1221  *      66715648        `65152 kB'
 1222  *      252215296       `240 MB'
 1223  */
 1224 int
 1225 humanize_number(char *buf, size_t len, uint64_t bytes, const char *suffix,
 1226     int divisor)
 1227 {
 1228         /* prefixes are: (none), kilo, Mega, Giga, Tera, Peta, Exa */
 1229         const char *prefixes;
 1230         int             r;
 1231         uint64_t        umax;
 1232         size_t          i, suffixlen;
 1233 
 1234         if (buf == NULL || suffix == NULL)
 1235                 return (-1);
 1236         if (len > 0)
 1237                 buf[0] = '\0';
 1238         suffixlen = strlen(suffix);
 1239         /* check if enough room for `x y' + suffix + `\0' */
 1240         if (len < 4 + suffixlen)
 1241                 return (-1);
 1242 
 1243         if (divisor == 1024) {
 1244                 /*
 1245                  * binary multiplies
 1246                  * XXX IEC 60027-2 recommends Ki, Mi, Gi...
 1247                  */
 1248                 prefixes = " KMGTPE";
 1249         } else
 1250                 prefixes = " kMGTPE"; /* SI for decimal multiplies */
 1251 
 1252         umax = 1;
 1253         for (i = 0; i < len - suffixlen - 3; i++)
 1254                 umax *= 10;
 1255         for (i = 0; bytes >= umax && prefixes[i + 1]; i++)
 1256                 bytes /= divisor;
 1257 
 1258         r = snprintf(buf, len, "%qu%s%c%s", (unsigned long long)bytes,
 1259             i == 0 ? "" : " ", prefixes[i], suffix);
 1260 
 1261         return (r);
 1262 }
 1263 
 1264 int
 1265 format_bytes(char *buf, size_t len, uint64_t bytes)
 1266 {
 1267         int     rv;
 1268         size_t  nlen;
 1269 
 1270         rv = humanize_number(buf, len, bytes, "B", 1024);
 1271         if (rv != -1) {
 1272                         /* nuke the trailing ` B' if it exists */
 1273                 nlen = strlen(buf) - 2;
 1274                 if (strcmp(&buf[nlen], " B") == 0)
 1275                         buf[nlen] = '\0';
 1276         }
 1277         return (rv);
 1278 }
 1279 
 1280 /*
 1281  * Return true if system call tracing is enabled for the specified process.
 1282  */
 1283 bool
 1284 trace_is_enabled(struct proc *p)
 1285 {
 1286 #ifdef SYSCALL_DEBUG
 1287         return (true);
 1288 #endif
 1289 #ifdef KTRACE
 1290         if (ISSET(p->p_traceflag, (KTRFAC_SYSCALL | KTRFAC_SYSRET)))
 1291                 return (true);
 1292 #endif
 1293 #ifdef PTRACE
 1294         if (ISSET(p->p_slflag, PSL_SYSCALL))
 1295                 return (true);
 1296 #endif
 1297 
 1298         return (false);
 1299 }
 1300 
 1301 /*
 1302  * Start trace of particular system call. If process is being traced,
 1303  * this routine is called by MD syscall dispatch code just before
 1304  * a system call is actually executed.
 1305  */
 1306 int
 1307 trace_enter(register_t code, const register_t *args, int narg)
 1308 {
 1309 #ifdef SYSCALL_DEBUG
 1310         scdebug_call(code, args);
 1311 #endif /* SYSCALL_DEBUG */
 1312 
 1313         ktrsyscall(code, args, narg);
 1314 
 1315 #ifdef PTRACE
 1316         if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
 1317             (PSL_SYSCALL|PSL_TRACED))
 1318                 process_stoptrace();
 1319 #endif
 1320         return 0;
 1321 }
 1322 
 1323 /*
 1324  * End trace of particular system call. If process is being traced,
 1325  * this routine is called by MD syscall dispatch code just after
 1326  * a system call finishes.
 1327  * MD caller guarantees the passed 'code' is within the supported
 1328  * system call number range for emulation the process runs under.
 1329  */
 1330 void
 1331 trace_exit(register_t code, register_t rval[], int error)
 1332 {
 1333 #ifdef SYSCALL_DEBUG
 1334         scdebug_ret(code, error, rval);
 1335 #endif /* SYSCALL_DEBUG */
 1336 
 1337         ktrsysret(code, error, rval);
 1338         
 1339 #ifdef PTRACE
 1340         if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
 1341             (PSL_SYSCALL|PSL_TRACED))
 1342                 process_stoptrace();
 1343 #endif
 1344 }

Cache object: 50686ff2967690375e75f52298fe8d12


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.