diff options
Diffstat (limited to 'sys/i386/linux')
-rw-r--r-- | sys/i386/linux/imgact_linux.c | 15 | ||||
-rw-r--r-- | sys/i386/linux/linux.h | 62 | ||||
-rw-r--r-- | sys/i386/linux/linux_dummy.c | 105 | ||||
-rw-r--r-- | sys/i386/linux/linux_file.c | 397 | ||||
-rw-r--r-- | sys/i386/linux/linux_genassym.c | 22 | ||||
-rw-r--r-- | sys/i386/linux/linux_ioctl.c | 47 | ||||
-rw-r--r-- | sys/i386/linux/linux_ipc.c | 54 | ||||
-rw-r--r-- | sys/i386/linux/linux_locore.s | 26 | ||||
-rw-r--r-- | sys/i386/linux/linux_misc.c | 433 | ||||
-rw-r--r-- | sys/i386/linux/linux_proto.h | 465 | ||||
-rw-r--r-- | sys/i386/linux/linux_signal.c | 210 | ||||
-rw-r--r-- | sys/i386/linux/linux_socket.c | 9 | ||||
-rw-r--r-- | sys/i386/linux/linux_stats.c | 161 | ||||
-rw-r--r-- | sys/i386/linux/linux_syscall.h | 151 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysent.c | 386 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysvec.c | 358 | ||||
-rw-r--r-- | sys/i386/linux/linux_util.c | 179 | ||||
-rw-r--r-- | sys/i386/linux/linux_util.h (renamed from sys/i386/linux/linux_generic.c) | 81 | ||||
-rw-r--r-- | sys/i386/linux/sysproto.h | 210 |
19 files changed, 2462 insertions, 909 deletions
diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 4319de2..9d6906d 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -28,7 +28,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: imgact_linux.c,v 1.7 1996/01/19 22:59:23 dyson Exp $ + * $Id: imgact_linux.c,v 1.8 1996/02/16 18:40:48 peter Exp $ */ #include <sys/param.h> @@ -50,7 +50,8 @@ #include <vm/vm_prot.h> #include <vm/vm_extern.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux.h> +#include <i386/linux/linux_proto.h> extern int exec_linux_imgact __P((struct image_params *iparams)); @@ -83,6 +84,9 @@ exec_linux_imgact(imgp) return (-1); } bss_size = round_page(a_out->a_bss); +#ifdef DEBUG + printf("imgact: text: %08x, data: %08x, bss: %08x\n", a_out->a_text, a_out->a_data, bss_size); +#endif /* * Check various fields in header for validity/bounds. @@ -173,6 +177,9 @@ exec_linux_imgact(imgp) if (error) return (error); +#ifdef DEBUG + printf("imgact: startaddr=%08x, length=%08x\n", vmaddr, a_out->a_text + a_out->a_data); +#endif /* * allow read/write of data */ @@ -193,6 +200,10 @@ exec_linux_imgact(imgp) bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (error); +#ifdef DEBUG + printf("imgact: bssaddr=%08x, length=%08x\n", vmaddr, bss_size); +#endif + } /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index c0fbc0a..f6bab97 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux.h,v 1.3 1995/12/29 22:12:10 sos Exp $ + * $Id: linux.h,v 1.4 1996/01/30 22:56:29 mpp Exp $ */ #ifndef _I386_LINUX_LINUX_H_ @@ -55,9 +55,56 @@ typedef struct { } linux_sigaction_t; typedef int linux_key_t; +/* + * The Linux sigcontext, pretty much a standard 386 trapframe. + */ + +struct linux_sigcontext { + int sc_gs; + int sc_fs; + int sc_es; + int sc_ds; + int sc_edi; + int sc_esi; + int sc_ebp; + int sc_esp; + int sc_ebx; + int sc_edx; + int sc_ecx; + int sc_eax; + int sc_trapno; + int sc_err; + int sc_eip; + int sc_cs; + int sc_eflags; + int sc_esp_at_signal; + int sc_ss; + int sc_387; + int sc_mask; + int sc_cr2; +}; + +/* + * We make the stack look like Linux expects it when calling a signal + * handler, but use the BSD way of calling the handler and sigreturn(). + * This means that we need to pass the pointer to the handler too. + * It is appended to the frame to not interfere with the rest of it. + */ + +struct linux_sigframe { + int sf_sig; + struct linux_sigcontext sf_sc; + sig_t sf_handler; +}; + extern int bsd_to_linux_signal[]; extern int linux_to_bsd_signal[]; +extern struct sysentvec linux_sysvec; + +struct image_params; +int linux_fixup __P((int **stack_base, struct image_params *iparams)); + /* misc defines */ #define LINUX_NAME_MAX 255 @@ -421,9 +468,14 @@ extern int linux_to_bsd_signal[]; #define LINUX_SNDCTL_DSP_GETISPACE 0x500D #define LINUX_SNDCTL_DSP_NONBLOCK 0x500E -#ifdef KERNEL -caddr_t ua_alloc_init __P((int len)); -caddr_t ua_alloc __P((int len)); -#endif +/* Socket system defines */ +#define LINUX_SIOCGIFCONF 0x8912 +#define LINUX_SIOCGIFFLAGS 0x8913 +#define LINUX_SIOCGIFADDR 0x8915 +#define LINUX_SIOCGIFDSTADDR 0x8917 +#define LINUX_SIOCGIFBRDADDR 0x8919 +#define LINUX_SIOCGIFNETMASK 0x891b +#define LINUX_SIOCADDMULTI 0x8931 +#define LINUX_SIOCDELMULTI 0x8932 #endif /* !_I386_LINUX_LINUX_H_ */ diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c index 6c55613..2fcab46 100644 --- a/sys/i386/linux/linux_dummy.c +++ b/sys/i386/linux/linux_dummy.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_dummy.c,v 1.1 1995/06/25 17:32:33 sos Exp $ + * $Id: linux_dummy.c,v 1.2 1995/11/22 07:43:44 bde Exp $ */ #include <sys/param.h> @@ -34,283 +34,264 @@ #include <sys/proc.h> #include <sys/resourcevar.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux.h> +#include <i386/linux/linux_proto.h> int -linux_setup(struct proc *p, void *args, int *retval) +linux_setup(struct proc *p, struct linux_setup_args *args, int *retval) { printf("Linux-emul(%d): setup() not supported\n", p->p_pid); return ENOSYS; } int -linux_break(struct proc *p, void *args, int *retval) +linux_break(struct proc *p, struct linux_break_args *args, int *retval) { printf("Linux-emul(%d): break() not supported\n", p->p_pid); return ENOSYS; } int -linux_stat(struct proc *p, void *args, int *retval) +linux_stat(struct proc *p, struct linux_stat_args *args, int *retval) { printf("Linux-emul(%d): stat() not supported\n", p->p_pid); return ENOSYS; } int -linux_fstat(struct proc *p, void *args, int *retval) +linux_fstat(struct proc *p, struct linux_fstat_args *args, int *retval) { printf("Linux-emul(%d): fstat() not supported\n", p->p_pid); return ENOSYS; } int -linux_mount(struct proc *p, void *args, int *retval) +linux_mount(struct proc *p, struct linux_mount_args *args, int *retval) { printf("Linux-emul(%d): mount() not supported\n", p->p_pid); return ENOSYS; } int -linux_umount(struct proc *p, void *args, int *retval) +linux_umount(struct proc *p, struct linux_umount_args *args, int *retval) { printf("Linux-emul(%d): umount() not supported\n", p->p_pid); return ENOSYS; } int -linux_stime(struct proc *p, void *args, int *retval) +linux_stime(struct proc *p, struct linux_stime_args *args, int *retval) { printf("Linux-emul(%d): stime() not supported\n", p->p_pid); return ENOSYS; } int -linux_ptrace(struct proc *p, void *args, int *retval) +linux_ptrace(struct proc *p, struct linux_ptrace_args *args, int *retval) { printf("Linux-emul(%d): ptrace() not supported\n", p->p_pid); return ENOSYS; } int -linux_pause(struct proc *p, void *args, int *retval) -{ - printf("Linux-emul(%d): pause() not supported\n", p->p_pid); - return ENOSYS; -} - -int -linux_stty(struct proc *p, void *args, int *retval) +linux_stty(struct proc *p, struct linux_stty_args *args, int *retval) { printf("Linux-emul(%d): stty() not supported\n", p->p_pid); return ENOSYS; } int -linux_gtty(struct proc *p, void *args, int *retval) +linux_gtty(struct proc *p, struct linux_gtty_args *args, int *retval) { printf("Linux-emul(%d): gtty() not supported\n", p->p_pid); return ENOSYS; } int -linux_nice(struct proc *p, void *args, int *retval) +linux_nice(struct proc *p, struct linux_nice_args *args, int *retval) { printf("Linux-emul(%d): nice() not supported\n", p->p_pid); return ENOSYS; } int -linux_ftime(struct proc *p, void *args, int *retval) +linux_ftime(struct proc *p, struct linux_ftime_args *args, int *retval) { printf("Linux-emul(%d): ftime() not supported\n", p->p_pid); return ENOSYS; } int -linux_prof(struct proc *p, void *args, int *retval) +linux_prof(struct proc *p, struct linux_prof_args *args, int *retval) { printf("Linux-emul(%d): prof() not supported\n", p->p_pid); return ENOSYS; } int -linux_signal(struct proc *p, void *args, int *retval) -{ - printf("Linux-emul(%d): signal() not supported\n", p->p_pid); - return ENOSYS; -} - -int -linux_phys(struct proc *p, void *args, int *retval) +linux_phys(struct proc *p, struct linux_phys_args *args, int *retval) { printf("Linux-emul(%d): phys() not supported\n", p->p_pid); return ENOSYS; } int -linux_lock(struct proc *p, void *args, int *retval) +linux_lock(struct proc *p, struct linux_lock_args *args, int *retval) { printf("Linux-emul(%d): lock() not supported\n", p->p_pid); return ENOSYS; } int -linux_mpx(struct proc *p, void *args, int *retval) +linux_mpx(struct proc *p, struct linux_mpx_args *args, int *retval) { printf("Linux-emul(%d): mpx() not supported\n", p->p_pid); return ENOSYS; } int -linux_ulimit(struct proc *p, void *args, int *retval) +linux_ulimit(struct proc *p, struct linux_ulimit_args *args, int *retval) { printf("Linux-emul(%d): ulimit() not supported\n", p->p_pid); return ENOSYS; } int -linux_olduname(struct proc *p, void *args, int *retval) +linux_olduname(struct proc *p, struct linux_olduname_args *args, int *retval) { printf("Linux-emul(%d): olduname() not supported\n", p->p_pid); return ENOSYS; } int -linux_ustat(struct proc *p, void *args, int *retval) +linux_ustat(struct proc *p, struct linux_ustat_args *args, int *retval) { printf("Linux-emul(%d): ustat() not supported\n", p->p_pid); return ENOSYS; } int -linux_ioperm(struct proc *p, void *args, int *retval) +linux_ioperm(struct proc *p, struct linux_ioperm_args *args, int *retval) { printf("Linux-emul(%d): ioperm() not supported\n", p->p_pid); return 0; /* EINVAL SOS XXX */ } int -linux_syslog(struct proc *p, void *args, int *retval) +linux_ksyslog(struct proc *p, struct linux_ksyslog_args *args, int *retval) { - printf("Linux-emul(%d): syslog() not supported (BSD sigreturn)\n",p->p_pid); - return sigreturn(p, args, retval); + printf("Linux-emul(%d): ksyslog(%x) not supported\n", + p->p_pid, args->what); + return ENOSYS; /* EPERM - Peter - it's a root-only thing */ } int -linux_iopl(struct proc *p, void *args, int *retval) +linux_iopl(struct proc *p, struct linux_iopl_args *args, int *retval) { printf("Linux-emul(%d): iopl() not supported\n", p->p_pid); return ENOSYS; } int -linux_vhangup(struct proc *p, void *args, int *retval) +linux_vhangup(struct proc *p, struct linux_vhangup_args *args, int *retval) { printf("Linux-emul(%d): vhangup() not supported\n", p->p_pid); return ENOSYS; } int -linux_idle(struct proc *p, void *args, int *retval) +linux_idle(struct proc *p, struct linux_idle_args *args, int *retval) { printf("Linux-emul(%d): idle() not supported\n", p->p_pid); return ENOSYS; } int -linux_vm86(struct proc *p, void *args, int *retval) +linux_vm86(struct proc *p, struct linux_vm86_args *args, int *retval) { printf("Linux-emul(%d): vm86() not supported\n", p->p_pid); return ENOSYS; } int -linux_swapoff(struct proc *p, void *args, int *retval) +linux_swapoff(struct proc *p, struct linux_swapoff_args *args, int *retval) { printf("Linux-emul(%d): swapoff() not supported\n", p->p_pid); return ENOSYS; } int -linux_sysinfo(struct proc *p, void *args, int *retval) +linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args, int *retval) { printf("Linux-emul(%d): sysinfo() not supported\n", p->p_pid); return ENOSYS; } int -linux_sigreturn(struct proc *p, void *args, int *retval) -{ - printf("Linux-emul(%d): sigreturn() not supported\n", p->p_pid); - return ENOSYS; -} - -int -linux_clone(struct proc *p, void *args, int *retval) +linux_clone(struct proc *p, struct linux_clone_args *args, int *retval) { printf("Linux-emul(%d): clone() not supported\n", p->p_pid); return ENOSYS; } int -linux_uname(struct proc *p, void *args, int *retval) +linux_uname(struct proc *p, struct linux_uname_args *args, int *retval) { printf("Linux-emul(%d): uname() not supported\n", p->p_pid); return ENOSYS; } int -linux_modify_ldt(struct proc *p, void *args, int *retval) +linux_modify_ldt(struct proc *p, struct linux_modify_ldt_args *args, int *retval) { printf("Linux-emul(%d): modify_ldt() not supported\n", p->p_pid); return ENOSYS; } int -linux_adjtimex(struct proc *p, void *args, int *retval) +linux_adjtimex(struct proc *p, struct linux_adjtimex_args *args, int *retval) { printf("Linux-emul(%d): adjtimex() not supported\n", p->p_pid); return ENOSYS; } int -linux_create_module(struct proc *p, void *args, int *retval) +linux_create_module(struct proc *p, struct linux_create_module_args *args, int *retval) { printf("Linux-emul(%d): create_module() not supported\n", p->p_pid); return ENOSYS; } int -linux_init_module(struct proc *p, void *args, int *retval) +linux_init_module(struct proc *p, struct linux_init_module_args *args, int *retval) { printf("Linux-emul(%d): init_module() not supported\n", p->p_pid); return ENOSYS; } int -linux_delete_module(struct proc *p, void *args, int *retval) +linux_delete_module(struct proc *p, struct linux_delete_module_args *args, int *retval) { printf("Linux-emul(%d): delete_module() not supported\n", p->p_pid); return ENOSYS; } int -linux_get_kernel_syms(struct proc *p, void *args, int *retval) +linux_get_kernel_syms(struct proc *p, struct linux_get_kernel_syms_args *args, int *retval) { printf("Linux-emul(%d): get_kernel_syms() not supported\n", p->p_pid); return ENOSYS; } int -linux_quotactl(struct proc *p, void *args, int *retval) +linux_quotactl(struct proc *p, struct linux_quotactl_args *args, int *retval) { printf("Linux-emul(%d): quotactl() not supported\n", p->p_pid); return ENOSYS; } int -linux_bdflush(struct proc *p, void *args, int *retval) +linux_bdflush(struct proc *p, struct linux_bdflush_args *args, int *retval) { printf("Linux-emul(%d): bdflush() not supported\n", p->p_pid); return ENOSYS; diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c index 0918f22..93932df 100644 --- a/sys/i386/linux/linux_file.c +++ b/sys/i386/linux/linux_file.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_file.c,v 1.4 1995/11/22 07:43:45 bde Exp $ + * $Id: linux_file.c,v 1.5 1995/12/15 03:06:50 peter Exp $ */ #include <sys/param.h> @@ -41,16 +41,15 @@ #include <sys/malloc.h> #include <sys/exec.h> #include <sys/dirent.h> +#include <sys/sysproto.h> +#include <sys/conf.h> +#include <sys/tty.h> #include <ufs/ufs/dir.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> - -struct linux_creat_args { - char *path; - int mode; -}; +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> int linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) @@ -60,6 +59,10 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) int flags; int mode; } */ bsd_open_args; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTCREAT(p, &sg, args->path); #ifdef DEBUG printf("Linux-emul(%d): creat(%s, %d)\n", @@ -71,12 +74,6 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) return open(p, &bsd_open_args, retval); } -struct linux_open_args { - char *path; - int flags; - int mode; -}; - int linux_open(struct proc *p, struct linux_open_args *args, int *retval) { @@ -86,7 +83,15 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval) int mode; } */ bsd_open_args; int error; + caddr_t sg; + + sg = stackgap_init(); + if (args->flags & LINUX_O_CREAT) + CHECKALTCREAT(p, &sg, args->path); + else + CHECKALTEXIST(p, &sg, args->path); + #ifdef DEBUG printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", p->p_pid, args->path, args->flags, args->mode); @@ -128,6 +133,10 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval) if (fp->f_type == DTYPE_VNODE) (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); } +#ifdef DEBUG + printf("Linux-emul(%d): open returns error %d\n", + p->p_pid, error); +#endif return error; } @@ -179,12 +188,6 @@ bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; } -struct linux_fcntl_args { - int fd; - int cmd; - int arg; -}; - int linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval) { @@ -195,8 +198,19 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval) int arg; } */ fcntl_args; struct linux_flock linux_flock; - struct flock *bsd_flock = - (struct flock *)ua_alloc_init(sizeof(struct flock)); + struct flock *bsd_flock; + struct filedesc *fdp; + struct file *fp; + struct vnode *vp; + struct vattr va; + long pgid; + struct pgrp *pgrp; + struct tty *tp, *(*d_tty) __P((dev_t)); + caddr_t sg; + + sg = stackgap_init(); + bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); + d_tty = NULL; #ifdef DEBUG printf("Linux-emul(%d): fcntl(%d, %08x, *)\n", @@ -269,22 +283,51 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval) return fcntl(p, &fcntl_args, retval); case LINUX_F_SETOWN: - fcntl_args.cmd = F_SETOWN; - return fcntl(p, &fcntl_args, retval); - case LINUX_F_GETOWN: - fcntl_args.cmd = F_GETOWN; - return fcntl(p, &fcntl_args, retval); + /* + * We need to route around the normal fcntl() for these calls, + * since it uses TIOC{G,S}PGRP, which is too restrictive for + * Linux F_{G,S}ETOWN semantics. For sockets, this problem + * does not exist. + */ + fdp = p->p_fd; + if ((u_int)args->fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[args->fd]) == NULL) + return EBADF; + if (fp->f_type == DTYPE_SOCKET) { + fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; + return fcntl(p, &fcntl_args, retval); + } + vp = (struct vnode *)fp->f_data; + if (vp->v_type != VCHR) + return EINVAL; + if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) + return error; + + d_tty = cdevsw[major(va.va_rdev)]->d_devtotty; + if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) + return EINVAL; + if (args->cmd == LINUX_F_GETOWN) { + retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; + return 0; + } + if ((long)args->arg <= 0) { + pgid = -(long)args->arg; + } else { + struct proc *p1 = pfind((long)args->arg); + if (p1 == 0) + return (ESRCH); + pgid = (long)p1->p_pgrp->pg_id; + } + pgrp = pgfind(pgid); + if (pgrp == NULL || pgrp->pg_session != p->p_session) + return EPERM; + tp->t_pgrp = pgrp; + return 0; } return EINVAL; } -struct linux_lseek_args { - int fdes; - unsigned long off; - int whence; -}; - int linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval) { @@ -308,6 +351,34 @@ linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval) return error; } +int +linux_llseek(struct proc *p, struct linux_llseek_args *args, int *retval) +{ + struct lseek_args bsd_args; + int error; + off_t off; + +#ifdef DEBUG + printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n", + p->p_pid, args->fd, args->ohigh, args->olow, args->whence); +#endif + off = (args->olow) | (((off_t) args->ohigh) << 32); + + bsd_args.fd = args->fd; + bsd_args.offset = off; + bsd_args.whence = args->whence; + + if ((error = lseek(p, &bsd_args, retval))) + return error; + + if ((error = copyout(retval, (caddr_t)args->res, sizeof (off_t)))) + return error; + + retval[0] = 0; + return 0; +} + + struct linux_dirent { long dino; linux_off_t doff; @@ -318,15 +389,20 @@ struct linux_dirent { #define LINUX_RECLEN(de,namlen) \ ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) -struct linux_readdir_args { - int fd; - struct linux_dirent *dent; - unsigned int count; -}; - int linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval) { + struct linux_getdents_args lda; + + lda.fd = args->fd; + lda.dent = args->dent; + lda.count = 1; + return linux_getdents(p, &lda, retval); +} + +int +linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval) +{ register struct dirent *bdp; struct vnode *vp; caddr_t inp, buf; /* BSD-format */ @@ -342,12 +418,12 @@ linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval) int buflen, error, eofflag, nbytes, justone, blockoff; #ifdef DEBUG - printf("Linux-emul(%d): readdir(%d, *, %d)\n", + printf("Linux-emul(%d): getdents(%d, *, %d)\n", p->p_pid, args->fd, args->count); #endif if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { return (error); -} + } if ((fp->f_flag & FREAD) == 0) return (EBADF); @@ -390,7 +466,7 @@ again: (u_int **) NULL); if (error) { goto out; -} + } inp = buf; inp += blockoff; @@ -398,7 +474,7 @@ again: resid = nbytes; if ((len = buflen - auio.uio_resid - blockoff) == 0) { goto eof; - } + } while (len > 0) { bdp = (struct dirent *) inp; @@ -426,7 +502,7 @@ again: strcpy(linux_dirent.dname, bdp->d_name); if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { goto out; - } + } inp += reclen; off += reclen; outp += linuxreclen; @@ -450,3 +526,238 @@ out: free(buf, M_TEMP); return error; } + +/* + * These exist mainly for hooks for doing /compat/linux translation. + */ + +int +linux_access(struct proc *p, struct linux_access_args *args, int *retval) +{ + struct access_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): access(%s, %d)\n", + p->p_pid, args->path, args->flags); +#endif + bsd.path = args->path; + bsd.flags = args->flags; + + return access(p, &bsd, retval); +} + +int +linux_unlink(struct proc *p, struct linux_unlink_args *args, int *retval) +{ + struct unlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): unlink(%s)\n", + p->p_pid, args->path); +#endif + bsd.path = args->path; + + return unlink(p, &bsd, retval); +} + +int +linux_chdir(struct proc *p, struct linux_chdir_args *args, int *retval) +{ + struct chdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): chdir(%s)\n", + p->p_pid, args->path); +#endif + bsd.path = args->path; + + return chdir(p, &bsd, retval); +} + +int +linux_chmod(struct proc *p, struct linux_chmod_args *args, int *retval) +{ + struct chmod_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): chmod(%s, %d)\n", + p->p_pid, args->path, args->mode); +#endif + bsd.path = args->path; + bsd.mode = args->mode; + + return chmod(p, &bsd, retval); +} + +int +linux_chown(struct proc *p, struct linux_chown_args *args, int *retval) +{ + struct chown_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): chown(%s, %d, %d)\n", + p->p_pid, args->path, args->uid, args->gid); +#endif + bsd.path = args->path; + /* XXX size casts here */ + bsd.uid = args->uid; + bsd.gid = args->gid; + + return chown(p, &bsd, retval); +} + +int +linux_mkdir(struct proc *p, struct linux_mkdir_args *args, int *retval) +{ + struct mkdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTCREAT(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): mkdir(%s, %d)\n", + p->p_pid, args->path, args->mode); +#endif + bsd.path = args->path; + bsd.mode = args->mode; + + return mkdir(p, &bsd, retval); +} + +int +linux_rmdir(struct proc *p, struct linux_rmdir_args *args, int *retval) +{ + struct rmdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): rmdir(%s)\n", + p->p_pid, args->path); +#endif + bsd.path = args->path; + + return rmdir(p, &bsd, retval); +} + +int +linux_rename(struct proc *p, struct linux_rename_args *args, int *retval) +{ + struct rename_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->from); + CHECKALTCREAT(p, &sg, args->to); + +#ifdef DEBUG + printf("Linux-emul(%d): rename(%s, %s)\n", + p->p_pid, args->from, args->to); +#endif + bsd.from = args->from; + bsd.to = args->to; + + return rename(p, &bsd, retval); +} + +int +linux_symlink(struct proc *p, struct linux_symlink_args *args, int *retval) +{ + struct symlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + CHECKALTCREAT(p, &sg, args->to); + +#ifdef DEBUG + printf("Linux-emul(%d): symlink(%s, %s)\n", + p->p_pid, args->path, args->to); +#endif + bsd.path = args->path; + bsd.link = args->to; + + return symlink(p, &bsd, retval); +} + +int +linux_execve(struct proc *p, struct linux_execve_args *args, int *retval) +{ + struct execve_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): execve(%s)\n", + p->p_pid, args->path); +#endif + bsd.fname = args->path; + bsd.argv = args->argp; + bsd.envv = args->envp; + + return execve(p, &bsd, retval); +} + +int +linux_readlink(struct proc *p, struct linux_readlink_args *args, int *retval) +{ + struct readlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->name); + +#ifdef DEBUG + printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n", + p->p_pid, args->name, args->buf, args->count); +#endif + bsd.path = args->name; + bsd.buf = args->buf; + bsd.count = args->count; + + return readlink(p, &bsd, retval); +} + +int +linux_truncate(struct proc *p, struct linux_truncate_args *args, int *retval) +{ + struct otruncate_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): truncate(%s)\n", + p->p_pid, args->path); +#endif + bsd.path = args->path; + + return otruncate(p, &bsd, retval); +} + diff --git a/sys/i386/linux/linux_genassym.c b/sys/i386/linux/linux_genassym.c new file mode 100644 index 0000000..c522948 --- /dev/null +++ b/sys/i386/linux/linux_genassym.c @@ -0,0 +1,22 @@ +#include <stdio.h> +#include <sys/param.h> +#include <sys/buf.h> +#include <sys/proc.h> +#include <i386/linux/linux.h> + +extern int main __P((void)); + +int +main() +{ + struct linux_sigframe *linux_sigf = (struct linux_sigframe *)0; + struct linux_sigcontext *linux_sc = (struct linux_sigcontext *)0; + + printf("#define\tLINUX_SIGF_HANDLER %d\n", &linux_sigf->sf_handler); + printf("#define\tLINUX_SIGF_SC %d\n", &linux_sigf->sf_sc); + printf("#define\tLINUX_SC_FS %d\n", &linux_sc->sc_fs); + printf("#define\tLINUX_SC_GS %d\n", &linux_sc->sc_gs); + printf("#define\tLINUX_SC_EFLAGS %d\n", &linux_sc->sc_eflags); + + return (0); +} diff --git a/sys/i386/linux/linux_ioctl.c b/sys/i386/linux/linux_ioctl.c index 03bc031..9680928 100644 --- a/sys/i386/linux/linux_ioctl.c +++ b/sys/i386/linux/linux_ioctl.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_ioctl.c,v 1.4 1995/12/29 22:12:12 sos Exp $ + * $Id: linux_ioctl.c,v 1.5 1995/12/30 00:42:25 sos Exp $ */ #include <sys/param.h> @@ -38,12 +38,16 @@ #include <sys/filedesc.h> #include <sys/tty.h> #include <sys/termios.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <sys/sockio.h> #include <machine/console.h> #include <machine/soundcard.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux_proto.h> struct linux_termios { unsigned long c_iflag; @@ -351,13 +355,6 @@ linux_to_bsd_termios(struct linux_termios *linux_termios, #endif } - -struct linux_ioctl_args { - int fd; - int cmd; - int arg; -}; - int linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval) { @@ -456,6 +453,38 @@ linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval) args->cmd = TIOCNOTTY; return ioctl(p, (struct ioctl_args *)args, retval); + case LINUX_SIOCGIFCONF: + args->cmd = OSIOCGIFCONF; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCGIFFLAGS: + args->cmd = SIOCGIFFLAGS; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCGIFADDR: + args->cmd = OSIOCGIFADDR; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCGIFDSTADDR: + args->cmd = OSIOCGIFDSTADDR; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCGIFBRDADDR: + args->cmd = OSIOCGIFBRDADDR; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCGIFNETMASK: + args->cmd = OSIOCGIFNETMASK; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCADDMULTI: + args->cmd = SIOCADDMULTI; + return ioctl(p, (struct ioctl_args *)args, retval); + + case LINUX_SIOCDELMULTI: + args->cmd = SIOCDELMULTI; + return ioctl(p, (struct ioctl_args *)args, retval); + case LINUX_TIOCSETD: switch (args->arg) { case LINUX_N_TTY: diff --git a/sys/i386/linux/linux_ipc.c b/sys/i386/linux/linux_ipc.c index 2e5b924..854766b 100644 --- a/sys/i386/linux/linux_ipc.c +++ b/sys/i386/linux/linux_ipc.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_ipc.c,v 1.5 1996/01/05 19:52:49 wollman Exp $ + * $Id: linux_ipc.c,v 1.6 1996/01/08 04:34:54 peter Exp $ */ @@ -36,7 +36,20 @@ #include <sys/shm.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> + +static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_msgop __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *)); +static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *)); struct linux_ipc_perm { linux_key_t key; @@ -115,33 +128,25 @@ bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ } -struct linux_ipc_args { - int what; - int arg1; - int arg2; - int arg3; - caddr_t ptr; -}; - -int +static int linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval) { return ENOSYS; } -int +static int linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval) { return ENOSYS; } -int +static int linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval) { return ENOSYS; } -int +static int linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgsnd_args /* { @@ -158,7 +163,7 @@ linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) return msgsnd(p, &bsd_args, retval); } -int +static int linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgrcv_args /* { @@ -177,7 +182,7 @@ linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) return msgrcv(p, &bsd_args, retval); } -int +static int linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgget_args /* { @@ -190,7 +195,7 @@ linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) return msgget(p, &bsd_args, retval); } -int +static int linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgctl_args /* { @@ -205,7 +210,7 @@ linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) return msgctl(p, &bsd_args, retval); } -int +static int linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmat_args /* { @@ -226,7 +231,7 @@ linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) return 0; } -int +static int linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmdt_args /* { @@ -237,7 +242,7 @@ linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) return shmdt(p, &bsd_args, retval); } -int +static int linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmget_args /* { @@ -252,7 +257,7 @@ linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) return shmget(p, &bsd_args, retval); } -int +static int linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmid_ds bsd_shmid; @@ -263,12 +268,13 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) struct shmid_ds *buf; } */ bsd_args; int error; + caddr_t sg = stackgap_init(); switch (args->arg2) { case LINUX_IPC_STAT: bsd_args.shmid = args->arg1; bsd_args.cmd = IPC_STAT; - bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); if ((error = shmctl(p, &bsd_args, retval))) return error; if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, @@ -282,7 +288,7 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) sizeof(linux_shmid)))) return error; linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); - bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, sizeof(struct shmid_ds)))) return error; @@ -297,7 +303,7 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) sizeof(linux_shmid)))) return error; linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); - bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, sizeof(struct shmid_ds)))) return error; diff --git a/sys/i386/linux/linux_locore.s b/sys/i386/linux/linux_locore.s new file mode 100644 index 0000000..1440218 --- /dev/null +++ b/sys/i386/linux/linux_locore.s @@ -0,0 +1,26 @@ +#include "linux_assym.h" /* system definitions */ +#include <machine/asmacros.h> /* miscellaneous asm macros */ + +#include <i386/linux/linux_syscall.h> /* system call numbers */ + +NON_GPROF_ENTRY(linux_sigcode) + call LINUX_SIGF_HANDLER(%esp) + leal LINUX_SIGF_SC(%esp),%ebx /* linux scp */ + movl LINUX_SC_FS(%ebx),%ecx + movl LINUX_SC_GS(%ebx),%edx + movl %cx,%fs + movl %dx,%gs + push %eax /* fake ret addr */ + movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */ + int $0x80 /* enter kernel with args on stack */ + hlt /* never gets here */ + + .align 2 /* long word align */ +_linux_esigcode: + + .data + .globl _linux_szsigcode +_linux_szsigcode: + .long _linux_esigcode-_linux_sigcode + + .text diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c index bc6e8d8..069ca28 100644 --- a/sys/i386/linux/linux_misc.c +++ b/sys/i386/linux/linux_misc.c @@ -6,7 +6,7 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer + * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_misc.c,v 1.11 1996/01/19 22:59:24 dyson Exp $ + * $Id: linux_misc.c,v 1.12 1996/02/16 18:40:50 peter Exp $ */ #include <sys/param.h> @@ -50,6 +50,7 @@ #include <sys/utsname.h> #include <sys/vnode.h> #include <sys/wait.h> +#include <sys/time.h> #include <vm/vm.h> #include <vm/vm_param.h> @@ -64,11 +65,8 @@ #include <machine/psl.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> - -struct linux_alarm_args { - unsigned int secs; -}; +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> int linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval) @@ -110,10 +108,6 @@ linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval) return 0; } -struct linux_brk_args { - linux_caddr_t dsend; -}; - int linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) { @@ -136,7 +130,7 @@ linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) return ENOMEM; error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) + if (error) return error; vm->vm_dsize += btoc((new-old)); *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize)); @@ -164,10 +158,6 @@ linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) #endif } -struct linux_uselib_args { - char *library; -}; - int linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) { @@ -178,12 +168,13 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) unsigned long vmaddr, file_offset; unsigned long buffer, bss_size; char *ptr; - char path[MAXPATHLEN]; - const char *prefix = "/compat/linux"; - size_t sz, len; int error; + caddr_t sg; int locked; + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->library); + #ifdef DEBUG printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library); #endif @@ -192,20 +183,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) locked = 0; vp = NULL; - for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ; - sz = MAXPATHLEN - (ptr - path); - if (error = copyinstr(args->library, ptr, sz, &len)) - goto cleanup; - if (*ptr != '/') { - error = EINVAL; - goto cleanup; - } - -#ifdef DEBUG - printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path); -#endif - - NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); + NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p); if (error = namei(&ni)) goto cleanup; @@ -361,7 +339,7 @@ printf("uselib: Non page aligned binary %d\n", file_offset); goto cleanup; /* copy from kernel VM space to user space */ - error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, + error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, a_out->a_text + a_out->a_data); /* release temporary kernel space */ @@ -404,7 +382,7 @@ printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]); /* * allocate some 'anon' space */ - error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, + error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) @@ -427,49 +405,138 @@ cleanup: return error; } -struct linux_select_args { - void *ptr; +/* XXX move */ +struct linux_select_argv { + int nfds; + fd_set *readfds; + fd_set *writefds; + fd_set *exceptfds; + struct timeval *timeout; }; int linux_select(struct proc *p, struct linux_select_args *args, int *retval) { - struct { - int nfds; - fd_set *readfds; - fd_set *writefds; - fd_set *exceptfds; - struct timeval *timeout; - } linux_args; - struct select_args /* { - unsigned int nd; - fd_set *in; - fd_set *ou; - fd_set *ex; - struct timeval *tv; - } */ bsd_args; + struct linux_select_argv linux_args; + struct linux_newselect_args newsel; int error; +#ifdef SELECT_DEBUG + printf("Linux-emul(%d): select(%x)\n", + p->p_pid, args->ptr); +#endif if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, sizeof(linux_args)))) return error; + + newsel.nfds = linux_args.nfds; + newsel.readfds = linux_args.readfds; + newsel.writefds = linux_args.writefds; + newsel.exceptfds = linux_args.exceptfds; + newsel.timeout = linux_args.timeout; + + return linux_newselect(p, &newsel, retval); +} + +int +linux_newselect(struct proc *p, struct linux_newselect_args *args, int *retval) +{ + struct select_args bsa; + struct timeval tv0, tv1, utv, *tvp; + caddr_t sg; + int error; + #ifdef DEBUG - printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n", - p->p_pid, linux_args.nfds, linux_args.readfds, - linux_args.writefds, linux_args.exceptfds, - linux_args.timeout); + printf("Linux-emul(%d): newselect(%d, %x, %x, %x, %x)\n", + p->p_pid, args->nfds, args->readfds, args->writefds, + args->exceptfds, args->timeout); #endif - bsd_args.nd = linux_args.nfds; - bsd_args.in = linux_args.readfds; - bsd_args.ou = linux_args.writefds; - bsd_args.ex = linux_args.exceptfds; - bsd_args.tv = linux_args.timeout; - return select(p, &bsd_args, retval); -} + error = 0; + bsa.nd = args->nfds; + bsa.in = args->readfds; + bsa.ou = args->writefds; + bsa.ex = args->exceptfds; + bsa.tv = args->timeout; -struct linux_getpgid_args { - int pid; -}; + /* + * Store current time for computation of the amount of + * time left. + */ + if (args->timeout) { + if ((error = copyin(args->timeout, &utv, sizeof(utv)))) + goto select_out; +#ifdef DEBUG + printf("Linux-emul(%d): incoming timeout (%d/%d)\n", + p->p_pid, utv.tv_sec, utv.tv_usec); +#endif + if (itimerfix(&utv)) { + /* + * The timeval was invalid. Convert it to something + * valid that will act as it does under Linux. + */ + sg = stackgap_init(); + tvp = stackgap_alloc(&sg, sizeof(utv)); + utv.tv_sec += utv.tv_usec / 1000000; + utv.tv_usec %= 1000000; + if (utv.tv_usec < 0) { + utv.tv_sec -= 1; + utv.tv_usec += 1000000; + } + if (utv.tv_sec < 0) + timerclear(&utv); + if ((error = copyout(&utv, tvp, sizeof(utv)))) + goto select_out; + bsa.tv = tvp; + } + microtime(&tv0); + } + + error = select(p, &bsa, retval); +#ifdef DEBUG + printf("Linux-emul(%d): real select returns %d\n", + p->p_pid, error); +#endif + + if (error) { + /* + * See fs/select.c in the Linux kernel. Without this, + * Maelstrom doesn't work. + */ + if (error == ERESTART) + error = EINTR; + goto select_out; + } + + if (args->timeout) { + if (*retval) { + /* + * Compute how much time was left of the timeout, + * by subtracting the current time and the time + * before we started the call, and subtracting + * that result from the user-supplied value. + */ + microtime(&tv1); + timevalsub(&tv1, &tv0); + timevalsub(&utv, &tv1); + if (utv.tv_sec < 0) + timerclear(&utv); + } else + timerclear(&utv); +#ifdef DEBUG + printf("Linux-emul(%d): outgoing timeout (%d/%d)\n", + p->p_pid, utv.tv_sec, utv.tv_usec); +#endif + if ((error = copyout(&utv, args->timeout, sizeof(utv)))) + goto select_out; + } + +select_out: +#ifdef DEBUG + printf("Linux-emul(%d): newselect_out -> %d\n", + p->p_pid, error); +#endif + return error; +} int linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval) @@ -490,35 +557,33 @@ linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval) } int -linux_fork(struct proc *p, void *args, int *retval) +linux_fork(struct proc *p, struct linux_fork_args *args, int *retval) { int error; #ifdef DEBUG printf("Linux-emul(%d): fork()\n", p->p_pid); #endif - if (error = fork(p, args, retval)) + if (error = fork(p, (struct fork_args *)args, retval)) return error; if (retval[1] == 1) retval[0] = 0; return 0; } -struct linux_mmap_args { - void *ptr; -}; - -int -linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval) -{ - struct { +/* XXX move */ +struct linux_mmap_argv { linux_caddr_t addr; int len; int prot; int flags; int fd; int pos; - } linux_args; +}; + +int +linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval) +{ struct mmap_args /* { caddr_t addr; size_t len; @@ -529,13 +594,14 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval) off_t pos; } */ bsd_args; int error; + struct linux_mmap_argv linux_args; if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, sizeof(linux_args)))) return error; #ifdef DEBUG printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n", - p->p_pid, linux_args.addr, linux_args.len, linux_args.prot, + p->p_pid, linux_args.addr, linux_args.len, linux_args.prot, linux_args.flags, linux_args.fd, linux_args.pos); #endif bsd_args.flags = 0; @@ -556,9 +622,17 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval) return mmap(p, &bsd_args, retval); } -struct linux_pipe_args { - int *pipefds; -}; +int +linux_msync(struct proc *p, struct linux_msync_args *args, int *retval) +{ + struct msync_args bsd_args; + + bsd_args.addr = args->addr; + bsd_args.len = args->len; + bsd_args.flags = 0; /* XXX ignore */ + + return msync(p, &bsd_args, retval); +} int linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval) @@ -576,10 +650,6 @@ linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval) return 0; } -struct linux_time_args { - linux_time_t *tm; -}; - int linux_time(struct proc *p, struct linux_time_args *args, int *retval) { @@ -592,28 +662,24 @@ linux_time(struct proc *p, struct linux_time_args *args, int *retval) #endif microtime(&tv); tm = tv.tv_sec; - if (error = copyout(&tm, args->tm, sizeof(linux_time_t))) + if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t)))) return error; - *retval = tv.tv_sec; + *retval = tm; return 0; } -struct linux_tms { +struct linux_times_argv { long tms_utime; long tms_stime; long tms_cutime; long tms_cstime; }; -struct linux_tms_args { - char *buf; -}; - int -linux_times(struct proc *p, struct linux_tms_args *args, int *retval) +linux_times(struct proc *p, struct linux_times_args *args, int *retval) { struct timeval tv; - struct linux_tms tms; + struct linux_times_argv tms; #ifdef DEBUG printf("Linux-emul(%d): times(*)\n", p->p_pid); @@ -627,9 +693,10 @@ linux_times(struct proc *p, struct linux_tms_args *args, int *retval) microtime(&tv); *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000; return (copyout((caddr_t)&tms, (caddr_t)args->buf, - sizeof(struct linux_tms))); + sizeof(struct linux_times_argv))); } +/* XXX move */ struct linux_newuname_t { char sysname[65]; char nodename[65]; @@ -639,10 +706,6 @@ struct linux_newuname_t { char domainname[65]; }; -struct linux_newuname_args { - char *buf; -}; - int linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval) { @@ -662,10 +725,6 @@ linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval) sizeof(struct linux_newuname_t))); } -struct linux_utime_args { - char *fname; - linux_time_t *timeptr; -}; int linux_utime(struct proc *p, struct linux_utime_args *args, int *retval) @@ -675,23 +734,21 @@ linux_utime(struct proc *p, struct linux_utime_args *args, int *retval) struct timeval *tptr; } */ bsdutimes; struct timeval tv; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->fname); #ifdef DEBUG printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname); #endif - tv.tv_sec = (long)args->timeptr; + tv.tv_sec = (long)args->timeptr; /* XXX: wrong?? */ tv.tv_usec = 0; bsdutimes.tptr = &tv; bsdutimes.path = args->fname; return utimes(p, &bsdutimes, retval); } -struct linux_waitpid_args { - int pid; - int *status; - int options; -}; - int linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval) { @@ -704,8 +761,8 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval) int error, tmpstat; #ifdef DEBUG - printf("Linux-emul(%d): waitpid(%d, *, %d)\n", - p->p_pid, args->pid, args->options); + printf("Linux-emul(%d): waitpid(%d, 0x%x, %d)\n", + p->p_pid, args->pid, args->status, args->options); #endif tmp.pid = args->pid; tmp.status = args->status; @@ -714,25 +771,21 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval) if (error = wait4(p, &tmp, retval)) return error; - if (error = copyin(args->status, &tmpstat, sizeof(int))) - return error; - if (WIFSIGNALED(tmpstat)) - tmpstat = (tmpstat & 0xffffff80) | - bsd_to_linux_signal[WTERMSIG(tmpstat)]; - else if (WIFSTOPPED(tmpstat)) - tmpstat = (tmpstat & 0xffff00ff) | - (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); - return copyout(&tmpstat, args->status, sizeof(int)); + if (args->status) { + if (error = copyin(args->status, &tmpstat, sizeof(int))) + return error; + if (WIFSIGNALED(tmpstat)) + tmpstat = (tmpstat & 0xffffff80) | + bsd_to_linux_signal[WTERMSIG(tmpstat)]; + else if (WIFSTOPPED(tmpstat)) + tmpstat = (tmpstat & 0xffff00ff) | + (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); + return copyout(&tmpstat, args->status, sizeof(int)); + } else + return 0; } -struct linux_wait4_args { - int pid; - int *status; - int options; - struct rusage *rusage; -}; - -int +int linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval) { struct wait_args /* { @@ -744,8 +797,8 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval) int error, tmpstat; #ifdef DEBUG - printf("Linux-emul(%d): wait4(%d, *, %d, *)\n", - p->p_pid, args->pid, args->options); + printf("Linux-emul(%d): wait4(%d, 0x%x, %d, 0x%x)\n", + p->p_pid, args->pid, args->status, args->options, args->rusage); #endif tmp.pid = args->pid; tmp.status = args->status; @@ -754,28 +807,108 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval) if (error = wait4(p, &tmp, retval)) return error; - if (error = copyin(args->status, &tmpstat, sizeof(int))) - return error; - if (WIFSIGNALED(tmpstat)) - tmpstat = (tmpstat & 0xffffff80) | - bsd_to_linux_signal[WTERMSIG(tmpstat)]; - else if (WIFSTOPPED(tmpstat)) - tmpstat = (tmpstat & 0xffff00ff) | - (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); - return copyout(&tmpstat, args->status, sizeof(int)); -} -struct linux_mknod_args { - char *path; - int mode; - int dev; -}; + p->p_siglist &= ~sigmask(SIGCHLD); + + if (args->status) { + if (error = copyin(args->status, &tmpstat, sizeof(int))) + return error; + if (WIFSIGNALED(tmpstat)) + tmpstat = (tmpstat & 0xffffff80) | + bsd_to_linux_signal[WTERMSIG(tmpstat)]; + else if (WIFSTOPPED(tmpstat)) + tmpstat = (tmpstat & 0xffff00ff) | + (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); + return copyout(&tmpstat, args->status, sizeof(int)); + } else + return 0; +} -int +int linux_mknod(struct proc *p, struct linux_mknod_args *args, int *retval) { - if (args->mode & S_IFIFO) - return mkfifo(p, (struct mkfifo_args *)args, retval); - else - return mknod(p, (struct mknod_args *)args, retval); + caddr_t sg; + struct mknod_args bsd_mknod; + struct mkfifo_args bsd_mkfifo; + + sg = stackgap_init(); + + CHECKALTCREAT(p, &sg, args->path); + +#ifdef DEBUG + printf("Linux-emul(%d): mknod(%s, %d, %d)\n", + p->p_pid, args->path, args->mode, args->dev); +#endif + + if (args->mode & S_IFIFO) { + bsd_mkfifo.path = args->path; + bsd_mkfifo.mode = args->mode; + return mkfifo(p, &bsd_mkfifo, retval); + } else { + bsd_mknod.path = args->path; + bsd_mknod.mode = args->mode; + bsd_mknod.dev = args->dev; + return mknod(p, &bsd_mknod, retval); + } +} + +/* + * UGH! This is just about the dumbest idea I've ever heard!! + */ +int +linux_personality(struct proc *p, struct linux_personality_args *args, + int *retval) +{ +#ifdef DEBUG + printf("Linux-emul(%d): personality(%d)\n", + p->p_pid, args->per); +#endif + if (args->per != 0) + return EINVAL; + + /* Yes Jim, it's still a Linux... */ + retval[0] = 0; + return 0; +} + +/* + * Wrappers for get/setitimer for debugging.. + */ +int +linux_setitimer(struct proc *p, struct linux_setitimer_args *args, int *retval) +{ + struct setitimer_args bsa; + struct itimerval foo; + int error; + +#ifdef DEBUG + printf("Linux-emul(%d): setitimer(%08x, %08x)\n", + p->p_pid, args->itv, args->oitv); +#endif + bsa.which = args->which; + bsa.itv = args->itv; + bsa.oitv = args->oitv; + if (args->itv) { + if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo, + sizeof(foo)))) + return error; +#ifdef DEBUG + printf("setitimer: value: sec: %d, usec: %d\n", foo.it_value.tv_sec, foo.it_value.tv_usec); + printf("setitimer: interval: sec: %d, usec: %d\n", foo.it_interval.tv_sec, foo.it_interval.tv_usec); +#endif + } + return setitimer(p, &bsa, retval); +} + +int +linux_getitimer(struct proc *p, struct linux_getitimer_args *args, int *retval) +{ + struct getitimer_args bsa; +#ifdef DEBUG + printf("Linux-emul(%d): getitimer(%08x)\n", + p->p_pid, args->itv); +#endif + bsa.which = args->which; + bsa.itv = args->itv; + return getitimer(p, &bsa, retval); } diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h new file mode 100644 index 0000000..a227f2c --- /dev/null +++ b/sys/i386/linux/linux_proto.h @@ -0,0 +1,465 @@ +/* + * System call prototypes. + * + * DO NOT EDIT-- this file is automatically generated. + * created from Id: syscalls.master,v 1.1 1996/03/02 19:04:15 peter Exp + */ + +#ifndef _LINUX_SYSPROTO_H_ +#define _LINUX_SYSPROTO_H_ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/mount.h> + +struct linux_setup_args { + int dummy; +}; +struct linux_fork_args { + int dummy; +}; +struct linux_open_args { + char * path; + int flags; + int mode; +}; +struct linux_waitpid_args { + int pid; + int * status; + int options; +}; +struct linux_creat_args { + char * path; + int mode; +}; +struct linux_unlink_args { + char * path; +}; +struct linux_execve_args { + char * path; + char ** argp; + char ** envp; +}; +struct linux_chdir_args { + char * path; +}; +struct linux_time_args { + linux_time_t * tm; +}; +struct linux_mknod_args { + char * path; + int mode; + int dev; +}; +struct linux_chmod_args { + char * path; + int mode; +}; +struct linux_chown_args { + char * path; + int uid; + int gid; +}; +struct linux_break_args { + char * nsize; +}; +struct linux_stat_args { + char * path; + struct ostat * up; +}; +struct linux_lseek_args { + int fdes; + long off; + int whence; +}; +struct linux_mount_args { + int dummy; +}; +struct linux_umount_args { + int dummy; +}; +struct linux_stime_args { + int dummy; +}; +struct linux_ptrace_args { + int dummy; +}; +struct linux_alarm_args { + unsigned int secs; +}; +struct linux_fstat_args { + int fd; + struct ostat * up; +}; +struct linux_pause_args { + int dummy; +}; +struct linux_utime_args { + char * fname; + struct linux_time_t * timeptr; +}; +struct linux_stty_args { + int dummy; +}; +struct linux_gtty_args { + int dummy; +}; +struct linux_access_args { + char * path; + int flags; +}; +struct linux_nice_args { + int dummy; +}; +struct linux_ftime_args { + int dummy; +}; +struct linux_kill_args { + int pid; + int signum; +}; +struct linux_rename_args { + char * from; + char * to; +}; +struct linux_mkdir_args { + char * path; + int mode; +}; +struct linux_rmdir_args { + char * path; +}; +struct linux_pipe_args { + int * pipefds; +}; +struct linux_times_args { + struct linux_times_argv * buf; +}; +struct linux_prof_args { + int dummy; +}; +struct linux_brk_args { + char * dsend; +}; +struct linux_signal_args { + int sig; + linux_handler_t handler; +}; +struct linux_phys_args { + int dummy; +}; +struct linux_lock_args { + int dummy; +}; +struct linux_ioctl_args { + int fd; + u_long cmd; + int arg; +}; +struct linux_fcntl_args { + int fd; + int cmd; + int arg; +}; +struct linux_mpx_args { + int dummy; +}; +struct linux_ulimit_args { + int dummy; +}; +struct linux_olduname_args { + struct linux_oldold_utsname * up; +}; +struct linux_ustat_args { + int dummy; +}; +struct linux_sigaction_args { + int sig; + struct linux_sigaction * nsa; + struct linux_sigaction * osa; +}; +struct linux_siggetmask_args { + int dummy; +}; +struct linux_sigsetmask_args { + linux_sigset_t mask; +}; +struct linux_sigsuspend_args { + linux_sigset_t mask; +}; +struct linux_sigpending_args { + linux_sigset_t * mask; +}; +struct linux_select_args { + struct linux_select_argv * ptr; +}; +struct linux_symlink_args { + char * path; + char * to; +}; +struct linux_readlink_args { + char * name; + char * buf; + int count; +}; +struct linux_uselib_args { + char * library; +}; +struct linux_readdir_args { + int fd; + struct linux_dirent * dent; + unsigned int count; +}; +struct linux_mmap_args { + struct linux_mmap_argv * ptr; +}; +struct linux_truncate_args { + char * path; + long length; +}; +struct linux_statfs_args { + char * path; + struct linux_statfs_buf * buf; +}; +struct linux_fstatfs_args { + int fd; + struct linux_statfs_buf * buf; +}; +struct linux_ioperm_args { + unsigned int lo; + unsigned int hi; + int val; +}; +struct linux_socketcall_args { + int what; + void * args; +}; +struct linux_ksyslog_args { + int what; +}; +struct linux_setitimer_args { + u_int which; + struct itimerval * itv; + struct itimerval * oitv; +}; +struct linux_getitimer_args { + u_int which; + struct itimerval * itv; +}; +struct linux_newstat_args { + char * path; + struct linux_newstat * buf; +}; +struct linux_newlstat_args { + char * path; + struct linux_newstat * buf; +}; +struct linux_newfstat_args { + int fd; + struct linux_newstat * buf; +}; +struct linux_uname_args { + struct linux_old_utsname * up; +}; +struct linux_iopl_args { + int level; +}; +struct linux_vhangup_args { + int dummy; +}; +struct linux_idle_args { + int dummy; +}; +struct linux_vm86_args { + int dummy; +}; +struct linux_wait4_args { + int pid; + int * status; + int options; + struct rusage * rusage; +}; +struct linux_swapoff_args { + int dummy; +}; +struct linux_sysinfo_args { + int dummy; +}; +struct linux_ipc_args { + int what; + int arg1; + int arg2; + int arg3; + caddr_t ptr; +}; +struct linux_sigreturn_args { + struct linux_sigcontext * scp; +}; +struct linux_clone_args { + int dummy; +}; +struct linux_newuname_args { + struct linux_newuname_t * buf; +}; +struct linux_modify_ldt_args { + int func; + void * ptr; + size_t bytecount; +}; +struct linux_adjtimex_args { + int dummy; +}; +struct linux_sigprocmask_args { + int how; + linux_sigset_t * mask; + linux_sigset_t * omask; +}; +struct linux_create_module_args { + int dummy; +}; +struct linux_init_module_args { + int dummy; +}; +struct linux_delete_module_args { + int dummy; +}; +struct linux_get_kernel_syms_args { + int dummy; +}; +struct linux_quotactl_args { + int dummy; +}; +struct linux_getpgid_args { + int pid; +}; +struct linux_bdflush_args { + int dummy; +}; +struct linux_personality_args { + int per; +}; +struct linux_llseek_args { + int fd; + u_int32_t ohigh; + u_int32_t olow; + caddr_t res; + int whence; +}; +struct linux_getdents_args { + int fd; + void * dent; + unsigned count; +}; +struct linux_newselect_args { + int nfds; + fd_set * readfds; + fd_set * writefds; + fd_set * exceptfds; + struct timeval * timeout; +}; +struct linux_msync_args { + caddr_t addr; + int len; + int fl; +}; +int linux_setup __P((struct proc *, struct linux_setup_args *, int [])); +int linux_fork __P((struct proc *, struct linux_fork_args *, int [])); +int linux_open __P((struct proc *, struct linux_open_args *, int [])); +int linux_waitpid __P((struct proc *, struct linux_waitpid_args *, int [])); +int linux_creat __P((struct proc *, struct linux_creat_args *, int [])); +int linux_unlink __P((struct proc *, struct linux_unlink_args *, int [])); +int linux_execve __P((struct proc *, struct linux_execve_args *, int [])); +int linux_chdir __P((struct proc *, struct linux_chdir_args *, int [])); +int linux_time __P((struct proc *, struct linux_time_args *, int [])); +int linux_mknod __P((struct proc *, struct linux_mknod_args *, int [])); +int linux_chmod __P((struct proc *, struct linux_chmod_args *, int [])); +int linux_chown __P((struct proc *, struct linux_chown_args *, int [])); +int linux_break __P((struct proc *, struct linux_break_args *, int [])); +int linux_stat __P((struct proc *, struct linux_stat_args *, int [])); +int linux_lseek __P((struct proc *, struct linux_lseek_args *, int [])); +int linux_mount __P((struct proc *, struct linux_mount_args *, int [])); +int linux_umount __P((struct proc *, struct linux_umount_args *, int [])); +int linux_stime __P((struct proc *, struct linux_stime_args *, int [])); +int linux_ptrace __P((struct proc *, struct linux_ptrace_args *, int [])); +int linux_alarm __P((struct proc *, struct linux_alarm_args *, int [])); +int linux_fstat __P((struct proc *, struct linux_fstat_args *, int [])); +int linux_pause __P((struct proc *, struct linux_pause_args *, int [])); +int linux_utime __P((struct proc *, struct linux_utime_args *, int [])); +int linux_stty __P((struct proc *, struct linux_stty_args *, int [])); +int linux_gtty __P((struct proc *, struct linux_gtty_args *, int [])); +int linux_access __P((struct proc *, struct linux_access_args *, int [])); +int linux_nice __P((struct proc *, struct linux_nice_args *, int [])); +int linux_ftime __P((struct proc *, struct linux_ftime_args *, int [])); +int linux_kill __P((struct proc *, struct linux_kill_args *, int [])); +int linux_rename __P((struct proc *, struct linux_rename_args *, int [])); +int linux_mkdir __P((struct proc *, struct linux_mkdir_args *, int [])); +int linux_rmdir __P((struct proc *, struct linux_rmdir_args *, int [])); +int linux_pipe __P((struct proc *, struct linux_pipe_args *, int [])); +int linux_times __P((struct proc *, struct linux_times_args *, int [])); +int linux_prof __P((struct proc *, struct linux_prof_args *, int [])); +int linux_brk __P((struct proc *, struct linux_brk_args *, int [])); +int linux_signal __P((struct proc *, struct linux_signal_args *, int [])); +int linux_phys __P((struct proc *, struct linux_phys_args *, int [])); +int linux_lock __P((struct proc *, struct linux_lock_args *, int [])); +int linux_ioctl __P((struct proc *, struct linux_ioctl_args *, int [])); +int linux_fcntl __P((struct proc *, struct linux_fcntl_args *, int [])); +int linux_mpx __P((struct proc *, struct linux_mpx_args *, int [])); +int linux_ulimit __P((struct proc *, struct linux_ulimit_args *, int [])); +int linux_olduname __P((struct proc *, struct linux_olduname_args *, int [])); +int linux_ustat __P((struct proc *, struct linux_ustat_args *, int [])); +int linux_sigaction __P((struct proc *, struct linux_sigaction_args *, int [])); +int linux_siggetmask __P((struct proc *, struct linux_siggetmask_args *, int [])); +int linux_sigsetmask __P((struct proc *, struct linux_sigsetmask_args *, int [])); +int linux_sigsuspend __P((struct proc *, struct linux_sigsuspend_args *, int [])); +int linux_sigpending __P((struct proc *, struct linux_sigpending_args *, int [])); +int linux_select __P((struct proc *, struct linux_select_args *, int [])); +int linux_symlink __P((struct proc *, struct linux_symlink_args *, int [])); +int linux_readlink __P((struct proc *, struct linux_readlink_args *, int [])); +int linux_uselib __P((struct proc *, struct linux_uselib_args *, int [])); +int linux_readdir __P((struct proc *, struct linux_readdir_args *, int [])); +int linux_mmap __P((struct proc *, struct linux_mmap_args *, int [])); +int linux_truncate __P((struct proc *, struct linux_truncate_args *, int [])); +int linux_statfs __P((struct proc *, struct linux_statfs_args *, int [])); +int linux_fstatfs __P((struct proc *, struct linux_fstatfs_args *, int [])); +int linux_ioperm __P((struct proc *, struct linux_ioperm_args *, int [])); +int linux_socketcall __P((struct proc *, struct linux_socketcall_args *, int [])); +int linux_ksyslog __P((struct proc *, struct linux_ksyslog_args *, int [])); +int linux_setitimer __P((struct proc *, struct linux_setitimer_args *, int [])); +int linux_getitimer __P((struct proc *, struct linux_getitimer_args *, int [])); +int linux_newstat __P((struct proc *, struct linux_newstat_args *, int [])); +int linux_newlstat __P((struct proc *, struct linux_newlstat_args *, int [])); +int linux_newfstat __P((struct proc *, struct linux_newfstat_args *, int [])); +int linux_uname __P((struct proc *, struct linux_uname_args *, int [])); +int linux_iopl __P((struct proc *, struct linux_iopl_args *, int [])); +int linux_vhangup __P((struct proc *, struct linux_vhangup_args *, int [])); +int linux_idle __P((struct proc *, struct linux_idle_args *, int [])); +int linux_vm86 __P((struct proc *, struct linux_vm86_args *, int [])); +int linux_wait4 __P((struct proc *, struct linux_wait4_args *, int [])); +int linux_swapoff __P((struct proc *, struct linux_swapoff_args *, int [])); +int linux_sysinfo __P((struct proc *, struct linux_sysinfo_args *, int [])); +int linux_ipc __P((struct proc *, struct linux_ipc_args *, int [])); +int linux_sigreturn __P((struct proc *, struct linux_sigreturn_args *, int [])); +int linux_clone __P((struct proc *, struct linux_clone_args *, int [])); +int linux_newuname __P((struct proc *, struct linux_newuname_args *, int [])); +int linux_modify_ldt __P((struct proc *, struct linux_modify_ldt_args *, int [])); +int linux_adjtimex __P((struct proc *, struct linux_adjtimex_args *, int [])); +int linux_sigprocmask __P((struct proc *, struct linux_sigprocmask_args *, int [])); +int linux_create_module __P((struct proc *, struct linux_create_module_args *, int [])); +int linux_init_module __P((struct proc *, struct linux_init_module_args *, int [])); +int linux_delete_module __P((struct proc *, struct linux_delete_module_args *, int [])); +int linux_get_kernel_syms __P((struct proc *, struct linux_get_kernel_syms_args *, int [])); +int linux_quotactl __P((struct proc *, struct linux_quotactl_args *, int [])); +int linux_getpgid __P((struct proc *, struct linux_getpgid_args *, int [])); +int linux_bdflush __P((struct proc *, struct linux_bdflush_args *, int [])); +int linux_personality __P((struct proc *, struct linux_personality_args *, int [])); +int linux_llseek __P((struct proc *, struct linux_llseek_args *, int [])); +int linux_getdents __P((struct proc *, struct linux_getdents_args *, int [])); +int linux_newselect __P((struct proc *, struct linux_newselect_args *, int [])); +int linux_msync __P((struct proc *, struct linux_msync_args *, int [])); + +#ifdef COMPAT_43 + + +#endif /* COMPAT_43 */ + +#endif /* !_LINUX_SYSPROTO_H_ */ diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c index fc5c2cd..32648cb 100644 --- a/sys/i386/linux/linux_signal.c +++ b/sys/i386/linux/linux_signal.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_signal.c,v 1.2 1995/11/22 07:43:50 bde Exp $ + * $Id: linux_signal.c,v 1.3 1995/12/15 03:06:56 peter Exp $ */ #include <sys/param.h> @@ -37,69 +37,96 @@ #include <sys/signalvar.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> - -#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD)) +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> static sigset_t -linux_to_bsd_sigmask(linux_sigset_t mask) { - int i; +linux_to_bsd_sigset(linux_sigset_t mask) { + int b, l; sigset_t new = 0; - for (i = 1; i <= LINUX_NSIG; i++) - if (mask & (1 << i-1)) - new |= (1 << (linux_to_bsd_signal[i]-1)); + for (l = 1; l <= LINUX_NSIG; l++) { + if (mask & (1 << (l - 1))) { + if ((b = linux_to_bsd_signal[l])) + new |= (1 << (b - 1)); + } + } return new; } static linux_sigset_t -bsd_to_linux_sigmask(sigset_t mask) { - int i; +bsd_to_linux_sigset(sigset_t mask) { + int b, l; sigset_t new = 0; - for (i = 1; i <= NSIG; i++) - if (mask & (1 << i-1)) - new |= (1 << (bsd_to_linux_signal[i]-1)); + for (b = 1; b <= NSIG; b++) { + if (mask & (1 << (b - 1))) { + if ((l = bsd_to_linux_signal[b])) + new |= (1 << (l - 1)); + } + } return new; } -struct linux_sigaction_args { - int sig; - linux_sigaction_t *nsa; - linux_sigaction_t *osa; -}; +void +linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) +{ + bsa->sa_mask = linux_to_bsd_sigset(lsa->sa_mask); + bsa->sa_handler = lsa->sa_handler; + bsa->sa_flags = 0; + if (lsa->sa_flags & LINUX_SA_NOCLDSTOP) + bsa->sa_flags |= SA_NOCLDSTOP; + if (lsa->sa_flags & LINUX_SA_ONSTACK) + bsa->sa_flags |= SA_ONSTACK; + if (lsa->sa_flags & LINUX_SA_RESTART) + bsa->sa_flags |= SA_RESTART; + if (lsa->sa_flags & LINUX_SA_ONESHOT) + bsa->sa_flags |= SA_RESETHAND; + if (lsa->sa_flags & LINUX_SA_NOMASK) + bsa->sa_flags |= SA_NODEFER; +} + +void +bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) +{ + lsa->sa_handler = bsa->sa_handler; + lsa->sa_restorer = NULL; /* unsupported */ + lsa->sa_mask = bsd_to_linux_sigset(bsa->sa_mask); + lsa->sa_flags = 0; + if (bsa->sa_flags & SA_NOCLDSTOP) + lsa->sa_flags |= LINUX_SA_NOCLDSTOP; + if (bsa->sa_flags & SA_ONSTACK) + lsa->sa_flags |= LINUX_SA_ONSTACK; + if (bsa->sa_flags & SA_RESTART) + lsa->sa_flags |= LINUX_SA_RESTART; + if (bsa->sa_flags & SA_RESETHAND) + lsa->sa_flags |= LINUX_SA_ONESHOT; + if (bsa->sa_flags & SA_NODEFER) + lsa->sa_flags |= LINUX_SA_NOMASK; +} int linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval) { linux_sigaction_t linux_sa; struct sigaction *nsa = NULL, *osa = NULL, bsd_sa; - struct sigaction_args /* { - int signum; - struct sigaction *nsa; - struct sigaction *osa; - } */ sa; + struct sigaction_args sa; int error; + caddr_t sg = stackgap_init(); #ifdef DEBUG - printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig); + printf("Linux-emul(%d): sigaction(%d, %08x, %08x)\n", p->p_pid, args->sig, + args->nsa, args->osa); #endif + if (args->osa) - osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction)); + osa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction)); if (args->nsa) { - nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction)); + nsa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction)); if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t))) return error; - bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask); - bsd_sa.sa_handler = linux_sa.sa_handler; - bsd_sa.sa_flags = 0; - if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP) - bsd_sa.sa_flags |= SA_NOCLDSTOP; - if (linux_sa.sa_flags & LINUX_SA_ONSTACK) - bsd_sa.sa_flags |= SA_ONSTACK; - if (linux_sa.sa_flags & LINUX_SA_RESTART) - bsd_sa.sa_flags |= SA_RESTART; + linux_to_bsd_sigaction(&linux_sa, &bsd_sa); if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction))) return error; } @@ -112,27 +139,49 @@ linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval) if (args->osa) { if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction))) return error; - linux_sa.sa_handler = bsd_sa.sa_handler; - linux_sa.sa_restorer = NULL; - linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask); - linux_sa.sa_flags = 0; - if (bsd_sa.sa_flags & SA_NOCLDSTOP) - linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP; - if (bsd_sa.sa_flags & SA_ONSTACK) - linux_sa.sa_flags |= LINUX_SA_ONSTACK; - if (bsd_sa.sa_flags & SA_RESTART) - linux_sa.sa_flags |= LINUX_SA_RESTART; + bsd_to_linux_sigaction(&bsd_sa, &linux_sa); if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t))) return error; } return 0; } -struct linux_sigprocmask_args { - int how; - linux_sigset_t *mask; - linux_sigset_t *omask; -}; +int +linux_signal(struct proc *p, struct linux_signal_args *args, int *retval) +{ + caddr_t sg; + struct sigaction_args sa_args; + struct sigaction *osa, *nsa, tmpsa; + int error; + +#ifdef DEBUG + printf("Linux-emul(%d): signal(%d, %08x)\n", p->p_pid, + args->sig, args->handler); +#endif + sg = stackgap_init(); + nsa = stackgap_alloc(&sg, sizeof *nsa); + osa = stackgap_alloc(&sg, sizeof *osa); + + tmpsa.sa_handler = args->handler; + tmpsa.sa_mask = (sigset_t) 0; + tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER; + if ((error = copyout(&tmpsa, nsa, sizeof tmpsa))) + return error; + + sa_args.signum = linux_to_bsd_signal[args->sig]; + sa_args.osa = osa; + sa_args.nsa = nsa; + if ((error = sigaction(p, &sa_args, retval))) + return error; + + if ((error = copyin(osa, &tmpsa, sizeof *osa))) + return error; + + *retval = (int)tmpsa.sa_handler; + + return 0; +} + int linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, @@ -145,8 +194,11 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, #ifdef DEBUG printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how); #endif + + *retval = 0; + if (args->omask != NULL) { - omask = bsd_to_linux_sigmask(p->p_sigmask); + omask = bsd_to_linux_sigset(p->p_sigmask); if (error = copyout(&omask, args->omask, sizeof(sigset_t))) return error; } @@ -155,17 +207,17 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t))) return error; - mask = linux_to_bsd_sigmask(mask); + mask = linux_to_bsd_sigset(mask); s = splhigh(); switch (args->how) { case LINUX_SIG_BLOCK: - p->p_sigmask |= (mask & ~DONTMASK); + p->p_sigmask |= (mask & ~sigcantmask); break; case LINUX_SIG_UNBLOCK: p->p_sigmask &= ~mask; break; case LINUX_SIG_SETMASK: - p->p_sigmask = (mask & ~DONTMASK); + p->p_sigmask = (mask & ~sigcantmask); break; default: error = EINVAL; @@ -176,38 +228,33 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args, } int -linux_siggetmask(struct proc *p, void *args, int *retval) +linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args, int *retval) { #ifdef DEBUG printf("Linux-emul(%d): siggetmask()\n", p->p_pid); #endif - *retval = bsd_to_linux_sigmask(p->p_sigmask); + *retval = bsd_to_linux_sigset(p->p_sigmask); return 0; } -struct linux_sigsetmask_args { - linux_sigset_t mask; -}; - int linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval) { int s; + sigset_t mask; #ifdef DEBUG printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask); #endif + *retval = bsd_to_linux_sigset(p->p_sigmask); + + mask = linux_to_bsd_sigset(args->mask); s = splhigh(); - p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK); + p->p_sigmask = mask & ~sigcantmask; splx(s); - *retval = bsd_to_linux_sigmask(p->p_sigmask); return 0; } -struct linux_sigpending_args { - linux_sigset_t *mask; -}; - int linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval) { @@ -216,32 +263,35 @@ linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval) #ifdef DEBUG printf("Linux-emul(%d): sigpending(*)\n", p->p_pid); #endif - linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask); + linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask); return copyout(&linux_sig, args->mask, sizeof(linux_sig)); } -struct linux_sigsuspend_args { - linux_sigset_t mask; -}; - int linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval) { - struct sigsuspend_args /* { - int mask; - } */ tmp; + struct sigsuspend_args tmp; + int error; #ifdef DEBUG printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask); #endif - tmp.mask = linux_to_bsd_sigmask(args->mask); + tmp.mask = linux_to_bsd_sigset(args->mask); return sigsuspend(p, &tmp , retval); } -struct linux_kill_args { - int pid; - int signum; -}; +int +linux_pause(struct proc *p, struct linux_pause_args *args,int *retval) +{ + struct sigsuspend_args tmp; + int error; + +#ifdef DEBUG + printf("Linux-emul(%d): pause()\n", p->p_pid); +#endif + tmp.mask = p->p_sigmask; + return sigsuspend(p, &tmp , retval); +} int linux_kill(struct proc *p, struct linux_kill_args *args, int *retval) diff --git a/sys/i386/linux/linux_socket.c b/sys/i386/linux/linux_socket.c index da4668c..63b33d5 100644 --- a/sys/i386/linux/linux_socket.c +++ b/sys/i386/linux/linux_socket.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_socket.c,v 1.2 1995/11/22 07:43:50 bde Exp $ + * $Id: linux_socket.c,v 1.3 1995/12/15 03:06:57 peter Exp $ */ /* XXX we use functions that might not exist. */ @@ -41,7 +41,7 @@ #include <netinet/in.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux_proto.h> static int linux_to_bsd_domain(int domain) @@ -555,11 +555,6 @@ linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval return getsockopt(p, &bsd_args, retval); } -struct linux_socketcall_args { - int what; - void *args; -}; - int linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval) { diff --git a/sys/i386/linux/linux_stats.c b/sys/i386/linux/linux_stats.c index 327343b..8d562e0 100644 --- a/sys/i386/linux/linux_stats.c +++ b/sys/i386/linux/linux_stats.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_stats.c,v 1.3 1995/11/22 07:43:51 bde Exp $ + * $Id: linux_stats.c,v 1.4 1996/01/30 12:23:17 peter Exp $ */ #include <sys/param.h> @@ -42,7 +42,8 @@ #include <sys/pipe.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_util.h> struct linux_newstat { unsigned short stat_dev; @@ -67,10 +68,6 @@ struct linux_newstat { unsigned long __unused5; }; -struct linux_newstat_args { - char *path; - struct linux_newstat *buf; -}; static int newstat_copyout(struct stat *buf, void *ubuf) @@ -97,9 +94,12 @@ int linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval) { struct stat buf; - struct linux_newstat tbuf; struct nameidata nd; int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path); @@ -115,44 +115,78 @@ linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval) return error; } +/* + * Get file status; this version does not follow links. + */ int -linux_newlstat(struct proc *p, struct linux_newstat_args *args, int *retval) +linux_newlstat(p, uap, retval) + struct proc *p; + struct linux_newlstat_args *uap; + int *retval; { - struct stat buf; - struct linux_newstat tbuf; - struct nameidata nd; - int error; + int error; + struct vnode *vp, *dvp; + struct stat sb, sb1; + struct nameidata nd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, uap->path); #ifdef DEBUG - printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, args->path); + printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, uap->path); #endif - NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p); - error = namei(&nd); - if (!error) { - error = vn_stat(nd.ni_vp, &buf, p); - vput(nd.ni_vp); - } - if (!error) - error = newstat_copyout(&buf, args->buf); - return error; + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, + uap->path, p); + error = namei(&nd); + if (error) + return (error); + /* + * For symbolic links, always return the attributes of its + * containing directory, except for mode, size, and links. + */ + vp = nd.ni_vp; + dvp = nd.ni_dvp; + if (vp->v_type != VLNK) { + if (dvp == vp) + vrele(dvp); + else + vput(dvp); + error = vn_stat(vp, &sb, p); + vput(vp); + if (error) + return (error); + } else { + error = vn_stat(dvp, &sb, p); + vput(dvp); + if (error) { + vput(vp); + return (error); + } + error = vn_stat(vp, &sb1, p); + vput(vp); + if (error) + return (error); + sb.st_mode &= ~S_IFDIR; + sb.st_mode |= S_IFLNK; + sb.st_nlink = sb1.st_nlink; + sb.st_size = sb1.st_size; + sb.st_blocks = sb1.st_blocks; + } + error = newstat_copyout(&sb, uap->buf); + return (error); } -struct linux_newfstat_args { - int fd; - struct linux_newstat *buf; -}; - int linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval) { - struct linux_newstat tbuf; struct filedesc *fdp = p->p_fd; struct file *fp; struct stat buf; int error; #ifdef DEBUG - printf("Linux-emul(%d): newlstat(%d, *)\n", p->p_pid, args->fd); + printf("Linux-emul(%d): newfstat(%d, *)\n", p->p_pid, args->fd); #endif if ((unsigned)args->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[args->fd]) == NULL) @@ -175,7 +209,7 @@ linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval) return error; } -struct linux_statfs { +struct linux_statfs_buf { long ftype; long fbsize; long fblocks; @@ -188,12 +222,6 @@ struct linux_statfs { long fspare[6]; }; - -struct linux_statfs_args { - char *path; - struct statfs *buf; -}; - int linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval) { @@ -201,8 +229,12 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval) struct nameidata *ndp; struct statfs *bsd_statfs; struct nameidata nd; - struct linux_statfs linux_statfs; + struct linux_statfs_buf linux_statfs_buf; int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path); @@ -217,32 +249,27 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval) if (error = VFS_STATFS(mp, bsd_statfs, p)) return error; bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - linux_statfs.ftype = bsd_statfs->f_type; - linux_statfs.fbsize = bsd_statfs->f_bsize; - linux_statfs.fblocks = bsd_statfs->f_blocks; - linux_statfs.fbfree = bsd_statfs->f_bfree; - linux_statfs.fbavail = bsd_statfs->f_bavail; - linux_statfs.fffree = bsd_statfs->f_ffree; - linux_statfs.ffiles = bsd_statfs->f_files; - linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0]; - linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1]; - linux_statfs.fnamelen = MAXNAMLEN; - return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, - sizeof(struct linux_statfs)); + linux_statfs_buf.ftype = bsd_statfs->f_type; + linux_statfs_buf.fbsize = bsd_statfs->f_bsize; + linux_statfs_buf.fblocks = bsd_statfs->f_blocks; + linux_statfs_buf.fbfree = bsd_statfs->f_bfree; + linux_statfs_buf.fbavail = bsd_statfs->f_bavail; + linux_statfs_buf.fffree = bsd_statfs->f_ffree; + linux_statfs_buf.ffiles = bsd_statfs->f_files; + linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs_buf.fnamelen = MAXNAMLEN; + return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf, + sizeof(struct linux_statfs_buf)); } -struct linux_fstatfs_args { - int fd; - struct statfs *buf; -}; - int linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval) { struct file *fp; struct mount *mp; struct statfs *bsd_statfs; - struct linux_statfs linux_statfs; + struct linux_statfs_buf linux_statfs_buf; int error; #ifdef DEBUG @@ -255,16 +282,16 @@ linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval) if (error = VFS_STATFS(mp, bsd_statfs, p)) return error; bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - linux_statfs.ftype = bsd_statfs->f_type; - linux_statfs.fbsize = bsd_statfs->f_bsize; - linux_statfs.fblocks = bsd_statfs->f_blocks; - linux_statfs.fbfree = bsd_statfs->f_bfree; - linux_statfs.fbavail = bsd_statfs->f_bavail; - linux_statfs.fffree = bsd_statfs->f_ffree; - linux_statfs.ffiles = bsd_statfs->f_files; - linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0]; - linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1]; - linux_statfs.fnamelen = MAXNAMLEN; - return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, - sizeof(struct linux_statfs)); + linux_statfs_buf.ftype = bsd_statfs->f_type; + linux_statfs_buf.fbsize = bsd_statfs->f_bsize; + linux_statfs_buf.fblocks = bsd_statfs->f_blocks; + linux_statfs_buf.fbfree = bsd_statfs->f_bfree; + linux_statfs_buf.fbavail = bsd_statfs->f_bavail; + linux_statfs_buf.fffree = bsd_statfs->f_ffree; + linux_statfs_buf.ffiles = bsd_statfs->f_files; + linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs_buf.fnamelen = MAXNAMLEN; + return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf, + sizeof(struct linux_statfs_buf)); } diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h new file mode 100644 index 0000000..6e0c5fd --- /dev/null +++ b/sys/i386/linux/linux_syscall.h @@ -0,0 +1,151 @@ +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * created from Id: syscalls.master,v 1.1 1996/03/02 19:04:15 peter Exp + */ + +#define LINUX_SYS_linux_setup 0 +#define LINUX_SYS_exit 1 +#define LINUX_SYS_linux_fork 2 +#define LINUX_SYS_read 3 +#define LINUX_SYS_write 4 +#define LINUX_SYS_linux_open 5 +#define LINUX_SYS_close 6 +#define LINUX_SYS_linux_waitpid 7 +#define LINUX_SYS_linux_creat 8 +#define LINUX_SYS_link 9 +#define LINUX_SYS_linux_unlink 10 +#define LINUX_SYS_linux_execve 11 +#define LINUX_SYS_linux_chdir 12 +#define LINUX_SYS_linux_time 13 +#define LINUX_SYS_linux_mknod 14 +#define LINUX_SYS_linux_chmod 15 +#define LINUX_SYS_linux_chown 16 +#define LINUX_SYS_linux_break 17 +#define LINUX_SYS_linux_stat 18 +#define LINUX_SYS_linux_lseek 19 +#define LINUX_SYS_getpid 20 +#define LINUX_SYS_linux_mount 21 +#define LINUX_SYS_linux_umount 22 +#define LINUX_SYS_setuid 23 +#define LINUX_SYS_getuid 24 +#define LINUX_SYS_linux_stime 25 +#define LINUX_SYS_linux_ptrace 26 +#define LINUX_SYS_linux_alarm 27 +#define LINUX_SYS_linux_fstat 28 +#define LINUX_SYS_linux_pause 29 +#define LINUX_SYS_linux_utime 30 +#define LINUX_SYS_linux_stty 31 +#define LINUX_SYS_linux_gtty 32 +#define LINUX_SYS_linux_access 33 +#define LINUX_SYS_linux_nice 34 +#define LINUX_SYS_linux_ftime 35 +#define LINUX_SYS_sync 36 +#define LINUX_SYS_linux_kill 37 +#define LINUX_SYS_linux_rename 38 +#define LINUX_SYS_linux_mkdir 39 +#define LINUX_SYS_linux_rmdir 40 +#define LINUX_SYS_dup 41 +#define LINUX_SYS_linux_pipe 42 +#define LINUX_SYS_linux_times 43 +#define LINUX_SYS_linux_prof 44 +#define LINUX_SYS_linux_brk 45 +#define LINUX_SYS_setgid 46 +#define LINUX_SYS_getgid 47 +#define LINUX_SYS_linux_signal 48 +#define LINUX_SYS_geteuid 49 +#define LINUX_SYS_getegid 50 +#define LINUX_SYS_acct 51 +#define LINUX_SYS_linux_phys 52 +#define LINUX_SYS_linux_lock 53 +#define LINUX_SYS_linux_ioctl 54 +#define LINUX_SYS_linux_fcntl 55 +#define LINUX_SYS_linux_mpx 56 +#define LINUX_SYS_setpgid 57 +#define LINUX_SYS_linux_ulimit 58 +#define LINUX_SYS_linux_olduname 59 +#define LINUX_SYS_umask 60 +#define LINUX_SYS_chroot 61 +#define LINUX_SYS_linux_ustat 62 +#define LINUX_SYS_dup2 63 +#define LINUX_SYS_getppid 64 +#define LINUX_SYS_getpgrp 65 +#define LINUX_SYS_setsid 66 +#define LINUX_SYS_linux_sigaction 67 +#define LINUX_SYS_linux_siggetmask 68 +#define LINUX_SYS_linux_sigsetmask 69 +#define LINUX_SYS_setreuid 70 +#define LINUX_SYS_setregid 71 +#define LINUX_SYS_linux_sigsuspend 72 +#define LINUX_SYS_linux_sigpending 73 +#define LINUX_SYS_osethostname 74 +#define LINUX_SYS_osetrlimit 75 +#define LINUX_SYS_ogetrlimit 76 +#define LINUX_SYS_getrusage 77 +#define LINUX_SYS_gettimeofday 78 +#define LINUX_SYS_settimeofday 79 +#define LINUX_SYS_getgroups 80 +#define LINUX_SYS_setgroups 81 +#define LINUX_SYS_linux_select 82 +#define LINUX_SYS_linux_symlink 83 +#define LINUX_SYS_ostat 84 +#define LINUX_SYS_linux_readlink 85 +#define LINUX_SYS_linux_uselib 86 +#define LINUX_SYS_swapon 87 +#define LINUX_SYS_reboot 88 +#define LINUX_SYS_linux_readdir 89 +#define LINUX_SYS_linux_mmap 90 +#define LINUX_SYS_munmap 91 +#define LINUX_SYS_linux_truncate 92 +#define LINUX_SYS_oftruncate 93 +#define LINUX_SYS_fchmod 94 +#define LINUX_SYS_fchown 95 +#define LINUX_SYS_getpriority 96 +#define LINUX_SYS_setpriority 97 +#define LINUX_SYS_profil 98 +#define LINUX_SYS_linux_statfs 99 +#define LINUX_SYS_linux_fstatfs 100 +#define LINUX_SYS_linux_ioperm 101 +#define LINUX_SYS_linux_socketcall 102 +#define LINUX_SYS_linux_ksyslog 103 +#define LINUX_SYS_linux_setitimer 104 +#define LINUX_SYS_linux_getitimer 105 +#define LINUX_SYS_linux_newstat 106 +#define LINUX_SYS_linux_newlstat 107 +#define LINUX_SYS_linux_newfstat 108 +#define LINUX_SYS_linux_uname 109 +#define LINUX_SYS_linux_iopl 110 +#define LINUX_SYS_linux_vhangup 111 +#define LINUX_SYS_linux_idle 112 +#define LINUX_SYS_linux_vm86 113 +#define LINUX_SYS_linux_wait4 114 +#define LINUX_SYS_linux_swapoff 115 +#define LINUX_SYS_linux_sysinfo 116 +#define LINUX_SYS_linux_ipc 117 +#define LINUX_SYS_fsync 118 +#define LINUX_SYS_linux_sigreturn 119 +#define LINUX_SYS_linux_clone 120 +#define LINUX_SYS_setdomainname 121 +#define LINUX_SYS_linux_newuname 122 +#define LINUX_SYS_linux_modify_ldt 123 +#define LINUX_SYS_linux_adjtimex 124 +#define LINUX_SYS_mprotect 125 +#define LINUX_SYS_linux_sigprocmask 126 +#define LINUX_SYS_linux_create_module 127 +#define LINUX_SYS_linux_init_module 128 +#define LINUX_SYS_linux_delete_module 129 +#define LINUX_SYS_linux_get_kernel_syms 130 +#define LINUX_SYS_linux_quotactl 131 +#define LINUX_SYS_linux_getpgid 132 +#define LINUX_SYS_fchdir 133 +#define LINUX_SYS_linux_bdflush 134 +#define LINUX_SYS_linux_personality 136 +#define LINUX_SYS_linux_llseek 140 +#define LINUX_SYS_linux_getdents 141 +#define LINUX_SYS_linux_newselect 142 +#define LINUX_SYS_flock 143 +#define LINUX_SYS_linux_msync 144 +#define LINUX_SYS_readv 145 +#define LINUX_SYS_writev 146 +#define LINUX_SYS_MAXSYSCALL 147 diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c index 0813e9b..4e32271 100644 --- a/sys/i386/linux/linux_sysent.c +++ b/sys/i386/linux/linux_sysent.c @@ -1,235 +1,171 @@ -/*- - * Copyright (c) 1994-1995 Søren Schmidt - * All rights reserved. +/* + * System call switch table. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: linux_sysent.c,v 1.3 1995/11/22 07:43:52 bde Exp $ + * DO NOT EDIT-- this file is automatically generated. + * created from Id: syscalls.master,v 1.1 1996/03/02 19:04:15 peter Exp */ -/* XXX we use functions that might not exist. */ -#define COMPAT_43 1 - +#include <sys/types.h> #include <sys/param.h> #include <sys/systm.h> -#include <sys/sysproto.h> #include <sys/sysent.h> -#include <sys/imgact.h> - +#include <sys/sysproto.h> #include <i386/linux/linux.h> -#include <i386/linux/sysproto.h> - -static struct sysent linux_sysent[] = { - 0, (sy_call_t *)linux_setup, /* 0 */ - 1, (sy_call_t *)exit, /* 1 */ - 0, (sy_call_t *)linux_fork, /* 2 */ - 3, (sy_call_t *)read, /* 3 */ - 3, (sy_call_t *)write, /* 4 */ - 3, (sy_call_t *)linux_open, /* 5 */ - 1, (sy_call_t *)close, /* 6 */ - 3, (sy_call_t *)linux_waitpid, /* 7 */ - 2, (sy_call_t *)linux_creat, /* 8 */ - 2, (sy_call_t *)link, /* 9 */ - 1, (sy_call_t *)unlink, /* 10 */ - 3, (sy_call_t *)execve, /* 11 */ - 1, (sy_call_t *)chdir, /* 12 */ - 1, (sy_call_t *)linux_time, /* 13 */ - 3, (sy_call_t *)linux_mknod, /* 14 */ - 2, (sy_call_t *)chmod, /* 15 */ - 3, (sy_call_t *)chown, /* 16 */ - 1, (sy_call_t *)linux_break, /* 17 */ - 2, (sy_call_t *)linux_stat, /* 18 */ - 3, (sy_call_t *)linux_lseek, /* 19 */ - 0, (sy_call_t *)getpid, /* 20 */ - 5, (sy_call_t *)linux_mount, /* 21 */ - 1, (sy_call_t *)linux_umount, /* 22 */ - 1, (sy_call_t *)setuid, /* 23 */ - 0, (sy_call_t *)getuid, /* 24 */ - 1, (sy_call_t *)linux_stime, /* 25 */ - 4, (sy_call_t *)linux_ptrace, /* 26 */ - 1, (sy_call_t *)linux_alarm, /* 27 */ - 2, (sy_call_t *)linux_fstat, /* 28 */ - 0, (sy_call_t *)linux_pause, /* 29 */ - 2, (sy_call_t *)linux_utime, /* 30 */ - 0, (sy_call_t *)linux_stty, /* 31 */ - 0, (sy_call_t *)linux_gtty, /* 32 */ - 2, (sy_call_t *)access, /* 33 */ - 1, (sy_call_t *)linux_nice, /* 34 */ - 0, (sy_call_t *)linux_ftime, /* 35 */ - 0, (sy_call_t *)sync, /* 36 */ - 2, (sy_call_t *)linux_kill, /* 37 */ - 2, (sy_call_t *)rename, /* 38 */ - 2, (sy_call_t *)mkdir, /* 39 */ - 1, (sy_call_t *)rmdir, /* 40 */ - 1, (sy_call_t *)dup, /* 41 */ - 1, (sy_call_t *)linux_pipe, /* 42 */ - 1, (sy_call_t *)linux_times, /* 43 */ - 0, (sy_call_t *)linux_prof, /* 44 */ - 1, (sy_call_t *)linux_brk, /* 45 */ - 1, (sy_call_t *)setgid, /* 46 */ - 0, (sy_call_t *)getgid, /* 47 */ - 2, (sy_call_t *)linux_signal, /* 48 */ - 0, (sy_call_t *)geteuid, /* 49 */ - 0, (sy_call_t *)getegid, /* 50 */ - 0, (sy_call_t *)acct, /* 51 */ - 0, (sy_call_t *)linux_phys, /* 52 */ - 0, (sy_call_t *)linux_lock, /* 53 */ - 3, (sy_call_t *)linux_ioctl, /* 54 */ - 3, (sy_call_t *)linux_fcntl, /* 55 */ - 0, (sy_call_t *)linux_mpx, /* 56 */ - 2, (sy_call_t *)setpgid, /* 57 */ - 0, (sy_call_t *)linux_ulimit, /* 58 */ - 1, (sy_call_t *)linux_olduname, /* 59 */ - 1, (sy_call_t *)umask, /* 60 */ - 1, (sy_call_t *)chroot, /* 61 */ - 2, (sy_call_t *)linux_ustat, /* 62 */ - 2, (sy_call_t *)dup2, /* 63 */ - 0, (sy_call_t *)getppid, /* 64 */ - 0, (sy_call_t *)getpgrp, /* 65 */ - 0, (sy_call_t *)setsid, /* 66 */ - 3, (sy_call_t *)linux_sigaction, /* 67 */ - 0, (sy_call_t *)linux_siggetmask, /* 68 */ - 1, (sy_call_t *)linux_sigsetmask, /* 69 */ - 2, (sy_call_t *)setreuid, /* 70 */ - 2, (sy_call_t *)setregid, /* 71 */ - 1, (sy_call_t *)linux_sigsuspend, /* 72 */ - 1, (sy_call_t *)linux_sigpending, /* 73 */ - 2, (sy_call_t *)osethostname, /* 74 */ - 2, (sy_call_t *)osetrlimit, /* 75 */ - 2, (sy_call_t *)ogetrlimit, /* 76 */ - 2, (sy_call_t *)getrusage, /* 77 */ - 2, (sy_call_t *)gettimeofday, /* 78 */ - 2, (sy_call_t *)settimeofday, /* 79 */ - 2, (sy_call_t *)getgroups, /* 80 */ - 2, (sy_call_t *)setgroups, /* 81 */ - 1, (sy_call_t *)linux_select, /* 82 */ - 2, (sy_call_t *)symlink, /* 83 */ - 2, (sy_call_t *)ostat, /* 84 */ - 3, (sy_call_t *)readlink, /* 85 */ - 1, (sy_call_t *)linux_uselib, /* 86 */ - 1, (sy_call_t *)swapon, /* 87 */ - 3, (sy_call_t *)reboot, /* 88 */ - 3, (sy_call_t *)linux_readdir, /* 89 */ - 1, (sy_call_t *)linux_mmap, /* 90 */ - 2, (sy_call_t *)munmap, /* 91 */ - 2, (sy_call_t *)otruncate, /* 92 */ - 2, (sy_call_t *)oftruncate, /* 93 */ - 2, (sy_call_t *)fchmod, /* 94 */ - 3, (sy_call_t *)fchown, /* 95 */ - 2, (sy_call_t *)getpriority, /* 96 */ - 3, (sy_call_t *)setpriority, /* 97 */ - 0, (sy_call_t *)profil, /* 98 */ - 2, (sy_call_t *)linux_statfs, /* 99 */ - 2, (sy_call_t *)linux_fstatfs, /* 100 */ - 3, (sy_call_t *)linux_ioperm, /* 101 */ - 2, (sy_call_t *)linux_socketcall, /* 102 */ - 3, (sy_call_t *)linux_syslog, /* 103 */ - 3, (sy_call_t *)setitimer, /* 104 */ - 2, (sy_call_t *)getitimer, /* 105 */ - 2, (sy_call_t *)linux_newstat, /* 106 */ - 2, (sy_call_t *)linux_newlstat, /* 107 */ - 2, (sy_call_t *)linux_newfstat, /* 108 */ - 2, (sy_call_t *)linux_uname, /* 109 */ - 1, (sy_call_t *)linux_iopl, /* 110 */ - 0, (sy_call_t *)linux_vhangup, /* 111 */ - 0, (sy_call_t *)linux_idle, /* 112 */ - 1, (sy_call_t *)linux_vm86, /* 113 */ - 4, (sy_call_t *)linux_wait4, /* 114 */ - 1, (sy_call_t *)linux_swapoff, /* 115 */ - 1, (sy_call_t *)linux_sysinfo, /* 116 */ - 4, (sy_call_t *)linux_ipc, /* 117 */ - 1, (sy_call_t *)fsync, /* 118 */ - 1, (sy_call_t *)linux_sigreturn, /* 119 */ - 0, (sy_call_t *)linux_clone, /* 120 */ - 2, (sy_call_t *)setdomainname, /* 121 */ - 1, (sy_call_t *)linux_newuname, /* 122 */ - 3, (sy_call_t *)linux_modify_ldt, /* 123 */ - 1, (sy_call_t *)linux_adjtimex, /* 124 */ - 3, (sy_call_t *)mprotect, /* 125 */ - 3, (sy_call_t *)linux_sigprocmask, /* 126 */ - 2, (sy_call_t *)linux_create_module, /* 127 */ - 4, (sy_call_t *)linux_init_module, /* 128 */ - 1, (sy_call_t *)linux_delete_module, /* 129 */ - 1, (sy_call_t *)linux_get_kernel_syms, /* 130 */ - 0, (sy_call_t *)linux_quotactl, /* 131 */ - 1, (sy_call_t *)linux_getpgid, /* 132 */ - 1, (sy_call_t *)fchdir, /* 133 */ - 0, (sy_call_t *)linux_bdflush, /* 134 */ -}; - -int bsd_to_linux_errno[ELAST] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 35, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 11,115,114, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100,101,102,103,104,105,106,107,108,109, - 110,111, 40, 36,112,113, 39, 11, 87,122, - 116, 66, 6, 6, 6, 6, 6, 37, 38, 9, - 6, -}; - -int bsd_to_linux_signal[NSIG] = { - 0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, - LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, - LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, - 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, - LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, - LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, - LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, - LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 -}; - -int linux_to_bsd_signal[LINUX_NSIG] = { - 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, - SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, - SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, - SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0 -}; - -int linux_fixup(int **stack_base, struct image_params *imgp) -{ - int *argv, *envp; +#include <i386/linux/linux_proto.h> - argv = *stack_base; - envp = *stack_base + (imgp->argc + 1); - (*stack_base)--; - **stack_base = (int)envp; - (*stack_base)--; - **stack_base = (int)argv; - (*stack_base)--; - **stack_base = (int)imgp->argc; - return 0; /* XXX */ -} +#ifdef COMPAT_43 +#define compat(n, name) n, (sy_call_t *)__CONCAT(o,name) +#else +#define compat(n, name) 0, (sy_call_t *)nosys +#endif -struct sysentvec linux_sysvec = { - sizeof (linux_sysent) / sizeof(linux_sysent[0]), - linux_sysent, - 0xff, - NSIG, - bsd_to_linux_signal, - ELAST, - bsd_to_linux_errno, - linux_fixup +/* The casts are bogus but will do for now. */ +struct sysent linux_sysent[] = { + { 0, (sy_call_t *)linux_setup }, /* 0 = linux_setup */ + { 1, (sy_call_t *)exit }, /* 1 = exit */ + { 0, (sy_call_t *)linux_fork }, /* 2 = linux_fork */ + { 3, (sy_call_t *)read }, /* 3 = read */ + { 3, (sy_call_t *)write }, /* 4 = write */ + { 3, (sy_call_t *)linux_open }, /* 5 = linux_open */ + { 1, (sy_call_t *)close }, /* 6 = close */ + { 3, (sy_call_t *)linux_waitpid }, /* 7 = linux_waitpid */ + { 2, (sy_call_t *)linux_creat }, /* 8 = linux_creat */ + { 2, (sy_call_t *)link }, /* 9 = link */ + { 1, (sy_call_t *)linux_unlink }, /* 10 = linux_unlink */ + { 3, (sy_call_t *)linux_execve }, /* 11 = linux_execve */ + { 1, (sy_call_t *)linux_chdir }, /* 12 = linux_chdir */ + { 1, (sy_call_t *)linux_time }, /* 13 = linux_time */ + { 3, (sy_call_t *)linux_mknod }, /* 14 = linux_mknod */ + { 2, (sy_call_t *)linux_chmod }, /* 15 = linux_chmod */ + { 3, (sy_call_t *)linux_chown }, /* 16 = linux_chown */ + { 1, (sy_call_t *)linux_break }, /* 17 = linux_break */ + { 2, (sy_call_t *)linux_stat }, /* 18 = linux_stat */ + { 3, (sy_call_t *)linux_lseek }, /* 19 = linux_lseek */ + { 0, (sy_call_t *)getpid }, /* 20 = getpid */ + { 0, (sy_call_t *)linux_mount }, /* 21 = linux_mount */ + { 0, (sy_call_t *)linux_umount }, /* 22 = linux_umount */ + { 1, (sy_call_t *)setuid }, /* 23 = setuid */ + { 0, (sy_call_t *)getuid }, /* 24 = getuid */ + { 0, (sy_call_t *)linux_stime }, /* 25 = linux_stime */ + { 0, (sy_call_t *)linux_ptrace }, /* 26 = linux_ptrace */ + { 1, (sy_call_t *)linux_alarm }, /* 27 = linux_alarm */ + { 2, (sy_call_t *)linux_fstat }, /* 28 = linux_fstat */ + { 0, (sy_call_t *)linux_pause }, /* 29 = linux_pause */ + { 2, (sy_call_t *)linux_utime }, /* 30 = linux_utime */ + { 0, (sy_call_t *)linux_stty }, /* 31 = linux_stty */ + { 0, (sy_call_t *)linux_gtty }, /* 32 = linux_gtty */ + { 2, (sy_call_t *)linux_access }, /* 33 = linux_access */ + { 0, (sy_call_t *)linux_nice }, /* 34 = linux_nice */ + { 0, (sy_call_t *)linux_ftime }, /* 35 = linux_ftime */ + { 0, (sy_call_t *)sync }, /* 36 = sync */ + { 2, (sy_call_t *)linux_kill }, /* 37 = linux_kill */ + { 2, (sy_call_t *)linux_rename }, /* 38 = linux_rename */ + { 2, (sy_call_t *)linux_mkdir }, /* 39 = linux_mkdir */ + { 1, (sy_call_t *)linux_rmdir }, /* 40 = linux_rmdir */ + { 1, (sy_call_t *)dup }, /* 41 = dup */ + { 1, (sy_call_t *)linux_pipe }, /* 42 = linux_pipe */ + { 1, (sy_call_t *)linux_times }, /* 43 = linux_times */ + { 0, (sy_call_t *)linux_prof }, /* 44 = linux_prof */ + { 1, (sy_call_t *)linux_brk }, /* 45 = linux_brk */ + { 1, (sy_call_t *)setgid }, /* 46 = setgid */ + { 0, (sy_call_t *)getgid }, /* 47 = getgid */ + { 2, (sy_call_t *)linux_signal }, /* 48 = linux_signal */ + { 0, (sy_call_t *)geteuid }, /* 49 = geteuid */ + { 0, (sy_call_t *)getegid }, /* 50 = getegid */ + { 1, (sy_call_t *)acct }, /* 51 = acct */ + { 0, (sy_call_t *)linux_phys }, /* 52 = linux_phys */ + { 0, (sy_call_t *)linux_lock }, /* 53 = linux_lock */ + { 3, (sy_call_t *)linux_ioctl }, /* 54 = linux_ioctl */ + { 3, (sy_call_t *)linux_fcntl }, /* 55 = linux_fcntl */ + { 0, (sy_call_t *)linux_mpx }, /* 56 = linux_mpx */ + { 2, (sy_call_t *)setpgid }, /* 57 = setpgid */ + { 0, (sy_call_t *)linux_ulimit }, /* 58 = linux_ulimit */ + { 1, (sy_call_t *)linux_olduname }, /* 59 = linux_olduname */ + { 1, (sy_call_t *)umask }, /* 60 = umask */ + { 1, (sy_call_t *)chroot }, /* 61 = chroot */ + { 0, (sy_call_t *)linux_ustat }, /* 62 = linux_ustat */ + { 2, (sy_call_t *)dup2 }, /* 63 = dup2 */ + { 0, (sy_call_t *)getppid }, /* 64 = getppid */ + { 0, (sy_call_t *)getpgrp }, /* 65 = getpgrp */ + { 0, (sy_call_t *)setsid }, /* 66 = setsid */ + { 3, (sy_call_t *)linux_sigaction }, /* 67 = linux_sigaction */ + { 0, (sy_call_t *)linux_siggetmask }, /* 68 = linux_siggetmask */ + { 1, (sy_call_t *)linux_sigsetmask }, /* 69 = linux_sigsetmask */ + { 2, (sy_call_t *)setreuid }, /* 70 = setreuid */ + { 2, (sy_call_t *)setregid }, /* 71 = setregid */ + { 1, (sy_call_t *)linux_sigsuspend }, /* 72 = linux_sigsuspend */ + { 1, (sy_call_t *)linux_sigpending }, /* 73 = linux_sigpending */ + { 2, (sy_call_t *)osethostname }, /* 74 = osethostname */ + { 2, (sy_call_t *)osetrlimit }, /* 75 = osetrlimit */ + { 2, (sy_call_t *)ogetrlimit }, /* 76 = ogetrlimit */ + { 2, (sy_call_t *)getrusage }, /* 77 = getrusage */ + { 2, (sy_call_t *)gettimeofday }, /* 78 = gettimeofday */ + { 2, (sy_call_t *)settimeofday }, /* 79 = settimeofday */ + { 2, (sy_call_t *)getgroups }, /* 80 = getgroups */ + { 2, (sy_call_t *)setgroups }, /* 81 = setgroups */ + { 1, (sy_call_t *)linux_select }, /* 82 = linux_select */ + { 2, (sy_call_t *)linux_symlink }, /* 83 = linux_symlink */ + { 2, (sy_call_t *)ostat }, /* 84 = ostat */ + { 3, (sy_call_t *)linux_readlink }, /* 85 = linux_readlink */ + { 1, (sy_call_t *)linux_uselib }, /* 86 = linux_uselib */ + { 1, (sy_call_t *)swapon }, /* 87 = swapon */ + { 1, (sy_call_t *)reboot }, /* 88 = reboot */ + { 3, (sy_call_t *)linux_readdir }, /* 89 = linux_readdir */ + { 1, (sy_call_t *)linux_mmap }, /* 90 = linux_mmap */ + { 2, (sy_call_t *)munmap }, /* 91 = munmap */ + { 2, (sy_call_t *)linux_truncate }, /* 92 = linux_truncate */ + { 2, (sy_call_t *)oftruncate }, /* 93 = oftruncate */ + { 2, (sy_call_t *)fchmod }, /* 94 = fchmod */ + { 3, (sy_call_t *)fchown }, /* 95 = fchown */ + { 2, (sy_call_t *)getpriority }, /* 96 = getpriority */ + { 3, (sy_call_t *)setpriority }, /* 97 = setpriority */ + { 4, (sy_call_t *)profil }, /* 98 = profil */ + { 2, (sy_call_t *)linux_statfs }, /* 99 = linux_statfs */ + { 2, (sy_call_t *)linux_fstatfs }, /* 100 = linux_fstatfs */ + { 3, (sy_call_t *)linux_ioperm }, /* 101 = linux_ioperm */ + { 2, (sy_call_t *)linux_socketcall }, /* 102 = linux_socketcall */ + { 1, (sy_call_t *)linux_ksyslog }, /* 103 = linux_ksyslog */ + { 3, (sy_call_t *)linux_setitimer }, /* 104 = linux_setitimer */ + { 2, (sy_call_t *)linux_getitimer }, /* 105 = linux_getitimer */ + { 2, (sy_call_t *)linux_newstat }, /* 106 = linux_newstat */ + { 2, (sy_call_t *)linux_newlstat }, /* 107 = linux_newlstat */ + { 2, (sy_call_t *)linux_newfstat }, /* 108 = linux_newfstat */ + { 1, (sy_call_t *)linux_uname }, /* 109 = linux_uname */ + { 1, (sy_call_t *)linux_iopl }, /* 110 = linux_iopl */ + { 0, (sy_call_t *)linux_vhangup }, /* 111 = linux_vhangup */ + { 0, (sy_call_t *)linux_idle }, /* 112 = linux_idle */ + { 0, (sy_call_t *)linux_vm86 }, /* 113 = linux_vm86 */ + { 4, (sy_call_t *)linux_wait4 }, /* 114 = linux_wait4 */ + { 0, (sy_call_t *)linux_swapoff }, /* 115 = linux_swapoff */ + { 0, (sy_call_t *)linux_sysinfo }, /* 116 = linux_sysinfo */ + { 5, (sy_call_t *)linux_ipc }, /* 117 = linux_ipc */ + { 1, (sy_call_t *)fsync }, /* 118 = fsync */ + { 1, (sy_call_t *)linux_sigreturn }, /* 119 = linux_sigreturn */ + { 0, (sy_call_t *)linux_clone }, /* 120 = linux_clone */ + { 2, (sy_call_t *)setdomainname }, /* 121 = setdomainname */ + { 1, (sy_call_t *)linux_newuname }, /* 122 = linux_newuname */ + { 3, (sy_call_t *)linux_modify_ldt }, /* 123 = linux_modify_ldt */ + { 0, (sy_call_t *)linux_adjtimex }, /* 124 = linux_adjtimex */ + { 3, (sy_call_t *)mprotect }, /* 125 = mprotect */ + { 3, (sy_call_t *)linux_sigprocmask }, /* 126 = linux_sigprocmask */ + { 0, (sy_call_t *)linux_create_module }, /* 127 = linux_create_module */ + { 0, (sy_call_t *)linux_init_module }, /* 128 = linux_init_module */ + { 0, (sy_call_t *)linux_delete_module }, /* 129 = linux_delete_module */ + { 0, (sy_call_t *)linux_get_kernel_syms }, /* 130 = linux_get_kernel_syms */ + { 0, (sy_call_t *)linux_quotactl }, /* 131 = linux_quotactl */ + { 1, (sy_call_t *)linux_getpgid }, /* 132 = linux_getpgid */ + { 1, (sy_call_t *)fchdir }, /* 133 = fchdir */ + { 0, (sy_call_t *)linux_bdflush }, /* 134 = linux_bdflush */ + { 0, (sy_call_t *)nosys }, /* 135 = sysfs */ + { 1, (sy_call_t *)linux_personality }, /* 136 = linux_personality */ + { 0, (sy_call_t *)nosys }, /* 137 = afs_syscall */ + { 0, (sy_call_t *)nosys }, /* 138 = setfsuid */ + { 0, (sy_call_t *)nosys }, /* 139 = getfsuid */ + { 5, (sy_call_t *)linux_llseek }, /* 140 = linux_llseek */ + { 3, (sy_call_t *)linux_getdents }, /* 141 = linux_getdents */ + { 5, (sy_call_t *)linux_newselect }, /* 142 = linux_newselect */ + { 2, (sy_call_t *)flock }, /* 143 = flock */ + { 3, (sy_call_t *)linux_msync }, /* 144 = linux_msync */ + { 3, (sy_call_t *)readv }, /* 145 = readv */ + { 3, (sy_call_t *)writev }, /* 146 = writev */ }; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c new file mode 100644 index 0000000..9278102 --- /dev/null +++ b/sys/i386/linux/linux_sysvec.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: linux_sysent.c,v 1.4 1996/01/14 10:59:57 sos Exp $ + */ + +/* XXX we use functions that might not exist. */ +#define COMPAT_43 1 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/imgact.h> +#include <sys/signalvar.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_prot.h> +#include <vm/lock.h> +#include <vm/vm_kern.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_pager.h> +#include <vm/vm_extern.h> +#include <sys/user.h> +#include <sys/exec.h> +#include <machine/cpu.h> +#include <machine/frame.h> +#include <machine/reg.h> +#include <machine/specialreg.h> +#include <machine/psl.h> +#include <machine/sysarch.h> +#include <machine/md_var.h> + +#include <i386/linux/linux.h> +#include <i386/linux/linux_proto.h> +#include <i386/linux/linux_syscall.h> + +/* + * Linux syscalls return negative errno's, we do positive and map them + */ +int bsd_to_linux_errno[ELAST] = { + -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, + -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, + -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, + -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, + -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, + -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, + -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, + -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, + -6, +}; + +int bsd_to_linux_signal[NSIG] = { + 0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, + LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0, + LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, + 0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, + LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, + LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, + LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, + LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2 +}; + +int linux_to_bsd_signal[LINUX_NSIG] = { + 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT, + SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, + SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO, + SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0 +}; + +int linux_fixup(int **stack_base, struct image_params *imgp) +{ + int *argv, *envp; + + argv = *stack_base; + envp = *stack_base + (imgp->argc + 1); + (*stack_base)--; + **stack_base = (int)envp; + (*stack_base)--; + **stack_base = (int)argv; + (*stack_base)--; + **stack_base = (int)imgp->argc; + return 0; /* XXX */ +} + +extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; + +static void linux_sendsig(sig_t action, + int sig, + int returnmask, + unsigned code); + +extern int _ucodesel, _udatasel; + +/* + * Send an interrupt to process. + * + * Stack is set up to allow sigcode stored + * in u. to call routine, followed by kcall + * to sigreturn routine below. After sigreturn + * resets the signal mask, the stack, and the + * frame pointer, it returns to the user + * specified pc, psl. + */ + +static void +linux_sendsig(catcher, sig, mask, code) + sig_t catcher; + int sig; + int mask; + unsigned code; +{ + register struct proc *p = curproc; + register int *regs; + struct linux_sigframe *fp, frame; + struct sigacts *psp = p->p_sigacts; + int oonstack; + + regs = p->p_md.md_regs; + oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + +#ifdef DEBUG + printf("Linux-emul(%d): linux_sendsig(%8x, %d, %d, %d)\n", + p->p_pid, catcher, sig, mask, code); +#endif + /* + * Allocate space for the signal handler context. + */ + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && + (psp->ps_sigonstack & sigmask(sig))) { + fp = (struct linux_sigframe *)(psp->ps_sigstk.ss_sp + + psp->ps_sigstk.ss_size - sizeof(struct linux_sigframe)); + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else { + fp = (struct linux_sigframe *)regs[tESP] - 1; + } + + /* + * grow() will return FALSE if the fp will not fit inside the stack + * and the stack can not be grown. useracc will return FALSE + * if access is denied. + */ + if ((grow(p, (int)fp) == FALSE) || + (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + SIGACTION(p, SIGILL) = SIG_DFL; + sig = sigmask(SIGILL); + p->p_sigignore &= ~sig; + p->p_sigcatch &= ~sig; + p->p_sigmask &= ~sig; + psignal(p, SIGILL); + return; + } + + /* + * Build the argument list for the signal handler. + */ + if (p->p_sysent->sv_sigtbl) { + if (sig < p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[sig]; + else + sig = p->p_sysent->sv_sigsize + 1; + } + + frame.sf_handler = catcher; + frame.sf_sig = sig; + + /* + * Build the signal context to be used by sigreturn. + */ + frame.sf_sc.sc_mask = mask; + __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs)); + __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs)); + frame.sf_sc.sc_es = regs[tES]; + frame.sf_sc.sc_ds = regs[tDS]; + frame.sf_sc.sc_edi = regs[tEDI]; + frame.sf_sc.sc_esi = regs[tESI]; + frame.sf_sc.sc_ebp = regs[tEBP]; + frame.sf_sc.sc_ebx = regs[tEBX]; + frame.sf_sc.sc_edx = regs[tEDX]; + frame.sf_sc.sc_ecx = regs[tECX]; + frame.sf_sc.sc_eax = regs[tEAX]; + frame.sf_sc.sc_eip = regs[tEIP]; + frame.sf_sc.sc_cs = regs[tCS]; + frame.sf_sc.sc_eflags = regs[tEFLAGS]; + frame.sf_sc.sc_esp_at_signal = regs[tESP]; + frame.sf_sc.sc_ss = regs[tSS]; + frame.sf_sc.sc_err = regs[tERR]; + frame.sf_sc.sc_trapno = code; /* XXX ???? */ + + if (copyout(&frame, fp, sizeof(frame)) != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + sigexit(p, SIGILL); + /* NOTREACHED */ + } + + /* + * Build context to run handler in. + */ + regs[tESP] = (int)fp; + regs[tEIP] = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); + regs[tEFLAGS] &= ~PSL_VM; + regs[tCS] = _ucodesel; + regs[tDS] = _udatasel; + regs[tES] = _udatasel; + regs[tSS] = _udatasel; +} + +/* + * System call to cleanup state after a signal + * has been taken. Reset signal mask and + * stack state from context left by sendsig (above). + * Return to previous pc and psl as specified by + * context left by sendsig. Check carefully to + * make sure that the user has not modified the + * psl to gain improper privileges or to cause + * a machine fault. + */ +int +linux_sigreturn(p, args, retval) + struct proc *p; + struct linux_sigreturn_args *args; + int *retval; +{ + struct linux_sigcontext *scp, context; + register int *regs; + int eflags; + + regs = p->p_md.md_regs; + +#ifdef DEBUG + printf("Linux-emul(%d): linux_sigreturn(%8x)\n", p->p_pid, args->scp); +#endif + /* + * The trampoline code hands us the context. + * It is unsafe to keep track of it ourselves, in the event that a + * program jumps out of a signal handler. + */ + scp = args->scp; + if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) + return (EFAULT); + + /* + * Check for security violations. + */ +#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) + eflags = context.sc_eflags; + /* + * XXX do allow users to change the privileged flag PSL_RF. The + * cpu sets PSL_RF in tf_eflags for faults. Debuggers should + * sometimes set it there too. tf_eflags is kept in the signal + * context during signal handling and there is no other place + * to remember it, so the PSL_RF bit may be corrupted by the + * signal handler without us knowing. Corruption of the PSL_RF + * bit at worst causes one more or one less debugger trap, so + * allowing it is fairly harmless. + */ + if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs[tEFLAGS] & ~PSL_RF)) { + return(EINVAL); + } + + /* + * Don't allow users to load a valid privileged %cs. Let the + * hardware check for invalid selectors, excess privilege in + * other selectors, invalid %eip's and invalid %esp's. + */ +#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) + if (!CS_SECURE(context.sc_cs)) { + trapsignal(p, SIGBUS, T_PROTFLT); + return(EINVAL); + } + + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; + p->p_sigmask = context.sc_mask &~ + (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); + /* + * Restore signal context. + */ + /* %fs and %gs were restored by the trampoline. */ + regs[tES] = context.sc_es; + regs[tDS] = context.sc_ds; + regs[tEDI] = context.sc_edi; + regs[tESI] = context.sc_esi; + regs[tEBP] = context.sc_ebp; + regs[tEBX] = context.sc_ebx; + regs[tEDX] = context.sc_edx; + regs[tECX] = context.sc_ecx; + regs[tEAX] = context.sc_eax; + regs[tEIP] = context.sc_eip; + regs[tCS] = context.sc_cs; + regs[tEFLAGS] = eflags; + regs[tESP] = context.sc_esp_at_signal; + regs[tSS] = context.sc_ss; + + return (EJUSTRETURN); +} + +static void +linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params) +{ + int i; + args[0] = tf->tf_ebx; + args[1] = tf->tf_ecx; + args[2] = tf->tf_edx; + args[3] = tf->tf_esi; + args[4] = tf->tf_edi; + *params = NULL; /* no copyin */ +} + +extern char linux_sigcode[]; +extern int linux_szsigcode; + +struct sysentvec linux_sysvec = { + sizeof (linux_sysent) / sizeof(linux_sysent[0]), + linux_sysent, + 0xff, + NSIG, + bsd_to_linux_signal, + ELAST, + bsd_to_linux_errno, + linux_fixup, + linux_sendsig, + linux_sigcode, + &linux_szsigcode, + linux_prepsyscall, +}; diff --git a/sys/i386/linux/linux_util.c b/sys/i386/linux/linux_util.c new file mode 100644 index 0000000..1785fd3 --- /dev/null +++ b/sys/i386/linux/linux_util.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1994 Christos Zoulas + * Copyright (c) 1995 Frank van der Linden + * Copyright (c) 1995 Scott Bartram + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/filedesc.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/vnode.h> + +#include <i386/linux/linux_util.h> + +const char linux_emul_path[] = "/compat/linux"; + +/* + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a seperate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +linux_emul_find(p, sgp, prefix, path, pbuf, cflag) + struct proc *p; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + int error; + char *ptr, *buf, *cp; + size_t sz, len; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--); + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } + else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the linux_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + /* XXX: prototype should have const here for NDINIT */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, + (char *) linux_emul_path, p); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + + if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) { + goto done; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) + != 0) { + goto done; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto done; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + +done: + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + return error; +} diff --git a/sys/i386/linux/linux_generic.c b/sys/i386/linux/linux_util.h index da528c1..46edfc5 100644 --- a/sys/i386/linux/linux_generic.c +++ b/sys/i386/linux/linux_util.h @@ -1,18 +1,19 @@ -/*- - * Copyright (c) 1995 Søren Schmidt +/* + * Copyright (c) 1994 Christos Zoulas + * Copyright (c) 1995 Frank van der Linden + * Copyright (c) 1995 Scott Bartram * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission + * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -25,37 +26,67 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_generic.c,v 1.3 1995/12/09 04:31:47 peter Exp $ + * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp + * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp + * $Id$ */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/exec.h> +/* + * This file is pretty much the same as Christos' svr4_util.h + * (for now). + */ -#include <vm/vm.h> /* XXX for a macro in exec.h */ +#ifndef _LINUX_UTIL_H_ +#define _LINUX_UTIL_H_ + +#include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> #include <machine/vmparam.h> +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/cdefs.h> -#include <i386/linux/linux.h> +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif -static caddr_t ua_ptr = NULL; +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); -caddr_t ua_alloc_init(int len) +static __inline caddr_t +stackgap_init() { - caddr_t ptr; - - ptr = (caddr_t)ALIGN((PS_STRINGS)); - ptr -= SPARE_USRSPACE; - ua_ptr = (caddr_t)(ptr + ALIGN(len)); - return ptr; +#define szsigcode (*(curproc->p_sysent->sv_szsigcode), sizeof(char *)) + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); } -caddr_t ua_alloc(int len) -{ - caddr_t ptr; - ptr = ua_ptr; - ua_ptr += ALIGN(len); - return ptr; +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; } + +#ifdef DEBUG_LINUX +#define DPRINTF(a) printf a; +#else +#define DPRINTF(a) +#endif + +extern const char linux_emul_path[]; + +int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *, + char **, int)); + +#define CHECKALTEXIST(p, sgp, path) \ + linux_emul_find(p, sgp, linux_emul_path, path, &(path), 0) + +#define CHECKALTCREAT(p, sgp, path) \ + linux_emul_find(p, sgp, linux_emul_path, path, &(path), 1) + +#endif /* !_LINUX_UTIL_H_ */ diff --git a/sys/i386/linux/sysproto.h b/sys/i386/linux/sysproto.h deleted file mode 100644 index ea6ab57..0000000 --- a/sys/i386/linux/sysproto.h +++ /dev/null @@ -1,210 +0,0 @@ -/*- - * Prototypes for linux system call functions. - * Bruce Evans, November 1995. - * This file is in the public domain. - */ - -#ifndef _I386_LINUX_SYSPROTO_H_ -#define _I386_LINUX_SYSPROTO_H_ - -struct linux_accept_args; -struct linux_alarm_args; -struct linux_bind_args; -struct linux_brk_args; -struct linux_connect_args; -struct linux_creat_args; -struct linux_fcntl_args; -struct linux_fstatfs_args; -struct linux_getpeername_args; -struct linux_getpgid_args; -struct linux_getsockname_args; -struct linux_getsockopt_args; -struct linux_ioctl_args; -struct linux_ipc_args; -struct linux_kill_args; -struct linux_listen_args; -struct linux_lseek_args; -struct linux_mmap_args; -struct linux_mknod_args; -struct linux_newfstat_args; -struct linux_newstat_args; -struct linux_newuname_args; -struct linux_open_args; -struct linux_pipe_args; -struct linux_readdir_args; -struct linux_recv_args; -struct linux_recvfrom_args; -struct linux_select_args; -struct linux_send_args; -struct linux_sendto_args; -struct linux_setsockopt_args; -struct linux_shutdown_args; -struct linux_sigaction_args; -struct linux_sigpending_args; -struct linux_sigprocmask_args; -struct linux_sigsetmask_args; -struct linux_sigsuspend_args; -struct linux_socket_args; -struct linux_socketcall_args; -struct linux_socketpair_args; -struct linux_statfs_args; -struct linux_time_args; -struct linux_tms_args; -struct linux_uselib_args; -struct linux_utime_args; -struct linux_wait4_args; -struct linux_waitpid_args; - -/* linux_dummy.c */ -int linux_adjtimex __P((struct proc *p, void *args, int *retval)); -int linux_bdflush __P((struct proc *p, void *args, int *retval)); -int linux_break __P((struct proc *p, void *args, int *retval)); -int linux_clone __P((struct proc *p, void *args, int *retval)); -int linux_create_module __P((struct proc *p, void *args, int *retval)); -int linux_delete_module __P((struct proc *p, void *args, int *retval)); -int linux_fstat __P((struct proc *p, void *args, int *retval)); -int linux_ftime __P((struct proc *p, void *args, int *retval)); -int linux_get_kernel_syms __P((struct proc *p, void *args, int *retval)); -int linux_gtty __P((struct proc *p, void *args, int *retval)); -int linux_idle __P((struct proc *p, void *args, int *retval)); -int linux_init_module __P((struct proc *p, void *args, int *retval)); -int linux_ioperm __P((struct proc *p, void *args, int *retval)); -int linux_iopl __P((struct proc *p, void *args, int *retval)); -int linux_lock __P((struct proc *p, void *args, int *retval)); -int linux_modify_ldt __P((struct proc *p, void *args, int *retval)); -int linux_mount __P((struct proc *p, void *args, int *retval)); -int linux_mpx __P((struct proc *p, void *args, int *retval)); -int linux_nice __P((struct proc *p, void *args, int *retval)); -int linux_olduname __P((struct proc *p, void *args, int *retval)); -int linux_pause __P((struct proc *p, void *args, int *retval)); -int linux_phys __P((struct proc *p, void *args, int *retval)); -int linux_prof __P((struct proc *p, void *args, int *retval)); -int linux_ptrace __P((struct proc *p, void *args, int *retval)); -int linux_quotactl __P((struct proc *p, void *args, int *retval)); -int linux_setup __P((struct proc *p, void *args, int *retval)); -int linux_signal __P((struct proc *p, void *args, int *retval)); -int linux_sigreturn __P((struct proc *p, void *args, int *retval)); -int linux_stat __P((struct proc *p, void *args, int *retval)); -int linux_stime __P((struct proc *p, void *args, int *retval)); -int linux_stty __P((struct proc *p, void *args, int *retval)); -int linux_swapoff __P((struct proc *p, void *args, int *retval)); -int linux_sysinfo __P((struct proc *p, void *args, int *retval)); -int linux_syslog __P((struct proc *p, void *args, int *retval)); -int linux_ulimit __P((struct proc *p, void *args, int *retval)); -int linux_umount __P((struct proc *p, void *args, int *retval)); -int linux_uname __P((struct proc *p, void *args, int *retval)); -int linux_ustat __P((struct proc *p, void *args, int *retval)); -int linux_vhangup __P((struct proc *p, void *args, int *retval)); -int linux_vm86 __P((struct proc *p, void *args, int *retval)); - -/* linux_file.c */ -int linux_creat __P((struct proc *p, struct linux_creat_args *args, - int *retval)); -int linux_fcntl __P((struct proc *p, struct linux_fcntl_args *args, - int *retval)); -int linux_lseek __P((struct proc *p, struct linux_lseek_args *args, - int *retval)); -int linux_open __P((struct proc *p, struct linux_open_args *args, - int *retval)); -int linux_readdir __P((struct proc *p, struct linux_readdir_args *args, - int *retval)); - -/* linux_ioctl.c */ -int linux_ioctl __P((struct proc *p, struct linux_ioctl_args *args, - int *retval)); - -/* linux_ipc.c */ -int linux_ipc __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_msgctl __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_msgget __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_msgrcv __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_msgsnd __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_semctl __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_semget __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_semop __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_shmat __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_shmctl __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_shmdt __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); -int linux_shmget __P((struct proc *p, struct linux_ipc_args *args, - int *retval)); - -/* linux_misc.c */ -int linux_alarm __P((struct proc *p, struct linux_alarm_args *args, - int *retval)); -int linux_brk __P((struct proc *p, struct linux_brk_args *args, - int *retval)); -int linux_fork __P((struct proc *p, void *args, int *retval)); -int linux_getpgid __P((struct proc *p, struct linux_getpgid_args *args, - int *retval)); -int linux_mknod __P((struct proc *p, struct linux_mknod_args *args, - int *retval)); -int linux_mmap __P((struct proc *p, struct linux_mmap_args *args, - int *retval)); -int linux_newuname __P((struct proc *p, struct linux_newuname_args *args, - int *retval)); -int linux_pipe __P((struct proc *p, struct linux_pipe_args *args, - int *retval)); -int linux_select __P((struct proc *p, struct linux_select_args *args, - int *retval)); -int linux_time __P((struct proc *p, struct linux_time_args *args, - int *retval)); -int linux_times __P((struct proc *p, struct linux_tms_args *args, - int *retval)); -int linux_uselib __P((struct proc *p, struct linux_uselib_args *args, - int *retval)); -int linux_utime __P((struct proc *p, struct linux_utime_args *args, - int *retval)); -int linux_wait4 __P((struct proc *p, struct linux_wait4_args *args, - int *retval)); -int linux_waitpid __P((struct proc *p, struct linux_waitpid_args *args, - int *retval)); - -/* linux_signal.c */ -int linux_kill __P((struct proc *p, struct linux_kill_args *args, - int *retval)); -int linux_sigaction __P((struct proc *p, struct linux_sigaction_args *args, - int *retval)); -int linux_siggetmask __P((struct proc *p, void *args, int *retval)); -int linux_sigpending __P((struct proc *p, - struct linux_sigpending_args *args, int *retval)); -int linux_sigprocmask __P((struct proc *p, - struct linux_sigprocmask_args *args, - int *retval)); -int linux_sigsetmask __P((struct proc *p, - struct linux_sigsetmask_args *args, int *retval)); -int linux_sigsuspend __P((struct proc *p, - struct linux_sigsuspend_args *args, int *retval)); - -/* linux_socket.c */ -int linux_socketcall __P((struct proc *p, - struct linux_socketcall_args *args, int *retval)); - -/* linux_stats.c */ -int linux_fstatfs __P((struct proc *p, struct linux_fstatfs_args *args, - int *retval)); -int linux_newfstat __P((struct proc *p, struct linux_newfstat_args *args, - int *retval)); -int linux_newlstat __P((struct proc *p, struct linux_newstat_args *args, - int *retval)); -int linux_newstat __P((struct proc *p, struct linux_newstat_args *args, - int *retval)); -int linux_statfs __P((struct proc *p, struct linux_statfs_args *args, - int *retval)); - -struct image_params; -int linux_fixup __P((int **stack_base, struct image_params *iparams)); - -extern struct sysentvec linux_sysvec; - -#endif /* !_I386_LINUX_SYSPROTO_H_ */ |