Home | History | Annotate | Line # | Download | only in kern
kern_syscall.c revision 1.5.12.1
      1  1.5.12.1       mrg /*	$NetBSD: kern_syscall.c,v 1.5.12.1 2012/03/11 01:52:30 mrg Exp $	*/
      2       1.1     pooka 
      3       1.1     pooka /*-
      4       1.1     pooka  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5       1.1     pooka  * All rights reserved.
      6       1.1     pooka  *
      7       1.1     pooka  * This code is derived from software developed for The NetBSD Foundation
      8       1.1     pooka  * by Andrew Doran.
      9       1.1     pooka  *
     10       1.1     pooka  * Redistribution and use in source and binary forms, with or without
     11       1.1     pooka  * modification, are permitted provided that the following conditions
     12       1.1     pooka  * are met:
     13       1.1     pooka  * 1. Redistributions of source code must retain the above copyright
     14       1.1     pooka  *    notice, this list of conditions and the following disclaimer.
     15       1.1     pooka  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1     pooka  *    notice, this list of conditions and the following disclaimer in the
     17       1.1     pooka  *    documentation and/or other materials provided with the distribution.
     18       1.1     pooka  *
     19       1.1     pooka  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1     pooka  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1     pooka  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1     pooka  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1     pooka  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1     pooka  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1     pooka  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1     pooka  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1     pooka  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1     pooka  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1     pooka  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1     pooka  */
     31       1.1     pooka 
     32       1.1     pooka #include <sys/cdefs.h>
     33  1.5.12.1       mrg __KERNEL_RCSID(0, "$NetBSD: kern_syscall.c,v 1.5.12.1 2012/03/11 01:52:30 mrg Exp $");
     34       1.2     pooka 
     35       1.2     pooka #include "opt_modular.h"
     36       1.1     pooka 
     37       1.3     pooka /* XXX To get syscall prototypes. */
     38       1.3     pooka #define SYSVSHM
     39       1.3     pooka #define SYSVSEM
     40       1.3     pooka #define SYSVMSG
     41       1.3     pooka 
     42       1.1     pooka #include <sys/param.h>
     43       1.1     pooka #include <sys/module.h>
     44       1.4     pooka #include <sys/sched.h>
     45       1.1     pooka #include <sys/syscall.h>
     46       1.1     pooka #include <sys/syscallargs.h>
     47       1.1     pooka #include <sys/syscallvar.h>
     48       1.5  pgoyette #include <sys/systm.h>
     49       1.1     pooka #include <sys/xcall.h>
     50       1.1     pooka 
     51       1.1     pooka int
     52       1.1     pooka sys_nomodule(struct lwp *l, const void *v, register_t *retval)
     53       1.1     pooka {
     54       1.1     pooka #ifdef MODULAR
     55       1.1     pooka 	static struct {
     56       1.1     pooka 		u_int		al_code;
     57       1.1     pooka 		const char	*al_module;
     58       1.1     pooka 	} const autoload[] = {
     59       1.1     pooka 	    { SYS_aio_cancel, "aio" },
     60       1.1     pooka 	    { SYS_aio_error, "aio" },
     61       1.1     pooka 	    { SYS_aio_fsync, "aio" },
     62       1.1     pooka 	    { SYS_aio_read, "aio" },
     63       1.1     pooka 	    { SYS_aio_return, "aio" },
     64       1.1     pooka 	    { SYS___aio_suspend50, "aio" },
     65       1.1     pooka 	    { SYS_aio_write, "aio" },
     66       1.1     pooka 	    { SYS_lio_listio, "aio" },
     67       1.1     pooka 	    { SYS_mq_open, "mqueue" },
     68       1.1     pooka 	    { SYS_mq_close, "mqueue" },
     69       1.1     pooka 	    { SYS_mq_unlink, "mqueue" },
     70       1.1     pooka 	    { SYS_mq_getattr, "mqueue" },
     71       1.1     pooka 	    { SYS_mq_setattr, "mqueue" },
     72       1.1     pooka 	    { SYS_mq_notify, "mqueue" },
     73       1.1     pooka 	    { SYS_mq_send, "mqueue" },
     74       1.1     pooka 	    { SYS_mq_receive, "mqueue" },
     75       1.1     pooka 	    { SYS___mq_timedsend50, "mqueue" },
     76       1.1     pooka 	    { SYS___mq_timedreceive50, "mqueue" },
     77       1.1     pooka 	    { SYS_compat_43_fstat43, "compat" },
     78       1.1     pooka 	    { SYS_compat_43_lstat43, "compat" },
     79       1.1     pooka 	    { SYS_compat_43_oaccept, "compat" },
     80       1.1     pooka 	    { SYS_compat_43_ocreat, "compat" },
     81       1.1     pooka 	    { SYS_compat_43_oftruncate, "compat" },
     82       1.1     pooka 	    { SYS_compat_43_ogetdirentries, "compat" },
     83       1.1     pooka 	    { SYS_compat_43_ogetdtablesize, "compat" },
     84       1.1     pooka 	    { SYS_compat_43_ogethostid, "compat" },
     85       1.1     pooka 	    { SYS_compat_43_ogethostname, "compat" },
     86       1.1     pooka 	    { SYS_compat_43_ogetkerninfo, "compat" },
     87       1.1     pooka 	    { SYS_compat_43_ogetpagesize, "compat" },
     88       1.1     pooka 	    { SYS_compat_43_ogetpeername, "compat" },
     89       1.1     pooka 	    { SYS_compat_43_ogetrlimit, "compat" },
     90       1.1     pooka 	    { SYS_compat_43_ogetsockname, "compat" },
     91       1.1     pooka 	    { SYS_compat_43_okillpg, "compat" },
     92       1.1     pooka 	    { SYS_compat_43_olseek, "compat" },
     93       1.1     pooka 	    { SYS_compat_43_ommap, "compat" },
     94       1.1     pooka 	    { SYS_compat_43_oquota, "compat" },
     95       1.1     pooka 	    { SYS_compat_43_orecv, "compat" },
     96       1.1     pooka 	    { SYS_compat_43_orecvfrom, "compat" },
     97       1.1     pooka 	    { SYS_compat_43_orecvmsg, "compat" },
     98       1.1     pooka 	    { SYS_compat_43_osend, "compat" },
     99       1.1     pooka 	    { SYS_compat_43_osendmsg, "compat" },
    100       1.1     pooka 	    { SYS_compat_43_osethostid, "compat" },
    101       1.1     pooka 	    { SYS_compat_43_osethostname, "compat" },
    102       1.1     pooka 	    { SYS_compat_43_osetrlimit, "compat" },
    103       1.1     pooka 	    { SYS_compat_43_osigblock, "compat" },
    104       1.1     pooka 	    { SYS_compat_43_osigsetmask, "compat" },
    105       1.1     pooka 	    { SYS_compat_43_osigstack, "compat" },
    106       1.1     pooka 	    { SYS_compat_43_osigvec, "compat" },
    107       1.1     pooka 	    { SYS_compat_43_otruncate, "compat" },
    108       1.1     pooka 	    { SYS_compat_43_owait, "compat" },
    109       1.1     pooka 	    { SYS_compat_43_stat43, "compat" },
    110       1.1     pooka 	    { SYS_compat_09_ogetdomainname, "compat" },
    111       1.1     pooka 	    { SYS_compat_09_osetdomainname, "compat" },
    112       1.1     pooka 	    { SYS_compat_09_ouname, "compat" },
    113       1.1     pooka #ifndef _LP64
    114       1.1     pooka 	    { SYS_compat_10_omsgsys, "compat" },
    115       1.1     pooka 	    { SYS_compat_10_osemsys, "compat" },
    116       1.1     pooka 	    { SYS_compat_10_oshmsys, "compat" },
    117       1.1     pooka #endif
    118       1.1     pooka 	    { SYS_compat_12_fstat12, "compat" },
    119       1.1     pooka 	    { SYS_compat_12_getdirentries, "compat" },
    120       1.1     pooka 	    { SYS_compat_12_lstat12, "compat" },
    121       1.1     pooka 	    { SYS_compat_12_msync, "compat" },
    122       1.1     pooka 	    { SYS_compat_12_oreboot, "compat" },
    123       1.1     pooka 	    { SYS_compat_12_oswapon, "compat" },
    124       1.1     pooka 	    { SYS_compat_12_stat12, "compat" },
    125       1.1     pooka 	    { SYS_compat_13_sigaction13, "compat" },
    126       1.1     pooka 	    { SYS_compat_13_sigaltstack13, "compat" },
    127       1.1     pooka 	    { SYS_compat_13_sigpending13, "compat" },
    128       1.1     pooka 	    { SYS_compat_13_sigprocmask13, "compat" },
    129       1.1     pooka 	    { SYS_compat_13_sigreturn13, "compat" },
    130       1.1     pooka 	    { SYS_compat_13_sigsuspend13, "compat" },
    131       1.1     pooka 	    { SYS_compat_14___semctl, "compat" },
    132       1.1     pooka 	    { SYS_compat_14_msgctl, "compat" },
    133       1.1     pooka 	    { SYS_compat_14_shmctl, "compat" },
    134       1.1     pooka 	    { SYS_compat_16___sigaction14, "compat" },
    135       1.1     pooka 	    { SYS_compat_16___sigreturn14, "compat" },
    136       1.1     pooka 	    { SYS_compat_20_fhstatfs, "compat" },
    137       1.1     pooka 	    { SYS_compat_20_fstatfs, "compat" },
    138       1.1     pooka 	    { SYS_compat_20_getfsstat, "compat" },
    139       1.1     pooka 	    { SYS_compat_20_statfs, "compat" },
    140       1.1     pooka 	    { SYS_compat_30___fhstat30, "compat" },
    141       1.1     pooka 	    { SYS_compat_30___fstat13, "compat" },
    142       1.1     pooka 	    { SYS_compat_30___lstat13, "compat" },
    143       1.1     pooka 	    { SYS_compat_30___stat13, "compat" },
    144       1.1     pooka 	    { SYS_compat_30_fhopen, "compat" },
    145       1.1     pooka 	    { SYS_compat_30_fhstat, "compat" },
    146       1.1     pooka 	    { SYS_compat_30_fhstatvfs1, "compat" },
    147       1.1     pooka 	    { SYS_compat_30_getdents, "compat" },
    148       1.1     pooka 	    { SYS_compat_30_getfh, "compat" },
    149       1.1     pooka 	    { SYS_compat_30_socket, "compat" },
    150       1.1     pooka 	    { SYS_compat_40_mount, "compat" },
    151       1.1     pooka 	    { SYS_compat_50_wait4, "compat" },
    152       1.1     pooka 	    { SYS_compat_50_mknod, "compat" },
    153       1.1     pooka 	    { SYS_compat_50_setitimer, "compat" },
    154       1.1     pooka 	    { SYS_compat_50_getitimer, "compat" },
    155       1.1     pooka 	    { SYS_compat_50_select, "compat" },
    156       1.1     pooka 	    { SYS_compat_50_gettimeofday, "compat" },
    157       1.1     pooka 	    { SYS_compat_50_getrusage, "compat" },
    158       1.1     pooka 	    { SYS_compat_50_settimeofday, "compat" },
    159       1.1     pooka 	    { SYS_compat_50_utimes, "compat" },
    160       1.1     pooka 	    { SYS_compat_50_adjtime, "compat" },
    161       1.1     pooka 	    { SYS_compat_50_lfs_segwait, "compat" },
    162       1.1     pooka 	    { SYS_compat_50_futimes, "compat" },
    163       1.1     pooka 	    { SYS_compat_50_clock_gettime, "compat" },
    164       1.1     pooka 	    { SYS_compat_50_clock_settime, "compat" },
    165       1.1     pooka 	    { SYS_compat_50_clock_getres, "compat" },
    166       1.1     pooka 	    { SYS_compat_50_timer_settime, "compat" },
    167       1.1     pooka 	    { SYS_compat_50_timer_gettime, "compat" },
    168       1.1     pooka 	    { SYS_compat_50_nanosleep, "compat" },
    169       1.1     pooka 	    { SYS_compat_50___sigtimedwait, "compat" },
    170       1.1     pooka 	    { SYS_compat_50_mq_timedsend, "compat" },
    171       1.1     pooka 	    { SYS_compat_50_mq_timedreceive, "compat" },
    172       1.1     pooka 	    { SYS_compat_50_lutimes, "compat" },
    173       1.1     pooka 	    { SYS_compat_50_____semctl13, "compat" },
    174       1.1     pooka 	    { SYS_compat_50___msgctl13, "compat" },
    175       1.1     pooka 	    { SYS_compat_50___shmctl13, "compat" },
    176       1.1     pooka 	    { SYS_compat_50__lwp_park, "compat" },
    177       1.1     pooka 	    { SYS_compat_50_kevent, "compat" },
    178       1.1     pooka 	    { SYS_compat_50_pselect, "compat" },
    179       1.1     pooka 	    { SYS_compat_50_pollts, "compat" },
    180       1.1     pooka 	    { SYS_compat_50___stat30, "compat" },
    181       1.1     pooka 	    { SYS_compat_50___fstat30, "compat" },
    182       1.1     pooka 	    { SYS_compat_50___lstat30, "compat" },
    183       1.1     pooka 	    { SYS_compat_50___ntp_gettime30, "compat" },
    184       1.1     pooka 	    { SYS_compat_50___fhstat40, "compat" },
    185       1.1     pooka 	    { SYS_compat_50_aio_suspend, "compat" },
    186       1.1     pooka 	    { SYS__ksem_init, "ksem" },
    187       1.1     pooka 	    { SYS__ksem_open, "ksem" },
    188       1.1     pooka 	    { SYS__ksem_unlink, "ksem" },
    189       1.1     pooka 	    { SYS__ksem_close, "ksem" },
    190       1.1     pooka 	    { SYS__ksem_post, "ksem" },
    191       1.1     pooka 	    { SYS__ksem_wait, "ksem" },
    192       1.1     pooka 	    { SYS__ksem_trywait, "ksem" },
    193       1.1     pooka 	    { SYS__ksem_getvalue, "ksem" },
    194       1.1     pooka 	    { SYS__ksem_destroy, "ksem" },
    195  1.5.12.1       mrg 	    { SYS__ksem_timedwait, "ksem" },
    196       1.1     pooka 	    { SYS_nfssvc, "nfsserver" },
    197       1.1     pooka 	};
    198       1.1     pooka 	const struct sysent *sy;
    199       1.1     pooka 	const struct emul *em;
    200       1.1     pooka 	int code, i;
    201       1.1     pooka 
    202       1.1     pooka 	/*
    203       1.1     pooka 	 * Restart the syscall if we interrupted a module unload that
    204       1.5  pgoyette 	 * failed.  Acquiring kernconfig_lock delays us until any unload
    205       1.1     pooka 	 * has been completed or rolled back.
    206       1.1     pooka 	 */
    207       1.5  pgoyette 	kernconfig_lock();
    208       1.1     pooka 	sy = l->l_sysent;
    209       1.1     pooka 	if (sy->sy_call != sys_nomodule) {
    210       1.5  pgoyette 		kernconfig_unlock();
    211       1.1     pooka 		return ERESTART;
    212       1.1     pooka 	}
    213       1.1     pooka 	/*
    214       1.1     pooka 	 * Try to autoload a module to satisfy the request.  If it
    215       1.1     pooka 	 * works, retry the request.
    216       1.1     pooka 	 */
    217       1.1     pooka 	em = l->l_proc->p_emul;
    218       1.1     pooka 	if (em == &emul_netbsd) {
    219       1.1     pooka 		code = sy - em->e_sysent;
    220       1.1     pooka 		for (i = 0; i < __arraycount(autoload); i++) {
    221       1.1     pooka 			if (autoload[i].al_code != code) {
    222       1.1     pooka 				continue;
    223       1.1     pooka 			}
    224       1.1     pooka 			if (module_autoload(autoload[i].al_module,
    225       1.1     pooka 			    MODULE_CLASS_ANY) != 0 ||
    226       1.1     pooka 			    sy->sy_call == sys_nomodule) {
    227       1.1     pooka 			    	break;
    228       1.1     pooka 			}
    229       1.5  pgoyette 			kernconfig_unlock();
    230       1.1     pooka 			return ERESTART;
    231       1.1     pooka 		}
    232       1.1     pooka 	}
    233       1.5  pgoyette 	kernconfig_unlock();
    234       1.1     pooka #endif	/* MODULAR */
    235       1.1     pooka 
    236       1.1     pooka 	return sys_nosys(l, v, retval);
    237       1.1     pooka }
    238       1.1     pooka 
    239       1.1     pooka int
    240       1.1     pooka syscall_establish(const struct emul *em, const struct syscall_package *sp)
    241       1.1     pooka {
    242       1.1     pooka 	struct sysent *sy;
    243       1.1     pooka 	int i;
    244       1.1     pooka 
    245       1.5  pgoyette 	KASSERT(kernconfig_is_held());
    246       1.1     pooka 
    247       1.1     pooka 	if (em == NULL) {
    248       1.1     pooka 		em = &emul_netbsd;
    249       1.1     pooka 	}
    250       1.1     pooka 	sy = em->e_sysent;
    251       1.1     pooka 
    252       1.1     pooka 	/*
    253       1.1     pooka 	 * Ensure that all preconditions are valid, since this is
    254       1.1     pooka 	 * an all or nothing deal.  Once a system call is entered,
    255       1.1     pooka 	 * it can become busy and we could be unable to remove it
    256       1.1     pooka 	 * on error.
    257       1.1     pooka 	 */
    258       1.1     pooka 	for (i = 0; sp[i].sp_call != NULL; i++) {
    259       1.1     pooka 		if (sy[sp[i].sp_code].sy_call != sys_nomodule) {
    260       1.1     pooka #ifdef DIAGNOSTIC
    261       1.1     pooka 			printf("syscall %d is busy\n", sp[i].sp_code);
    262       1.1     pooka #endif
    263       1.1     pooka 			return EBUSY;
    264       1.1     pooka 		}
    265       1.1     pooka 	}
    266       1.1     pooka 	/* Everything looks good, patch them in. */
    267       1.1     pooka 	for (i = 0; sp[i].sp_call != NULL; i++) {
    268       1.1     pooka 		sy[sp[i].sp_code].sy_call = sp[i].sp_call;
    269       1.1     pooka 	}
    270       1.1     pooka 
    271       1.1     pooka 	return 0;
    272       1.1     pooka }
    273       1.1     pooka 
    274       1.1     pooka int
    275       1.1     pooka syscall_disestablish(const struct emul *em, const struct syscall_package *sp)
    276       1.1     pooka {
    277       1.1     pooka 	struct sysent *sy;
    278       1.1     pooka 	uint64_t where;
    279       1.1     pooka 	lwp_t *l;
    280       1.1     pooka 	int i;
    281       1.1     pooka 
    282       1.5  pgoyette 	KASSERT(kernconfig_is_held());
    283       1.1     pooka 
    284       1.1     pooka 	if (em == NULL) {
    285       1.1     pooka 		em = &emul_netbsd;
    286       1.1     pooka 	}
    287       1.1     pooka 	sy = em->e_sysent;
    288       1.1     pooka 
    289       1.1     pooka 	/*
    290       1.1     pooka 	 * First, patch the system calls to sys_nomodule to gate further
    291       1.1     pooka 	 * activity.
    292       1.1     pooka 	 */
    293       1.1     pooka 	for (i = 0; sp[i].sp_call != NULL; i++) {
    294       1.1     pooka 		KASSERT(sy[sp[i].sp_code].sy_call == sp[i].sp_call);
    295       1.1     pooka 		sy[sp[i].sp_code].sy_call = sys_nomodule;
    296       1.1     pooka 	}
    297       1.1     pooka 
    298       1.1     pooka 	/*
    299       1.1     pooka 	 * Run a cross call to cycle through all CPUs.  This does two
    300       1.1     pooka 	 * things: lock activity provides a barrier and makes our update
    301       1.1     pooka 	 * of sy_call visible to all CPUs, and upon return we can be sure
    302       1.1     pooka 	 * that we see pertinent values of l_sysent posted by remote CPUs.
    303       1.1     pooka 	 */
    304       1.1     pooka 	where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
    305       1.1     pooka 	xc_wait(where);
    306       1.1     pooka 
    307       1.1     pooka 	/*
    308       1.1     pooka 	 * Now it's safe to check l_sysent.  Run through all LWPs and see
    309       1.1     pooka 	 * if anyone is still using the system call.
    310       1.1     pooka 	 */
    311       1.1     pooka 	for (i = 0; sp[i].sp_call != NULL; i++) {
    312       1.1     pooka 		mutex_enter(proc_lock);
    313       1.1     pooka 		LIST_FOREACH(l, &alllwp, l_list) {
    314       1.1     pooka 			if (l->l_sysent == &sy[sp[i].sp_code]) {
    315       1.1     pooka 				break;
    316       1.1     pooka 			}
    317       1.1     pooka 		}
    318       1.1     pooka 		mutex_exit(proc_lock);
    319       1.1     pooka 		if (l == NULL) {
    320       1.1     pooka 			continue;
    321       1.1     pooka 		}
    322       1.1     pooka 		/*
    323       1.1     pooka 		 * We lose: one or more calls are still in use.  Put back
    324       1.1     pooka 		 * the old entrypoints and act like nothing happened.
    325       1.5  pgoyette 		 * When we drop kernconfig_lock, any system calls held in
    326       1.1     pooka 		 * sys_nomodule() will be restarted.
    327       1.1     pooka 		 */
    328       1.1     pooka 		for (i = 0; sp[i].sp_call != NULL; i++) {
    329       1.1     pooka 			sy[sp[i].sp_code].sy_call = sp[i].sp_call;
    330       1.1     pooka 		}
    331       1.1     pooka 		return EBUSY;
    332       1.1     pooka 	}
    333       1.1     pooka 
    334       1.1     pooka 	return 0;
    335       1.1     pooka }
    336