kern_subr.c revision 1.208 1 /* $NetBSD: kern_subr.c,v 1.208 2010/11/11 11:07:07 hannken 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.208 2010/11/11 11:07:07 hannken 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_tftproot.h"
90
91 #include <sys/param.h>
92 #include <sys/systm.h>
93 #include <sys/proc.h>
94 #include <sys/mount.h>
95 #include <sys/device.h>
96 #include <sys/reboot.h>
97 #include <sys/conf.h>
98 #include <sys/disk.h>
99 #include <sys/disklabel.h>
100 #include <sys/queue.h>
101 #include <sys/ktrace.h>
102 #include <sys/ptrace.h>
103 #include <sys/fcntl.h>
104 #include <sys/kauth.h>
105 #include <sys/stat.h>
106 #include <sys/vnode.h>
107 #include <sys/module.h>
108
109 #include <uvm/uvm_extern.h>
110
111 #include <dev/cons.h>
112
113 #include <net/if.h>
114
115 /* XXX these should eventually move to subr_autoconf.c */
116 static device_t finddevice(const char *);
117 static device_t getdisk(char *, int, int, dev_t *, int);
118 static device_t parsedisk(char *, int, int, dev_t *);
119 static const char *getwedgename(const char *, int);
120
121 #ifdef TFTPROOT
122 int tftproot_dhcpboot(device_t);
123 #endif
124
125 dev_t dumpcdev; /* for savecore */
126
127 static int
128 isswap(device_t dv)
129 {
130 struct dkwedge_info wi;
131 struct vnode *vn;
132 int error;
133
134 if (device_class(dv) != DV_DISK || !device_is_a(dv, "dk"))
135 return 0;
136
137 if ((vn = opendisk(dv)) == NULL)
138 return 0;
139
140 error = VOP_IOCTL(vn, DIOCGWEDGEINFO, &wi, FREAD, NOCRED);
141 VOP_CLOSE(vn, FREAD, NOCRED);
142 vput(vn);
143 if (error) {
144 #ifdef DEBUG_WEDGE
145 printf("%s: Get wedge info returned %d\n", device_xname(dv), error);
146 #endif
147 return 0;
148 }
149 return strcmp(wi.dkw_ptype, DKW_PTYPE_SWAP) == 0;
150 }
151
152 /*
153 * Determine the root device and, if instructed to, the root file system.
154 */
155
156 #ifdef MEMORY_DISK_IS_ROOT
157 int md_is_root = 1;
158 #else
159 int md_is_root = 0;
160 #endif
161
162 /*
163 * The device and wedge that we booted from. If booted_wedge is NULL,
164 * the we might consult booted_partition.
165 */
166 device_t booted_device;
167 device_t booted_wedge;
168 int booted_partition;
169
170 /*
171 * Use partition letters if it's a disk class but not a wedge.
172 * XXX Check for wedge is kinda gross.
173 */
174 #define DEV_USES_PARTITIONS(dv) \
175 (device_class((dv)) == DV_DISK && \
176 !device_is_a((dv), "dk"))
177
178 void
179 setroot(device_t bootdv, int bootpartition)
180 {
181 device_t dv;
182 deviter_t di;
183 int len, majdev;
184 dev_t nrootdev;
185 dev_t ndumpdev = NODEV;
186 char buf[128];
187 const char *rootdevname;
188 const char *dumpdevname;
189 device_t rootdv = NULL; /* XXX gcc -Wuninitialized */
190 device_t dumpdv = NULL;
191 struct ifnet *ifp;
192 const char *deffsname;
193 struct vfsops *vops;
194
195 #ifdef TFTPROOT
196 if (tftproot_dhcpboot(bootdv) != 0)
197 boothowto |= RB_ASKNAME;
198 #endif
199
200 /*
201 * For root on md0 we have to force the attachment of md0.
202 */
203 if (md_is_root) {
204 int md_major;
205 dev_t md_dev;
206
207 bootdv = NULL;
208 md_major = devsw_name2blk("md", NULL, 0);
209 if (md_major >= 0) {
210 md_dev = MAKEDISKDEV(md_major, 0, RAW_PART);
211 if (bdev_open(md_dev, FREAD, S_IFBLK, curlwp) == 0)
212 bootdv = device_find_by_xname("md0");
213 }
214 if (bootdv == NULL)
215 panic("Cannot open \"md0\" (root)");
216 }
217
218 /*
219 * If NFS is specified as the file system, and we found
220 * a DV_DISK boot device (or no boot device at all), then
221 * find a reasonable network interface for "rootspec".
222 */
223 vops = vfs_getopsbyname(MOUNT_NFS);
224 if (vops != NULL && strcmp(rootfstype, MOUNT_NFS) == 0 &&
225 rootspec == NULL &&
226 (bootdv == NULL || device_class(bootdv) != DV_IFNET)) {
227 IFNET_FOREACH(ifp) {
228 if ((ifp->if_flags &
229 (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
230 break;
231 }
232 if (ifp == NULL) {
233 /*
234 * Can't find a suitable interface; ask the
235 * user.
236 */
237 boothowto |= RB_ASKNAME;
238 } else {
239 /*
240 * Have a suitable interface; behave as if
241 * the user specified this interface.
242 */
243 rootspec = (const char *)ifp->if_xname;
244 }
245 }
246 if (vops != NULL)
247 vfs_delref(vops);
248
249 /*
250 * If wildcarded root and we the boot device wasn't determined,
251 * ask the user.
252 */
253 if (rootspec == NULL && bootdv == NULL)
254 boothowto |= RB_ASKNAME;
255
256 top:
257 if (boothowto & RB_ASKNAME) {
258 device_t defdumpdv;
259
260 for (;;) {
261 printf("root device");
262 if (bootdv != NULL) {
263 printf(" (default %s", device_xname(bootdv));
264 if (DEV_USES_PARTITIONS(bootdv))
265 printf("%c", bootpartition + 'a');
266 printf(")");
267 }
268 printf(": ");
269 len = cngetsn(buf, sizeof(buf));
270 if (len == 0 && bootdv != NULL) {
271 strlcpy(buf, device_xname(bootdv), sizeof(buf));
272 len = strlen(buf);
273 }
274 if (len > 0 && buf[len - 1] == '*') {
275 buf[--len] = '\0';
276 dv = getdisk(buf, len, 1, &nrootdev, 0);
277 if (dv != NULL) {
278 rootdv = dv;
279 break;
280 }
281 }
282 dv = getdisk(buf, len, bootpartition, &nrootdev, 0);
283 if (dv != NULL) {
284 rootdv = dv;
285 break;
286 }
287 }
288
289 /*
290 * Set up the default dump device. If root is on
291 * a network device, there is no default dump
292 * device, since we don't support dumps to the
293 * network.
294 */
295 if (DEV_USES_PARTITIONS(rootdv) == 0)
296 defdumpdv = NULL;
297 else
298 defdumpdv = rootdv;
299
300 for (;;) {
301 printf("dump device");
302 if (defdumpdv != NULL) {
303 /*
304 * Note, we know it's a disk if we get here.
305 */
306 printf(" (default %sb)", device_xname(defdumpdv));
307 }
308 printf(": ");
309 len = cngetsn(buf, sizeof(buf));
310 if (len == 0) {
311 if (defdumpdv != NULL) {
312 ndumpdev = MAKEDISKDEV(major(nrootdev),
313 DISKUNIT(nrootdev), 1);
314 }
315 dumpdv = defdumpdv;
316 break;
317 }
318 if (len == 4 && strcmp(buf, "none") == 0) {
319 dumpdv = NULL;
320 break;
321 }
322 dv = getdisk(buf, len, 1, &ndumpdev, 1);
323 if (dv != NULL) {
324 dumpdv = dv;
325 break;
326 }
327 }
328
329 rootdev = nrootdev;
330 dumpdev = ndumpdev;
331
332 for (vops = LIST_FIRST(&vfs_list); vops != NULL;
333 vops = LIST_NEXT(vops, vfs_list)) {
334 if (vops->vfs_mountroot != NULL &&
335 strcmp(rootfstype, vops->vfs_name) == 0)
336 break;
337 }
338
339 if (vops == NULL) {
340 deffsname = "generic";
341 } else
342 deffsname = vops->vfs_name;
343
344 for (;;) {
345 printf("file system (default %s): ", deffsname);
346 len = cngetsn(buf, sizeof(buf));
347 if (len == 0) {
348 if (strcmp(deffsname, "generic") == 0)
349 rootfstype = ROOT_FSTYPE_ANY;
350 break;
351 }
352 if (len == 4 && strcmp(buf, "halt") == 0)
353 cpu_reboot(RB_HALT, NULL);
354 else if (len == 6 && strcmp(buf, "reboot") == 0)
355 cpu_reboot(0, NULL);
356 #if defined(DDB)
357 else if (len == 3 && strcmp(buf, "ddb") == 0) {
358 console_debugger();
359 }
360 #endif
361 else if (len == 7 && strcmp(buf, "generic") == 0) {
362 rootfstype = ROOT_FSTYPE_ANY;
363 break;
364 }
365 vops = vfs_getopsbyname(buf);
366 if (vops == NULL || vops->vfs_mountroot == NULL) {
367 printf("use one of: generic");
368 for (vops = LIST_FIRST(&vfs_list);
369 vops != NULL;
370 vops = LIST_NEXT(vops, vfs_list)) {
371 if (vops->vfs_mountroot != NULL)
372 printf(" %s", vops->vfs_name);
373 }
374 if (vops != NULL)
375 vfs_delref(vops);
376 #if defined(DDB)
377 printf(" ddb");
378 #endif
379 printf(" halt reboot\n");
380 } else {
381 /*
382 * XXX If *vops gets freed between here and
383 * the call to mountroot(), rootfstype will
384 * point to something unexpected. But in
385 * this case the system will fail anyway.
386 */
387 rootfstype = vops->vfs_name;
388 vfs_delref(vops);
389 break;
390 }
391 }
392
393 } else if (rootspec == NULL) {
394 /*
395 * Wildcarded root; use the boot device.
396 */
397 rootdv = bootdv;
398
399 if (bootdv)
400 majdev = devsw_name2blk(device_xname(bootdv), NULL, 0);
401 else
402 majdev = -1;
403 if (majdev >= 0) {
404 /*
405 * Root is on a disk. `bootpartition' is root,
406 * unless the device does not use partitions.
407 */
408 if (DEV_USES_PARTITIONS(bootdv))
409 rootdev = MAKEDISKDEV(majdev,
410 device_unit(bootdv),
411 bootpartition);
412 else
413 rootdev = makedev(majdev, device_unit(bootdv));
414 }
415 } else {
416
417 /*
418 * `root on <dev> ...'
419 */
420
421 /*
422 * If it's a network interface, we can bail out
423 * early.
424 */
425 dv = finddevice(rootspec);
426 if (dv != NULL && device_class(dv) == DV_IFNET) {
427 rootdv = dv;
428 goto haveroot;
429 }
430
431 if (rootdev == NODEV &&
432 device_class(dv) == DV_DISK && device_is_a(dv, "dk") &&
433 (majdev = devsw_name2blk(device_xname(dv), NULL, 0)) >= 0)
434 rootdev = makedev(majdev, device_unit(dv));
435
436 rootdevname = devsw_blk2name(major(rootdev));
437 if (rootdevname == NULL) {
438 printf("unknown device major 0x%llx\n",
439 (unsigned long long)rootdev);
440 boothowto |= RB_ASKNAME;
441 goto top;
442 }
443 memset(buf, 0, sizeof(buf));
444 snprintf(buf, sizeof(buf), "%s%llu", rootdevname,
445 (unsigned long long)DISKUNIT(rootdev));
446
447 rootdv = finddevice(buf);
448 if (rootdv == NULL) {
449 printf("device %s (0x%llx) not configured\n",
450 buf, (unsigned long long)rootdev);
451 boothowto |= RB_ASKNAME;
452 goto top;
453 }
454 }
455
456 haveroot:
457
458 root_device = rootdv;
459
460 switch (device_class(rootdv)) {
461 case DV_IFNET:
462 case DV_DISK:
463 aprint_normal("root on %s", device_xname(rootdv));
464 if (DEV_USES_PARTITIONS(rootdv))
465 aprint_normal("%c", (int)DISKPART(rootdev) + 'a');
466 break;
467
468 default:
469 printf("can't determine root device\n");
470 boothowto |= RB_ASKNAME;
471 goto top;
472 }
473
474 /*
475 * Now configure the dump device.
476 *
477 * If we haven't figured out the dump device, do so, with
478 * the following rules:
479 *
480 * (a) We already know dumpdv in the RB_ASKNAME case.
481 *
482 * (b) If dumpspec is set, try to use it. If the device
483 * is not available, punt.
484 *
485 * (c) If dumpspec is not set, the dump device is
486 * wildcarded or unspecified. If the root device
487 * is DV_IFNET, punt. Otherwise, use partition b
488 * of the root device.
489 */
490
491 if (boothowto & RB_ASKNAME) { /* (a) */
492 if (dumpdv == NULL)
493 goto nodumpdev;
494 } else if (dumpspec != NULL) { /* (b) */
495 if (strcmp(dumpspec, "none") == 0 || dumpdev == NODEV) {
496 /*
497 * Operator doesn't want a dump device.
498 * Or looks like they tried to pick a network
499 * device. Oops.
500 */
501 goto nodumpdev;
502 }
503
504 dumpdevname = devsw_blk2name(major(dumpdev));
505 if (dumpdevname == NULL)
506 goto nodumpdev;
507 memset(buf, 0, sizeof(buf));
508 snprintf(buf, sizeof(buf), "%s%llu", dumpdevname,
509 (unsigned long long)DISKUNIT(dumpdev));
510
511 dumpdv = finddevice(buf);
512 if (dumpdv == NULL) {
513 /*
514 * Device not configured.
515 */
516 goto nodumpdev;
517 }
518 } else { /* (c) */
519 if (DEV_USES_PARTITIONS(rootdv) == 0) {
520 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
521 dv != NULL;
522 dv = deviter_next(&di))
523 if (isswap(dv))
524 break;
525 deviter_release(&di);
526 if (dv == NULL)
527 goto nodumpdev;
528
529 majdev = devsw_name2blk(device_xname(dv), NULL, 0);
530 if (majdev < 0)
531 goto nodumpdev;
532 dumpdv = dv;
533 dumpdev = makedev(majdev, device_unit(dumpdv));
534 } else {
535 dumpdv = rootdv;
536 dumpdev = MAKEDISKDEV(major(rootdev),
537 device_unit(dumpdv), 1);
538 }
539 }
540
541 dumpcdev = devsw_blk2chr(dumpdev);
542 aprint_normal(" dumps on %s", device_xname(dumpdv));
543 if (DEV_USES_PARTITIONS(dumpdv))
544 aprint_normal("%c", (int)DISKPART(dumpdev) + 'a');
545 aprint_normal("\n");
546 return;
547
548 nodumpdev:
549 dumpdev = NODEV;
550 dumpcdev = NODEV;
551 aprint_normal("\n");
552 }
553
554 static device_t
555 finddevice(const char *name)
556 {
557 const char *wname;
558
559 if ((wname = getwedgename(name, strlen(name))) != NULL)
560 return dkwedge_find_by_wname(wname);
561
562 return device_find_by_xname(name);
563 }
564
565 static device_t
566 getdisk(char *str, int len, int defpart, dev_t *devp, int isdump)
567 {
568 device_t dv;
569 deviter_t di;
570
571 if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
572 printf("use one of:");
573 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
574 dv = deviter_next(&di)) {
575 if (DEV_USES_PARTITIONS(dv))
576 printf(" %s[a-%c]", device_xname(dv),
577 'a' + MAXPARTITIONS - 1);
578 else if (device_class(dv) == DV_DISK)
579 printf(" %s", device_xname(dv));
580 if (isdump == 0 && device_class(dv) == DV_IFNET)
581 printf(" %s", device_xname(dv));
582 }
583 deviter_release(&di);
584 dkwedge_print_wnames();
585 if (isdump)
586 printf(" none");
587 #if defined(DDB)
588 printf(" ddb");
589 #endif
590 printf(" halt reboot\n");
591 }
592 return dv;
593 }
594
595 static const char *
596 getwedgename(const char *name, int namelen)
597 {
598 const char *wpfx = "wedge:";
599 const int wpfxlen = strlen(wpfx);
600
601 if (namelen < wpfxlen || strncmp(name, wpfx, wpfxlen) != 0)
602 return NULL;
603
604 return name + wpfxlen;
605 }
606
607 static device_t
608 parsedisk(char *str, int len, int defpart, dev_t *devp)
609 {
610 device_t dv;
611 const char *wname;
612 char *cp, c;
613 int majdev, part;
614 if (len == 0)
615 return (NULL);
616
617 if (len == 4 && strcmp(str, "halt") == 0)
618 cpu_reboot(RB_HALT, NULL);
619 else if (len == 6 && strcmp(str, "reboot") == 0)
620 cpu_reboot(0, NULL);
621 #if defined(DDB)
622 else if (len == 3 && strcmp(str, "ddb") == 0)
623 console_debugger();
624 #endif
625
626 cp = str + len - 1;
627 c = *cp;
628
629 if ((wname = getwedgename(str, len)) != NULL) {
630 if ((dv = dkwedge_find_by_wname(wname)) == NULL)
631 return NULL;
632 part = defpart;
633 goto gotdisk;
634 } else if (c >= 'a' && c <= ('a' + MAXPARTITIONS - 1)) {
635 part = c - 'a';
636 *cp = '\0';
637 } else
638 part = defpart;
639
640 dv = finddevice(str);
641 if (dv != NULL) {
642 if (device_class(dv) == DV_DISK) {
643 gotdisk:
644 majdev = devsw_name2blk(device_xname(dv), NULL, 0);
645 if (majdev < 0)
646 panic("parsedisk");
647 if (DEV_USES_PARTITIONS(dv))
648 *devp = MAKEDISKDEV(majdev, device_unit(dv),
649 part);
650 else
651 *devp = makedev(majdev, device_unit(dv));
652 }
653
654 if (device_class(dv) == DV_IFNET)
655 *devp = NODEV;
656 }
657
658 *cp = c;
659 return (dv);
660 }
661
662 /*
663 * Return true if system call tracing is enabled for the specified process.
664 */
665 bool
666 trace_is_enabled(struct proc *p)
667 {
668 #ifdef SYSCALL_DEBUG
669 return (true);
670 #endif
671 #ifdef KTRACE
672 if (ISSET(p->p_traceflag, (KTRFAC_SYSCALL | KTRFAC_SYSRET)))
673 return (true);
674 #endif
675 #ifdef PTRACE
676 if (ISSET(p->p_slflag, PSL_SYSCALL))
677 return (true);
678 #endif
679
680 return (false);
681 }
682
683 /*
684 * Start trace of particular system call. If process is being traced,
685 * this routine is called by MD syscall dispatch code just before
686 * a system call is actually executed.
687 */
688 int
689 trace_enter(register_t code, const register_t *args, int narg)
690 {
691 #ifdef SYSCALL_DEBUG
692 scdebug_call(code, args);
693 #endif /* SYSCALL_DEBUG */
694
695 ktrsyscall(code, args, narg);
696
697 #ifdef PTRACE
698 if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
699 (PSL_SYSCALL|PSL_TRACED))
700 process_stoptrace();
701 #endif
702 return 0;
703 }
704
705 /*
706 * End trace of particular system call. If process is being traced,
707 * this routine is called by MD syscall dispatch code just after
708 * a system call finishes.
709 * MD caller guarantees the passed 'code' is within the supported
710 * system call number range for emulation the process runs under.
711 */
712 void
713 trace_exit(register_t code, register_t rval[], int error)
714 {
715 #ifdef SYSCALL_DEBUG
716 scdebug_ret(code, error, rval);
717 #endif /* SYSCALL_DEBUG */
718
719 ktrsysret(code, error, rval);
720
721 #ifdef PTRACE
722 if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
723 (PSL_SYSCALL|PSL_TRACED))
724 process_stoptrace();
725 #endif
726 }
727