diff --git a/sys/alpha/linux/linux.h b/sys/alpha/linux/linux.h index c0fbc0a20fe2..f6bab97e92bb 100644 --- a/sys/alpha/linux/linux.h +++ b/sys/alpha/linux/linux.h @@ -1,429 +1,481 @@ /*- * 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 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. * - * $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_ #define _I386_LINUX_LINUX_H_ typedef unsigned short linux_uid_t; typedef unsigned short linux_gid_t; typedef unsigned short linux_dev_t; typedef unsigned long linux_ino_t; typedef unsigned short linux_mode_t; typedef unsigned short linux_nlink_t; typedef long linux_time_t; typedef long linux_clock_t; typedef char * linux_caddr_t; typedef long linux_off_t; typedef struct { long val[2]; } linux_fsid_t; typedef int linux_pid_t; typedef unsigned long linux_sigset_t; typedef void (*linux_handler_t)(int); typedef struct { void (*sa_handler)(int); linux_sigset_t sa_mask; unsigned long sa_flags; void (*sa_restorer)(void); } 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 /* signal numbers */ #define LINUX_SIGHUP 1 #define LINUX_SIGINT 2 #define LINUX_SIGQUIT 3 #define LINUX_SIGILL 4 #define LINUX_SIGTRAP 5 #define LINUX_SIGABRT 6 #define LINUX_SIGIOT 6 #define LINUX_SIGUNUSED 7 #define LINUX_SIGFPE 8 #define LINUX_SIGKILL 9 #define LINUX_SIGUSR1 10 #define LINUX_SIGSEGV 11 #define LINUX_SIGUSR2 12 #define LINUX_SIGPIPE 13 #define LINUX_SIGALRM 14 #define LINUX_SIGTERM 15 #define LINUX_SIGSTKFLT 16 #define LINUX_SIGCHLD 17 #define LINUX_SIGCONT 18 #define LINUX_SIGSTOP 19 #define LINUX_SIGTSTP 20 #define LINUX_SIGTTIN 21 #define LINUX_SIGTTOU 22 #define LINUX_SIGIO 23 #define LINUX_SIGPOLL LINUX_SIGIO #define LINUX_SIGURG LINUX_SIGIO #define LINUX_SIGXCPU 24 #define LINUX_SIGXFSZ 25 #define LINUX_SIGVTALRM 26 #define LINUX_SIGPROF 27 #define LINUX_SIGWINCH 28 #define LINUX_SIGLOST 29 #define LINUX_SIGPWR 30 #define LINUX_SIGBUS LINUX_SIGUNUSED #define LINUX_NSIG 32 /* sigaction flags */ #define LINUX_SA_NOCLDSTOP 0x00000001 #define LINUX_SA_ONSTACK 0x08000000 #define LINUX_SA_RESTART 0x10000000 #define LINUX_SA_INTERRUPT 0x20000000 #define LINUX_SA_NOMASK 0x40000000 #define LINUX_SA_ONESHOT 0x80000000 /* sigprocmask actions */ #define LINUX_SIG_BLOCK 0 #define LINUX_SIG_UNBLOCK 1 #define LINUX_SIG_SETMASK 2 /* termio commands */ #define LINUX_TCGETS 0x5401 #define LINUX_TCSETS 0x5402 #define LINUX_TCSETSW 0x5403 #define LINUX_TCSETSF 0x5404 #define LINUX_TCGETA 0x5405 #define LINUX_TCSETA 0x5406 #define LINUX_TCSETAW 0x5407 #define LINUX_TCSETAF 0x5408 #define LINUX_TCSBRK 0x5409 #define LINUX_TCXONC 0x540A #define LINUX_TCFLSH 0x540B #define LINUX_TIOCEXCL 0x540C #define LINUX_TIOCNXCL 0x540D #define LINUX_TIOCSCTTY 0x540E #define LINUX_TIOCGPGRP 0x540F #define LINUX_TIOCSPGRP 0x5410 #define LINUX_TIOCOUTQ 0x5411 #define LINUX_TIOCSTI 0x5412 #define LINUX_TIOCGWINSZ 0x5413 #define LINUX_TIOCSWINSZ 0x5414 #define LINUX_TIOCMGET 0x5415 #define LINUX_TIOCMBIS 0x5416 #define LINUX_TIOCMBIC 0x5417 #define LINUX_TIOCMSET 0x5418 #define LINUX_TIOCGSOFTCAR 0x5419 #define LINUX_TIOCSSOFTCAR 0x541A #define LINUX_FIONREAD 0x541B #define LINUX_TIOCINQ FIONREAD #define LINUX_TIOCLINUX 0x541C #define LINUX_TIOCCONS 0x541D #define LINUX_TIOCGSERIAL 0x541E #define LINUX_TIOCSSERIAL 0x541F #define LINUX_TIOCPKT 0x5420 #define LINUX_FIONBIO 0x5421 #define LINUX_TIOCNOTTY 0x5422 #define LINUX_TIOCSETD 0x5423 #define LINUX_TIOCGETD 0x5424 #define LINUX_TCSBRKP 0x5425 #define LINUX_TIOCTTYGSTRUCT 0x5426 #define LINUX_FIONCLEX 0x5450 #define LINUX_FIOCLEX 0x5451 #define LINUX_FIOASYNC 0x5452 #define LINUX_TIOCSERCONFIG 0x5453 #define LINUX_TIOCSERGWILD 0x5454 #define LINUX_TIOCSERSWILD 0x5455 #define LINUX_TIOCGLCKTRMIOS 0x5456 #define LINUX_TIOCSLCKTRMIOS 0x5457 /* line disciplines */ #define LINUX_N_TTY 0 #define LINUX_N_SLIP 1 #define LINUX_N_MOUSE 2 #define LINUX_N_PPP 3 /* Linux termio c_cc values */ #define LINUX_VINTR 0 #define LINUX_VQUIT 1 #define LINUX_VERASE 2 #define LINUX_VKILL 3 #define LINUX_VEOF 4 #define LINUX_VTIME 5 #define LINUX_VMIN 6 #define LINUX_VSWTC 7 #define LINUX_NCC 8 /* Linux termios c_cc values */ #define LINUX_VSTART 8 #define LINUX_VSTOP 9 #define LINUX_VSUSP 10 #define LINUX_VEOL 11 #define LINUX_VREPRINT 12 #define LINUX_VDISCARD 13 #define LINUX_VWERASE 14 #define LINUX_VLNEXT 15 #define LINUX_VEOL2 16 #define LINUX_NCCS 17 /* Linux c_iflag masks */ #define LINUX_IGNBRK 0x0000001 #define LINUX_BRKINT 0x0000002 #define LINUX_IGNPAR 0x0000004 #define LINUX_PARMRK 0x0000008 #define LINUX_INPCK 0x0000010 #define LINUX_ISTRIP 0x0000020 #define LINUX_INLCR 0x0000040 #define LINUX_IGNCR 0x0000080 #define LINUX_ICRNL 0x0000100 #define LINUX_IUCLC 0x0000200 #define LINUX_IXON 0x0000400 #define LINUX_IXANY 0x0000800 #define LINUX_IXOFF 0x0001000 #define LINUX_IMAXBEL 0x0002000 /* Linux c_oflag masks */ #define LINUX_OPOST 0x0000001 #define LINUX_OLCUC 0x0000002 #define LINUX_ONLCR 0x0000004 #define LINUX_OCRNL 0x0000008 #define LINUX_ONOCR 0x0000010 #define LINUX_ONLRET 0x0000020 #define LINUX_OFILL 0x0000040 #define LINUX_OFDEL 0x0000080 #define LINUX_NLDLY 0x0000100 #define LINUX_NL0 0x0000000 #define LINUX_NL1 0x0000100 #define LINUX_CRDLY 0x0000600 #define LINUX_CR0 0x0000000 #define LINUX_CR1 0x0000200 #define LINUX_CR2 0x0000400 #define LINUX_CR3 0x0000600 #define LINUX_TABDLY 0x0001800 #define LINUX_TAB0 0x0000000 #define LINUX_TAB1 0x0000800 #define LINUX_TAB2 0x0001000 #define LINUX_TAB3 0x0001800 #define LINUX_XTABS 0x0001800 #define LINUX_BSDLY 0x0002000 #define LINUX_BS0 0x0000000 #define LINUX_BS1 0x0002000 #define LINUX_VTDLY 0x0004000 #define LINUX_VT0 0x0000000 #define LINUX_VT1 0x0004000 #define LINUX_FFDLY 0x0008000 #define LINUX_FF0 0x0000000 #define LINUX_FF1 0x0008000 #define LINUX_CBAUD 0x0000100f #define LINUX_B0 0x00000000 #define LINUX_B50 0x00000001 #define LINUX_B75 0x00000002 #define LINUX_B110 0x00000003 #define LINUX_B134 0x00000004 #define LINUX_B150 0x00000005 #define LINUX_B200 0x00000006 #define LINUX_B300 0x00000007 #define LINUX_B600 0x00000008 #define LINUX_B1200 0x00000009 #define LINUX_B1800 0x0000000a #define LINUX_B2400 0x0000000b #define LINUX_B4800 0x0000000c #define LINUX_B9600 0x0000000d #define LINUX_B19200 0x0000000e #define LINUX_B38400 0x0000000f #define LINUX_EXTA LINUX_B19200 #define LINUX_EXTB LINUX_B38400 #define LINUX_CBAUDEX 0x00001000 #define LINUX_B57600 0x00001001 #define LINUX_B115200 0x00001002 #define LINUX_CSIZE 0x00000030 #define LINUX_CS5 0x00000000 #define LINUX_CS6 0x00000010 #define LINUX_CS7 0x00000020 #define LINUX_CS8 0x00000030 #define LINUX_CSTOPB 0x00000040 #define LINUX_CREAD 0x00000080 #define LINUX_PARENB 0x00000100 #define LINUX_PARODD 0x00000200 #define LINUX_HUPCL 0x00000400 #define LINUX_CLOCAL 0x00000800 #define LINUX_CRTSCTS 0x80000000 /* Linux c_lflag masks */ #define LINUX_ISIG 0x00000001 #define LINUX_ICANON 0x00000002 #define LINUX_XCASE 0x00000004 #define LINUX_ECHO 0x00000008 #define LINUX_ECHOE 0x00000010 #define LINUX_ECHOK 0x00000020 #define LINUX_ECHONL 0x00000040 #define LINUX_NOFLSH 0x00000080 #define LINUX_TOSTOP 0x00000100 #define LINUX_ECHOCTL 0x00000200 #define LINUX_ECHOPRT 0x00000400 #define LINUX_ECHOKE 0x00000800 #define LINUX_FLUSHO 0x00001000 #define LINUX_PENDIN 0x00002000 #define LINUX_IEXTEN 0x00008000 /* open/fcntl flags */ #define LINUX_O_RDONLY 00 #define LINUX_O_WRONLY 01 #define LINUX_O_RDWR 02 #define LINUX_O_CREAT 0100 #define LINUX_O_EXCL 0200 #define LINUX_O_NOCTTY 0400 #define LINUX_O_TRUNC 01000 #define LINUX_O_APPEND 02000 #define LINUX_O_NONBLOCK 04000 #define LINUX_O_NDELAY LINUX_O_NONBLOCK #define LINUX_O_SYNC 010000 #define LINUX_FASYNC 020000 /* fcntl flags */ #define LINUX_F_DUPFD 0 #define LINUX_F_GETFD 1 #define LINUX_F_SETFD 2 #define LINUX_F_GETFL 3 #define LINUX_F_SETFL 4 #define LINUX_F_GETLK 5 #define LINUX_F_SETLK 6 #define LINUX_F_SETLKW 7 #define LINUX_F_SETOWN 8 #define LINUX_F_GETOWN 9 #define LINUX_F_RDLCK 0 #define LINUX_F_WRLCK 1 #define LINUX_F_UNLCK 2 /* mmap options */ #define LINUX_MAP_SHARED 0x0001 #define LINUX_MAP_PRIVATE 0x0002 #define LINUX_MAP_FIXED 0x0010 #define LINUX_MAP_ANON 0x0020 /* SystemV ipc defines */ #define LINUX_SEMOP 1 #define LINUX_SEMGET 2 #define LINUX_SEMCTL 3 #define LINUX_MSGSND 11 #define LINUX_MSGRCV 12 #define LINUX_MSGGET 13 #define LINUX_MSGCTL 14 #define LINUX_SHMAT 21 #define LINUX_SHMDT 22 #define LINUX_SHMGET 23 #define LINUX_SHMCTL 24 #define LINUX_IPC_RMID 0 #define LINUX_IPC_SET 1 #define LINUX_IPC_STAT 2 #define LINUX_IPC_INFO 3 #define LINUX_SHM_LOCK 11 #define LINUX_SHM_UNLOCK 12 #define LINUX_SHM_STAT 13 #define LINUX_SHM_INFO 14 #define LINUX_SHM_RDONLY 0x1000 #define LINUX_SHM_RND 0x2000 #define LINUX_SHM_REMAP 0x4000 /* Socket defines */ #define LINUX_SOCKET 1 #define LINUX_BIND 2 #define LINUX_CONNECT 3 #define LINUX_LISTEN 4 #define LINUX_ACCEPT 5 #define LINUX_GETSOCKNAME 6 #define LINUX_GETPEERNAME 7 #define LINUX_SOCKETPAIR 8 #define LINUX_SEND 9 #define LINUX_RECV 10 #define LINUX_SENDTO 11 #define LINUX_RECVFROM 12 #define LINUX_SHUTDOWN 13 #define LINUX_SETSOCKOPT 14 #define LINUX_GETSOCKOPT 15 #define LINUX_AF_UNSPEC 0 #define LINUX_AF_UNIX 1 #define LINUX_AF_INET 2 #define LINUX_AF_AX25 3 #define LINUX_AF_IPX 4 #define LINUX_AF_APPLETALK 5 #define LINUX_SOL_SOCKET 1 #define LINUX_SOL_IP 0 #define LINUX_SOL_IPX 256 #define LINUX_SOL_AX25 257 #define LINUX_SOL_TCP 6 #define LINUX_SOL_UDP 17 #define LINUX_SO_DEBUG 1 #define LINUX_SO_REUSEADDR 2 #define LINUX_SO_TYPE 3 #define LINUX_SO_ERROR 4 #define LINUX_SO_DONTROUTE 5 #define LINUX_SO_BROADCAST 6 #define LINUX_SO_SNDBUF 7 #define LINUX_SO_RCVBUF 8 #define LINUX_SO_KEEPALIVE 9 #define LINUX_SO_OOBINLINE 10 #define LINUX_SO_NO_CHECK 11 #define LINUX_SO_PRIORITY 12 #define LINUX_SO_LINGER 13 #define LINUX_IP_TOS 1 #define LINUX_IP_TTL 2 /* Sound system defines */ #define LINUX_SNDCTL_DSP_RESET 0x5000 #define LINUX_SNDCTL_DSP_SYNC 0x5001 #define LINUX_SNDCTL_DSP_SPEED 0x5002 #define LINUX_SNDCTL_DSP_STEREO 0x5003 #define LINUX_SNDCTL_DSP_GETBLKSIZE 0x5004 #define LINUX_SNDCTL_DSP_SETBLKSIZE 0x5004 #define LINUX_SNDCTL_DSP_SETFMT 0x5005 #define LINUX_SOUND_PCM_WRITE_CHANNELS 0x5006 #define LINUX_SOUND_PCM_WRITE_FILTER 0x5007 #define LINUX_SNDCTL_DSP_POST 0x5008 #define LINUX_SNDCTL_DSP_SUBDIVIDE 0x5009 #define LINUX_SNDCTL_DSP_SETFRAGMENT 0x500A #define LINUX_SNDCTL_DSP_GETFMTS 0x500B #define LINUX_SNDCTL_DSP_GETOSPACE 0x500C #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/alpha/linux/linux_dummy.c b/sys/alpha/linux/linux_dummy.c index 6c55613e6abc..2fcab4616a39 100644 --- a/sys/alpha/linux/linux_dummy.c +++ b/sys/alpha/linux/linux_dummy.c @@ -1,317 +1,298 @@ /*- * 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_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 #include #include #include #include -#include +#include +#include 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/alpha/linux/linux_genassym.c b/sys/alpha/linux/linux_genassym.c new file mode 100644 index 000000000000..c52294880775 --- /dev/null +++ b/sys/alpha/linux/linux_genassym.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +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/alpha/linux/linux_sysvec.c b/sys/alpha/linux/linux_sysvec.c new file mode 100644 index 000000000000..92781027d986 --- /dev/null +++ b/sys/alpha/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index c32df1735d57..a22e6447646b 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -1,293 +1,293 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $ + * $Id: exception.s,v 1.14 1995/12/21 19:20:57 davidg Exp $ */ #include "npx.h" /* NNPX */ #include "assym.s" /* system defines */ #include /* error return codes */ #include /* SWI_AST_MASK ... */ #include /* PSL_I */ #include /* trap codes */ #include /* syscall numbers */ #include /* miscellaneous macros */ #define KDSEL 0x10 /* kernel data selector */ #define SEL_RPL_MASK 0x0003 #define TRAPF_CS_OFF (13 * 4) .text /*****************************************************************************/ /* Trap handling */ /*****************************************************************************/ /* * Trap and fault vector routines */ #define IDTVEC(name) ALIGN_TEXT ; .globl _X/**/name ; _X/**/name: #define TRAP(a) pushl $(a) ; jmp _alltraps /* * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose * control. The sti's give the standard losing behaviour for ddb and kgdb. */ #ifdef BDE_DEBUGGER #define BDBTRAP(name) \ ss ; \ cmpb $0,_bdb_exists ; \ je 1f ; \ testb $SEL_RPL_MASK,4(%esp) ; \ jne 1f ; \ ss ; \ .globl bdb_/**/name/**/_ljmp ; \ bdb_/**/name/**/_ljmp: ; \ ljmp $0,$0 ; \ 1: #else #define BDBTRAP(name) #endif #ifdef KGDB # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; \ pushl $(a) ; jmp _bpttraps #else # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) #endif MCOUNT_LABEL(user) MCOUNT_LABEL(btrap) IDTVEC(div) pushl $0; TRAP(T_DIVIDE) IDTVEC(dbg) BDBTRAP(dbg) pushl $0; BPTTRAP(T_TRCTRAP) IDTVEC(nmi) pushl $0; TRAP(T_NMI) IDTVEC(bpt) BDBTRAP(bpt) pushl $0; BPTTRAP(T_BPTFLT) IDTVEC(ofl) pushl $0; TRAP(T_OFLOW) IDTVEC(bnd) pushl $0; TRAP(T_BOUND) IDTVEC(ill) pushl $0; TRAP(T_PRIVINFLT) IDTVEC(dna) pushl $0; TRAP(T_DNA) IDTVEC(fpusegm) pushl $0; TRAP(T_FPOPFLT) IDTVEC(tss) TRAP(T_TSSFLT) IDTVEC(missing) TRAP(T_SEGNPFLT) IDTVEC(stk) TRAP(T_STKFLT) IDTVEC(prot) TRAP(T_PROTFLT) IDTVEC(page) TRAP(T_PAGEFLT) IDTVEC(rsvd) pushl $0; TRAP(T_RESERVED) IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can * call npxintr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. */ pushl $0 /* dumby error code */ pushl $0 /* dumby trap type */ pushal pushl %ds pushl %es /* now the stack frame is a trap frame */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) movl _cpl,%eax pushl %eax pushl $0 /* dummy unit to finish building intr frame */ incl _cnt+V_TRAP orl $SWI_AST_MASK,%eax movl %eax,_cpl call _npxintr incb _intr_nesting_level MEXITCOUNT jmp _doreti #else /* NNPX > 0 */ pushl $0; TRAP(T_ARITHTRAP) #endif /* NNPX > 0 */ IDTVEC(align) TRAP(T_ALIGNFLT) SUPERALIGN_TEXT _alltraps: pushal pushl %ds pushl %es alltraps_with_regs_pushed: movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) calltrap: FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ incl _cnt+V_TRAP orl $SWI_AST_MASK,_cpl call _trap /* * There was no place to save the cpl so we have to recover it * indirectly. For traps from user mode it was 0, and for traps * from kernel mode Oring SWI_AST_MASK into it didn't change it. */ subl %eax,%eax testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) jne 1f movl _cpl,%eax 1: /* * Return via _doreti to handle ASTs. Have to change trap frame * to interrupt frame. */ pushl %eax subl $4,%esp incb _intr_nesting_level MEXITCOUNT jmp _doreti #ifdef KGDB /* * This code checks for a kgdb trap, then falls through * to the regular trap code. */ SUPERALIGN_TEXT _bpttraps: pushal pushl %ds pushl %es movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) /* non-kernel mode? */ jne calltrap /* yes */ call _kgdb_trap_glue MEXITCOUNT jmp calltrap #endif /* * Call gate entry for syscall. * The intersegment call has been set up to specify one dummy parameter. * This leaves a place to put eflags so that the call frame can be * converted to a trap frame. Note that the eflags is (semi-)bogusly * pushed into (what will be) tf_err and then copied later into the * final spot. It has to be done this way because esp can't be just * temporarily altered for the pushfl - an interrupt might come in * and clobber the saved cs/eip. */ SUPERALIGN_TEXT IDTVEC(syscall) pushfl /* save eflags in tf_err for now */ subl $4,%esp /* skip over tf_trapno */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ movl %eax,TF_EFLAGS(%esp) + movl $7,TF_ERR(%esp) /* sizeof "lcall 7,0" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#if defined(COMPAT_LINUX) || defined(LINUX) /* - * Call gate entry for Linux syscall (int 0x80) + * Call gate entry for Linux/NetBSD syscall (int 0x80) */ SUPERALIGN_TEXT -IDTVEC(linux_syscall) +IDTVEC(int0x80_syscall) subl $8,%esp /* skip over tf_trapno and tf_err */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es + movl $2,TF_ERR(%esp) /* sizeof "int 0x80" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl - call _linux_syscall + call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#endif /* COMPAT_LINUX || LINUX */ /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and * belongs in i386/isa. */ #include "i386/isa/vector.s" /* * Include what was once icu-dependent code. * XXX it should be merged into this file (also move the definition of * imen to vector.s or isa.c). * Before including it, set up a normal asm environment so that vector.s * doesn't have to know that stuff is included after it. */ .data ALIGN_DATA .text SUPERALIGN_TEXT #include "i386/isa/icu.s" diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s index c32df1735d57..a22e6447646b 100644 --- a/sys/amd64/amd64/exception.s +++ b/sys/amd64/amd64/exception.s @@ -1,293 +1,293 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $ + * $Id: exception.s,v 1.14 1995/12/21 19:20:57 davidg Exp $ */ #include "npx.h" /* NNPX */ #include "assym.s" /* system defines */ #include /* error return codes */ #include /* SWI_AST_MASK ... */ #include /* PSL_I */ #include /* trap codes */ #include /* syscall numbers */ #include /* miscellaneous macros */ #define KDSEL 0x10 /* kernel data selector */ #define SEL_RPL_MASK 0x0003 #define TRAPF_CS_OFF (13 * 4) .text /*****************************************************************************/ /* Trap handling */ /*****************************************************************************/ /* * Trap and fault vector routines */ #define IDTVEC(name) ALIGN_TEXT ; .globl _X/**/name ; _X/**/name: #define TRAP(a) pushl $(a) ; jmp _alltraps /* * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose * control. The sti's give the standard losing behaviour for ddb and kgdb. */ #ifdef BDE_DEBUGGER #define BDBTRAP(name) \ ss ; \ cmpb $0,_bdb_exists ; \ je 1f ; \ testb $SEL_RPL_MASK,4(%esp) ; \ jne 1f ; \ ss ; \ .globl bdb_/**/name/**/_ljmp ; \ bdb_/**/name/**/_ljmp: ; \ ljmp $0,$0 ; \ 1: #else #define BDBTRAP(name) #endif #ifdef KGDB # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; \ pushl $(a) ; jmp _bpttraps #else # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) #endif MCOUNT_LABEL(user) MCOUNT_LABEL(btrap) IDTVEC(div) pushl $0; TRAP(T_DIVIDE) IDTVEC(dbg) BDBTRAP(dbg) pushl $0; BPTTRAP(T_TRCTRAP) IDTVEC(nmi) pushl $0; TRAP(T_NMI) IDTVEC(bpt) BDBTRAP(bpt) pushl $0; BPTTRAP(T_BPTFLT) IDTVEC(ofl) pushl $0; TRAP(T_OFLOW) IDTVEC(bnd) pushl $0; TRAP(T_BOUND) IDTVEC(ill) pushl $0; TRAP(T_PRIVINFLT) IDTVEC(dna) pushl $0; TRAP(T_DNA) IDTVEC(fpusegm) pushl $0; TRAP(T_FPOPFLT) IDTVEC(tss) TRAP(T_TSSFLT) IDTVEC(missing) TRAP(T_SEGNPFLT) IDTVEC(stk) TRAP(T_STKFLT) IDTVEC(prot) TRAP(T_PROTFLT) IDTVEC(page) TRAP(T_PAGEFLT) IDTVEC(rsvd) pushl $0; TRAP(T_RESERVED) IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can * call npxintr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. */ pushl $0 /* dumby error code */ pushl $0 /* dumby trap type */ pushal pushl %ds pushl %es /* now the stack frame is a trap frame */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) movl _cpl,%eax pushl %eax pushl $0 /* dummy unit to finish building intr frame */ incl _cnt+V_TRAP orl $SWI_AST_MASK,%eax movl %eax,_cpl call _npxintr incb _intr_nesting_level MEXITCOUNT jmp _doreti #else /* NNPX > 0 */ pushl $0; TRAP(T_ARITHTRAP) #endif /* NNPX > 0 */ IDTVEC(align) TRAP(T_ALIGNFLT) SUPERALIGN_TEXT _alltraps: pushal pushl %ds pushl %es alltraps_with_regs_pushed: movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) calltrap: FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ incl _cnt+V_TRAP orl $SWI_AST_MASK,_cpl call _trap /* * There was no place to save the cpl so we have to recover it * indirectly. For traps from user mode it was 0, and for traps * from kernel mode Oring SWI_AST_MASK into it didn't change it. */ subl %eax,%eax testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) jne 1f movl _cpl,%eax 1: /* * Return via _doreti to handle ASTs. Have to change trap frame * to interrupt frame. */ pushl %eax subl $4,%esp incb _intr_nesting_level MEXITCOUNT jmp _doreti #ifdef KGDB /* * This code checks for a kgdb trap, then falls through * to the regular trap code. */ SUPERALIGN_TEXT _bpttraps: pushal pushl %ds pushl %es movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) /* non-kernel mode? */ jne calltrap /* yes */ call _kgdb_trap_glue MEXITCOUNT jmp calltrap #endif /* * Call gate entry for syscall. * The intersegment call has been set up to specify one dummy parameter. * This leaves a place to put eflags so that the call frame can be * converted to a trap frame. Note that the eflags is (semi-)bogusly * pushed into (what will be) tf_err and then copied later into the * final spot. It has to be done this way because esp can't be just * temporarily altered for the pushfl - an interrupt might come in * and clobber the saved cs/eip. */ SUPERALIGN_TEXT IDTVEC(syscall) pushfl /* save eflags in tf_err for now */ subl $4,%esp /* skip over tf_trapno */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ movl %eax,TF_EFLAGS(%esp) + movl $7,TF_ERR(%esp) /* sizeof "lcall 7,0" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#if defined(COMPAT_LINUX) || defined(LINUX) /* - * Call gate entry for Linux syscall (int 0x80) + * Call gate entry for Linux/NetBSD syscall (int 0x80) */ SUPERALIGN_TEXT -IDTVEC(linux_syscall) +IDTVEC(int0x80_syscall) subl $8,%esp /* skip over tf_trapno and tf_err */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es + movl $2,TF_ERR(%esp) /* sizeof "int 0x80" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl - call _linux_syscall + call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#endif /* COMPAT_LINUX || LINUX */ /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and * belongs in i386/isa. */ #include "i386/isa/vector.s" /* * Include what was once icu-dependent code. * XXX it should be merged into this file (also move the definition of * imen to vector.s or isa.c). * Before including it, set up a normal asm environment so that vector.s * doesn't have to know that stuff is included after it. */ .data ALIGN_DATA .text SUPERALIGN_TEXT #include "i386/isa/icu.s" diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S index 6cafa0021a4a..e578692bd401 100644 --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -1,800 +1,806 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.61 1996/01/30 07:59:02 davidg Exp $ + * $Id: locore.s,v 1.62 1996/02/04 21:20:32 davidg Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "opt_ddb.h" #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ #include #include "apm.h" /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* * Sysmap is the base address of the kernel page tables. * It is a bogus interface for kgdb and isn't used by the kernel itself. */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .align 2 /* Just to be sure */ .globl tmpstk .space 0x2000 /* space for tmpstk - temporary stack */ tmpstk: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555 .globl _boothowto,_bootdev .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id,_bootinfo .globl _cpu_high, _cpu_feature _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_high: .long 0 /* highest arg to CPUID */ _cpu_feature: .long 0 /* features */ _cpu_vendor: .space 20 /* CPU origin code */ _bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ /* Set up a real frame, some day we will be doing returns */ pushl %ebp movl %esp, %ebp /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_KERNEL popfl /* Don't trust what the BIOS gives for %fs and %gs. */ mov %ds, %ax mov %ax, %fs mov %ax, %gs /* * This code is called in different ways depending on what loaded * and started the kernel. This is used to detect how we get the * arguments from the other code and what we do with them. * * Old disk boot blocks: * (*btext)(howto, bootdev, cyloffset, esym); * [return address == 0, and can NOT be returned to] * [cyloffset was not supported by the FreeBSD boot code * and always passed in as 0] * [esym is also known as total in the boot code, and * was never properly supported by the FreeBSD boot code] * * Old diskless netboot code: * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); * [return address != 0, and can NOT be returned to] * If we are being booted by this code it will NOT work, * so we are just going to halt if we find this case. * * New uniform boot code: * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) * [return address != 0, and can be returned to] * * There may seem to be a lot of wasted arguments in here, but * that is so the newer boot code can still load very old kernels * and old boot code can load new kernels. */ /* * The old style disk boot blocks fake a frame on the stack and * did an lret to get here. The frame on the stack has a return * address of 0. */ cmpl $0,4(%ebp) je 2f /* olddiskboot: */ /* * We have some form of return address, so this is either the * old diskless netboot code, or the new uniform code. That can * be detected by looking at the 5th argument, it if is 0 we * we are being booted by the new unifrom boot code. */ cmpl $0,24(%ebp) je 1f /* newboot: */ /* * Seems we have been loaded by the old diskless boot code, we * don't stand a chance of running as the diskless structure * changed considerably between the two, so just halt. */ hlt /* * We have been loaded by the new uniform boot code. * Lets check the bootinfo version, and if we do not understand * it we return to the loader with a status of 1 to indicate this error */ 1: /* newboot: */ movl 28(%ebp),%ebx /* &bootinfo.version */ movl BI_VERSION(%ebx),%eax cmpl $1,%eax /* We only understand version 1 */ je 1f movl $1,%eax /* Return status */ leave ret 1: /* * If we have a kernelname copy it in */ movl BI_KERNELNAME(%ebx),%esi cmpl $0,%esi je 2f /* No kernelname */ movl $MAXPATHLEN,%ecx /* Brute force!!! */ lea _kernelname-KERNBASE,%edi cmpb $'/',(%esi) /* Make sure it starts with a slash */ je 1f movb $'/',(%edi) incl %edi decl %ecx 1: cld rep movsb 2: /* * Determine the size of the boot loader's copy of the bootinfo * struct. This is impossible to do properly because old versions * of the struct don't contain a size field and there are 2 old * versions with the same version number. */ movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ je got_bi_size /* no, sizeless version */ movl BI_SIZE(%ebx),%ecx got_bi_size: /* * Copy the common part of the bootinfo struct */ movl %ebx,%esi movl $_bootinfo-KERNBASE,%edi cmpl $BOOTINFO_SIZE,%ecx jbe got_common_bi_size movl $BOOTINFO_SIZE,%ecx got_common_bi_size: cld rep movsb #ifdef NFS /* * If we have a nfs_diskless structure copy it in */ movl BI_NFS_DISKLESS(%ebx),%esi cmpl $0,%esi je 2f lea _nfs_diskless-KERNBASE,%edi movl $NFSDISKLESS_SIZE,%ecx cld rep movsb lea _nfs_diskless_valid-KERNBASE,%edi movl $1,(%edi) #endif /* * The old style disk boot. * (*btext)(howto, bootdev, cyloffset, esym); * Note that the newer boot code just falls into here to pick * up howto and bootdev, cyloffset and esym are no longer used */ 2: /* olddiskboot: */ movl 8(%ebp),%eax movl %eax,_boothowto-KERNBASE movl 12(%ebp),%eax movl %eax,_bootdev-KERNBASE #if NAPM > 0 /* call APM BIOS driver setup (i386/apm/apm_setup.s) */ call _apm_setup #endif /* NAPM */ /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 3f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 3f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 #ifndef CYRIX_CACHE_WORKS /* Disable caching of the ISA hole only. */ invd movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $(CCR0_NC1|CCR0_BARB),%al movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 invd #else /* CYRIX_CACHE_WORKS */ /* Set cache parameters */ invd # Start with guaranteed clean cache movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al andb $~CCR0_NC0,%al #ifndef CYRIX_CACHE_REALLY_WORKS orb $(CCR0_NC1|CCR0_BARB),%al #else orb $CCR0_NC1,%al #endif movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 /* clear non-cacheable region 1 */ movb $(NCR1+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 2 */ movb $(NCR2+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 3 */ movb $(NCR3+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 4 */ movb $(NCR4+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* enable caching in CR0 */ movl %cr0,%eax andl $~(CR0_CD|CR0_NW),%eax movl %eax,%cr0 invd #endif /* CYRIX_CACHE_WORKS */ jmp 3f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,_cpu_high-KERNBASE # highest capability movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id movl %edx,_cpu_feature-KERNBASE # store cpu_feature rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 3f 1: /* a Pentium? */ cmpl $5,%eax jne 2f movl $CPU_586,_cpu-KERNBASE jmp 3f 2: /* Greater than Pentium...call it a Pentium Pro */ movl $CPU_686,_cpu-KERNBASE 3: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb #ifdef DDB /* include symbols in "kernel image" if they are loaded */ movl _bootinfo+BI_ESYMTAB-KERNBASE,%edi testl %edi,%edi je over_symalloc addl $NBPG-1,%edi andl $~(NBPG-1),%edi movl %edi,%esi movl %esi,_KERNend-KERNBASE movl $KERNBASE,%edi addl %edi,_bootinfo+BI_SYMTAB-KERNBASE addl %edi,_bootinfo+BI_ESYMTAB-KERNBASE over_symalloc: #endif /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ #if 0 movl $_etext,%ecx /* get size of text */ subl $_btext,%ecx addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $_btext-KERNBASE,%eax /* get offset to physical memory */ orl $PG_V|PG_KR,%eax /* specify read only */ #endif lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, and p0stack PT */ movl $(1+UPAGES+1),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase /* set up bootstrap stack */ movl $_kstack+UPAGES*NBPG,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Prepare "first" - physical address of first available page * after the kernel+pdir+upages+p0stack+page tables */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USER /* eflags (IOPL 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x +/* + * Signal trampoline, copied to top of user stack + */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ - movl $103,%eax /* XXX sigreturn() */ + movl $SYS_sigreturn,%eax /* sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ - + .align 2 /* long word align */ +_esigcode: + .data .globl _szsigcode _szsigcode: - .long _szsigcode-_sigcode + .long _esigcode-_sigcode + .text diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s index 6cafa0021a4a..e578692bd401 100644 --- a/sys/amd64/amd64/locore.s +++ b/sys/amd64/amd64/locore.s @@ -1,800 +1,806 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.61 1996/01/30 07:59:02 davidg Exp $ + * $Id: locore.s,v 1.62 1996/02/04 21:20:32 davidg Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "opt_ddb.h" #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ #include #include "apm.h" /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* * Sysmap is the base address of the kernel page tables. * It is a bogus interface for kgdb and isn't used by the kernel itself. */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .align 2 /* Just to be sure */ .globl tmpstk .space 0x2000 /* space for tmpstk - temporary stack */ tmpstk: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555 .globl _boothowto,_bootdev .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id,_bootinfo .globl _cpu_high, _cpu_feature _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_high: .long 0 /* highest arg to CPUID */ _cpu_feature: .long 0 /* features */ _cpu_vendor: .space 20 /* CPU origin code */ _bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ /* Set up a real frame, some day we will be doing returns */ pushl %ebp movl %esp, %ebp /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_KERNEL popfl /* Don't trust what the BIOS gives for %fs and %gs. */ mov %ds, %ax mov %ax, %fs mov %ax, %gs /* * This code is called in different ways depending on what loaded * and started the kernel. This is used to detect how we get the * arguments from the other code and what we do with them. * * Old disk boot blocks: * (*btext)(howto, bootdev, cyloffset, esym); * [return address == 0, and can NOT be returned to] * [cyloffset was not supported by the FreeBSD boot code * and always passed in as 0] * [esym is also known as total in the boot code, and * was never properly supported by the FreeBSD boot code] * * Old diskless netboot code: * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); * [return address != 0, and can NOT be returned to] * If we are being booted by this code it will NOT work, * so we are just going to halt if we find this case. * * New uniform boot code: * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) * [return address != 0, and can be returned to] * * There may seem to be a lot of wasted arguments in here, but * that is so the newer boot code can still load very old kernels * and old boot code can load new kernels. */ /* * The old style disk boot blocks fake a frame on the stack and * did an lret to get here. The frame on the stack has a return * address of 0. */ cmpl $0,4(%ebp) je 2f /* olddiskboot: */ /* * We have some form of return address, so this is either the * old diskless netboot code, or the new uniform code. That can * be detected by looking at the 5th argument, it if is 0 we * we are being booted by the new unifrom boot code. */ cmpl $0,24(%ebp) je 1f /* newboot: */ /* * Seems we have been loaded by the old diskless boot code, we * don't stand a chance of running as the diskless structure * changed considerably between the two, so just halt. */ hlt /* * We have been loaded by the new uniform boot code. * Lets check the bootinfo version, and if we do not understand * it we return to the loader with a status of 1 to indicate this error */ 1: /* newboot: */ movl 28(%ebp),%ebx /* &bootinfo.version */ movl BI_VERSION(%ebx),%eax cmpl $1,%eax /* We only understand version 1 */ je 1f movl $1,%eax /* Return status */ leave ret 1: /* * If we have a kernelname copy it in */ movl BI_KERNELNAME(%ebx),%esi cmpl $0,%esi je 2f /* No kernelname */ movl $MAXPATHLEN,%ecx /* Brute force!!! */ lea _kernelname-KERNBASE,%edi cmpb $'/',(%esi) /* Make sure it starts with a slash */ je 1f movb $'/',(%edi) incl %edi decl %ecx 1: cld rep movsb 2: /* * Determine the size of the boot loader's copy of the bootinfo * struct. This is impossible to do properly because old versions * of the struct don't contain a size field and there are 2 old * versions with the same version number. */ movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ je got_bi_size /* no, sizeless version */ movl BI_SIZE(%ebx),%ecx got_bi_size: /* * Copy the common part of the bootinfo struct */ movl %ebx,%esi movl $_bootinfo-KERNBASE,%edi cmpl $BOOTINFO_SIZE,%ecx jbe got_common_bi_size movl $BOOTINFO_SIZE,%ecx got_common_bi_size: cld rep movsb #ifdef NFS /* * If we have a nfs_diskless structure copy it in */ movl BI_NFS_DISKLESS(%ebx),%esi cmpl $0,%esi je 2f lea _nfs_diskless-KERNBASE,%edi movl $NFSDISKLESS_SIZE,%ecx cld rep movsb lea _nfs_diskless_valid-KERNBASE,%edi movl $1,(%edi) #endif /* * The old style disk boot. * (*btext)(howto, bootdev, cyloffset, esym); * Note that the newer boot code just falls into here to pick * up howto and bootdev, cyloffset and esym are no longer used */ 2: /* olddiskboot: */ movl 8(%ebp),%eax movl %eax,_boothowto-KERNBASE movl 12(%ebp),%eax movl %eax,_bootdev-KERNBASE #if NAPM > 0 /* call APM BIOS driver setup (i386/apm/apm_setup.s) */ call _apm_setup #endif /* NAPM */ /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 3f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 3f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 #ifndef CYRIX_CACHE_WORKS /* Disable caching of the ISA hole only. */ invd movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $(CCR0_NC1|CCR0_BARB),%al movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 invd #else /* CYRIX_CACHE_WORKS */ /* Set cache parameters */ invd # Start with guaranteed clean cache movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al andb $~CCR0_NC0,%al #ifndef CYRIX_CACHE_REALLY_WORKS orb $(CCR0_NC1|CCR0_BARB),%al #else orb $CCR0_NC1,%al #endif movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 /* clear non-cacheable region 1 */ movb $(NCR1+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 2 */ movb $(NCR2+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 3 */ movb $(NCR3+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 4 */ movb $(NCR4+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* enable caching in CR0 */ movl %cr0,%eax andl $~(CR0_CD|CR0_NW),%eax movl %eax,%cr0 invd #endif /* CYRIX_CACHE_WORKS */ jmp 3f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,_cpu_high-KERNBASE # highest capability movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id movl %edx,_cpu_feature-KERNBASE # store cpu_feature rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 3f 1: /* a Pentium? */ cmpl $5,%eax jne 2f movl $CPU_586,_cpu-KERNBASE jmp 3f 2: /* Greater than Pentium...call it a Pentium Pro */ movl $CPU_686,_cpu-KERNBASE 3: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb #ifdef DDB /* include symbols in "kernel image" if they are loaded */ movl _bootinfo+BI_ESYMTAB-KERNBASE,%edi testl %edi,%edi je over_symalloc addl $NBPG-1,%edi andl $~(NBPG-1),%edi movl %edi,%esi movl %esi,_KERNend-KERNBASE movl $KERNBASE,%edi addl %edi,_bootinfo+BI_SYMTAB-KERNBASE addl %edi,_bootinfo+BI_ESYMTAB-KERNBASE over_symalloc: #endif /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ #if 0 movl $_etext,%ecx /* get size of text */ subl $_btext,%ecx addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $_btext-KERNBASE,%eax /* get offset to physical memory */ orl $PG_V|PG_KR,%eax /* specify read only */ #endif lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, and p0stack PT */ movl $(1+UPAGES+1),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase /* set up bootstrap stack */ movl $_kstack+UPAGES*NBPG,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Prepare "first" - physical address of first available page * after the kernel+pdir+upages+p0stack+page tables */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USER /* eflags (IOPL 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x +/* + * Signal trampoline, copied to top of user stack + */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ - movl $103,%eax /* XXX sigreturn() */ + movl $SYS_sigreturn,%eax /* sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ - + .align 2 /* long word align */ +_esigcode: + .data .globl _szsigcode _szsigcode: - .long _szsigcode-_sigcode + .long _esigcode-_sigcode + .text diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 067d4e794c70..30f442e39e7f 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1,1830 +1,1817 @@ /*- * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.174 1996/02/13 10:30:36 phk Exp $ + * $Id: machdep.c,v 1.175 1996/03/02 18:24:00 peter Exp $ */ #include "npx.h" #include "isa.h" #include "opt_sysvipc.h" #include "opt_ddb.h" #include "opt_bounce.h" #include "opt_machdep.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSHM #include #endif #ifdef SYSVMSG #include #endif #ifdef SYSVSEM #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern void init386 __P((int first)); extern int ptrace_set_pc __P((struct proc *p, unsigned int addr)); extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); extern void i486_bzero __P((void *, size_t)); extern void i586_bzero __P((void *, size_t)); extern void i686_bzero __P((void *, size_t)); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) static void identifycpu(void); char machine[] = "i386"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); static char cpu_model[128]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); struct kern_devconf kdc_cpu0 = { 0, 0, 0, /* filled in by dev_attach */ "cpu", 0, { MDDT_CPU }, 0, 0, 0, CPU_EXTERNALLEN, 0, /* CPU has no parent */ 0, /* no parentdata */ DC_BUSY, /* the CPU is always busy */ cpu_model, /* no sense in duplication */ DC_CLS_CPU /* class */ }; #ifndef PANIC_REBOOT_WAIT_TIME #define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ #endif #ifdef BOUNCE_BUFFERS extern char *bouncememory; extern int maxbkva; #ifdef BOUNCEPAGES int bouncepages = BOUNCEPAGES; #else int bouncepages = 0; #endif #endif /* BOUNCE_BUFFERS */ extern int freebufspace; int msgbufmapped = 0; /* set when safe to use msgbuf */ int _udatasel, _ucodesel; int physmem = 0; static int sysctl_hw_physmem SYSCTL_HANDLER_ARGS { int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); return (error); } SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_physmem, "I", ""); static int sysctl_hw_usermem SYSCTL_HANDLER_ARGS { int error = sysctl_handle_int(oidp, 0, ctob(physmem - cnt.v_wire_count), req); return (error); } SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_usermem, "I", ""); int boothowto = 0, bootverbose = 0, Maxmem = 0; static int badpages = 0; long dumplo; extern int bootdev; vm_offset_t phys_avail[10]; /* must be 2 less so 0 0 can signal end of chunks */ #define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) int cpu_class = CPUCLASS_386; /* smallest common denominator */ static void dumpsys __P((void)); static void setup_netisrs __P((struct linker_set *)); /* XXX declare elsewhere */ static vm_offset_t buffer_sva, buffer_eva; vm_offset_t clean_sva, clean_eva; static vm_offset_t pager_sva, pager_eva; extern struct linker_set netisr_set; #define offsetof(type, member) ((size_t)(&((type *)0)->member)) static void cpu_startup(dummy) void *dummy; { register unsigned i; register caddr_t v; vm_offset_t maxaddr; vm_size_t size = 0; int firstaddr; vm_offset_t minaddr; if (boothowto & RB_VERBOSE) bootverbose++; /* * Initialize error message buffer (at end of core). */ /* avail_end was pre-decremented in init_386() to compensate */ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp, avail_end + i * NBPG, VM_PROT_ALL, TRUE); msgbufmapped = 1; /* * Good {morning,afternoon,evening,night}. */ printf(version); startrtclock(); identifycpu(); printf("real memory = %d (%dK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024); /* * Display any holes after the first chunk of extended memory. */ if (badpages != 0) { int indx = 1; /* * XXX skip reporting ISA hole & unmanaged kernel memory */ if (phys_avail[0] == PAGE_SIZE) indx += 2; printf("Physical memory hole(s):\n"); for (; phys_avail[indx + 1] != 0; indx += 2) { int size = phys_avail[indx + 1] - phys_avail[indx]; printf("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[indx], phys_avail[indx + 1] - 1, size, size / PAGE_SIZE); } } /* * Quickly wire in netisrs. */ setup_netisrs(&netisr_set); /* #ifdef ISDN DONET(isdnintr, NETISR_ISDN); #endif */ /* * Allocate space for system data structures. * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * As pages of memory are allocated and cleared, * "firstaddr" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ /* * Make two passes. The first pass calculates how much memory is * needed and allocates it. The second pass assigns virtual * addresses to the various data structures. */ firstaddr = 0; again: v = (caddr_t)firstaddr; #define valloc(name, type, num) \ (name) = (type *)v; v = (caddr_t)((name)+(num)) #define valloclim(name, type, num, lim) \ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) valloc(callout, struct callout, ncallout); #ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni); #endif #ifdef SYSVSEM valloc(sema, struct semid_ds, seminfo.semmni); valloc(sem, struct sem, seminfo.semmns); /* This is pretty disgusting! */ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); #endif #ifdef SYSVMSG valloc(msgpool, char, msginfo.msgmax); valloc(msgmaps, struct msgmap, msginfo.msgseg); valloc(msghdrs, struct msg, msginfo.msgtql); valloc(msqids, struct msqid_ds, msginfo.msgmni); #endif if (nbuf == 0) { nbuf = 30; if( physmem > 1024) nbuf += min((physmem - 1024) / 12, 1024); } nswbuf = min(nbuf, 128); valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); #ifdef BOUNCE_BUFFERS /* * If there is more than 16MB of memory, allocate some bounce buffers */ if (Maxmem > 4096) { if (bouncepages == 0) { bouncepages = 64; bouncepages += ((Maxmem - 4096) / 2048) * 32; } v = (caddr_t)((vm_offset_t)((vm_offset_t)v + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); valloc(bouncememory, char, bouncepages * PAGE_SIZE); } #endif /* * End of first pass, size has been calculated so allocate memory */ if (firstaddr == 0) { size = (vm_size_t)(v - firstaddr); firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) panic("startup: no room for tables"); goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) panic("startup: table size inconsistency"); #ifdef BOUNCE_BUFFERS clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + maxbkva + pager_map_size, TRUE); io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva, FALSE); #else clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + pager_map_size, TRUE); #endif buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, (nbuf*MAXBSIZE), TRUE); pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, (nswbuf*MAXPHYS) + pager_map_size, TRUE); exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, (16*ARG_MAX), TRUE); u_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, (maxproc*UPAGES*PAGE_SIZE), FALSE); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *)malloc(nmbclusters+CLBYTES/MCLBYTES, M_MBUF, M_NOWAIT); bzero(mclrefcnt, nmbclusters+CLBYTES/MCLBYTES); mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr, nmbclusters * MCLBYTES, FALSE); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; if (boothowto & RB_CONFIG) { userconfig(); cninit(); /* the preferred console may have changed */ } #ifdef BOUNCE_BUFFERS /* * init bounce buffers */ vm_bounce_init(); #endif printf("avail memory = %d (%dK bytes)\n", ptoa(cnt.v_free_count), ptoa(cnt.v_free_count) / 1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); vm_pager_bufferinit(); /* * In verbose mode, print out the BIOS's idea of the disk geometries. */ if (bootverbose) { printf("BIOS Geometries:\n"); for (i = 0; i < N_BIOS_GEOM; i++) { unsigned long bios_geom; int max_cylinder, max_head, max_sector; bios_geom = bootinfo.bi_bios_geom[i]; /* * XXX the bootstrap punts a 1200K floppy geometry * when the get-disk-geometry interrupt fails. Skip * drives that have this geometry. */ if (bios_geom == 0x4f010f) continue; printf(" %x:%08lx ", i, bios_geom); max_cylinder = bios_geom >> 16; max_head = (bios_geom >> 8) & 0xff; max_sector = bios_geom & 0xff; printf( "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", max_cylinder, max_cylinder + 1, max_head, max_head + 1, max_sector, max_sector); } printf(" %d accounted for\n", bootinfo.bi_n_bios_used); } } int register_netisr(num, handler) int num; netisr_t *handler; { if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { printf("register_netisr: bad isr number: %d\n", num); return (EINVAL); } netisrs[num] = handler; return (0); } static void setup_netisrs(ls) struct linker_set *ls; { int i; const struct netisrtab *nit; for(i = 0; ls->ls_items[i]; i++) { nit = (const struct netisrtab *)ls->ls_items[i]; register_netisr(nit->nit_num, nit->nit_isr); } } static struct cpu_nameclass i386_cpus[] = { { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ { "i386DX", CPUCLASS_386 }, /* CPU_386 */ { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ { "i486DX", CPUCLASS_486 }, /* CPU_486 */ { "Pentium", CPUCLASS_586 }, /* CPU_586 */ { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ }; static void identifycpu() { printf("CPU: "); if (cpu >= 0 && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) { cpu_class = i386_cpus[cpu].cpu_class; strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); } else { printf("unknown cpu type %d\n", cpu); panic("startup: bad cpu id"); } #if defined(I586_CPU) || defined(I686_CPU) if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { calibrate_cyclecounter(); } #endif #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) if (!strcmp(cpu_vendor,"GenuineIntel")) { if ((cpu_id & 0xf00) > 3) { cpu_model[0] = '\0'; switch (cpu_id & 0x3000) { case 0x1000: strcpy(cpu_model, "Overdrive "); break; case 0x2000: strcpy(cpu_model, "Dual "); break; } switch (cpu_id & 0xf00) { case 0x400: strcat(cpu_model, "i486 "); break; case 0x500: strcat(cpu_model, "Pentium"); /* nb no space */ break; case 0x600: strcat(cpu_model, "Pentium Pro"); break; default: strcat(cpu_model, "unknown"); break; } switch (cpu_id & 0xff0) { case 0x400: strcat(cpu_model, "DX"); break; case 0x410: strcat(cpu_model, "DX"); break; case 0x420: strcat(cpu_model, "SX"); break; case 0x430: strcat(cpu_model, "DX2"); break; case 0x440: strcat(cpu_model, "SL"); break; case 0x450: strcat(cpu_model, "SX2"); break; case 0x470: strcat(cpu_model, "DX2 Write-Back Enhanced"); break; case 0x480: strcat(cpu_model, "DX4"); break; break; } } } #endif printf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_286: printf("286"); break; #if defined(I386_CPU) case CPUCLASS_386: printf("386"); break; #endif #if defined(I486_CPU) case CPUCLASS_486: printf("486"); bzero = i486_bzero; break; #endif #if defined(I586_CPU) case CPUCLASS_586: printf("%d.%02d-MHz ", ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100, ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100); printf("586"); bzero = i586_bzero; break; #endif #if defined(I686_CPU) case CPUCLASS_686: printf("%d.%02d-MHz ", ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100, ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100); printf("686"); bzero = i686_bzero; break; #endif default: printf("unknown"); /* will panic below... */ } printf("-class CPU)\n"); #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) if(*cpu_vendor) printf(" Origin = \"%s\"",cpu_vendor); if(cpu_id) printf(" Id = 0x%lx",cpu_id); if (!strcmp(cpu_vendor, "GenuineIntel")) { printf(" Stepping=%ld", cpu_id & 0xf); if (cpu_high > 0) { printf("\n Features=0x%b", cpu_feature, "\020" "\001FPU" "\002VME" "\003DE" "\004PSE" "\005TSC" "\006MSR" "\007PAE" "\010MCE" "\011CX8" "\012APIC" "\013" "\014" "\015MTRR" "\016PGE" "\017MCA" "\020CMOV" ); } } /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) printf("\n"); #endif /* * Now that we have told the user what they have, * let them know if that machine type isn't configured. */ switch (cpu_class) { case CPUCLASS_286: /* a 286 should not make it this far, anyway */ #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) #error This kernel is not configured for one of the supported CPUs #endif #if !defined(I386_CPU) case CPUCLASS_386: #endif #if !defined(I486_CPU) case CPUCLASS_486: #endif #if !defined(I586_CPU) case CPUCLASS_586: #endif #if !defined(I686_CPU) case CPUCLASS_686: #endif panic("CPU class not configured"); default: break; } dev_attach(&kdc_cpu0); } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored - * in u. to call routine, followed by kcall + * at top 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. */ void sendsig(catcher, sig, mask, code) sig_t catcher; int sig, mask; unsigned code; { register struct proc *p = curproc; register int *regs; register struct sigframe *fp; struct sigframe sf; struct sigacts *psp = p->p_sigacts; int oonstack; regs = p->p_md.md_regs; - oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; + oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; /* - * Allocate and validate space for the signal handler - * context. Note that if the stack is in P0 space, the - * call to grow() is a nop, and the useracc() check - * will fail if the process has not already allocated - * the space with a `brk'. + * Allocate and validate space for the signal handler context. */ - if ((psp->ps_flags & SAS_ALTSTACK) && - (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size - sizeof(struct sigframe)); - psp->ps_sigstk.ss_flags |= SA_ONSTACK; + psp->ps_sigstk.ss_flags |= SS_ONSTACK; } else { - fp = (struct sigframe *)(regs[tESP] - - sizeof(struct sigframe)); + fp = (struct 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 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; } sf.sf_signum = sig; sf.sf_code = code; sf.sf_scp = &fp->sf_sc; sf.sf_addr = (char *) regs[tERR]; sf.sf_handler = catcher; /* save scratch registers */ sf.sf_sc.sc_eax = regs[tEAX]; sf.sf_sc.sc_ebx = regs[tEBX]; sf.sf_sc.sc_ecx = regs[tECX]; sf.sf_sc.sc_edx = regs[tEDX]; sf.sf_sc.sc_esi = regs[tESI]; sf.sf_sc.sc_edi = regs[tEDI]; sf.sf_sc.sc_cs = regs[tCS]; sf.sf_sc.sc_ds = regs[tDS]; sf.sf_sc.sc_ss = regs[tSS]; sf.sf_sc.sc_es = regs[tES]; sf.sf_sc.sc_isp = regs[tISP]; /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = oonstack; sf.sf_sc.sc_mask = mask; sf.sf_sc.sc_sp = regs[tESP]; sf.sf_sc.sc_fp = regs[tEBP]; sf.sf_sc.sc_pc = regs[tEIP]; sf.sf_sc.sc_ps = regs[tEFLAGS]; /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, fp, sizeof(struct sigframe)) != 0) { /* * Something is wrong with the stack pointer. * ...Kill the process. */ sigexit(p, SIGILL); }; regs[tESP] = (int)fp; - regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; + 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 * state to gain improper privileges. */ int sigreturn(p, uap, retval) struct proc *p; struct sigreturn_args /* { struct sigcontext *sigcntxp; } */ *uap; int *retval; { register struct sigcontext *scp; register struct sigframe *fp; register int *regs = p->p_md.md_regs; int eflags; /* * (XXX old comment) regs[tESP] points to the return address. * The user scp pointer is above that. * The return address is faked in the signal trampoline code * for consistency. */ scp = uap->sigcntxp; fp = (struct sigframe *) ((caddr_t)scp - offsetof(struct sigframe, sf_sc)); if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) return(EINVAL); /* * Don't allow users to change privileged or reserved flags. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = scp->sc_ps; /* * 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)) { #ifdef DEBUG printf("sigreturn: eflags = 0x%x\n", eflags); #endif 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(scp->sc_cs)) { #ifdef DEBUG printf("sigreturn: cs = 0x%x\n", scp->sc_cs); #endif trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } /* restore scratch registers */ regs[tEAX] = scp->sc_eax; regs[tEBX] = scp->sc_ebx; regs[tECX] = scp->sc_ecx; regs[tEDX] = scp->sc_edx; regs[tESI] = scp->sc_esi; regs[tEDI] = scp->sc_edi; regs[tCS] = scp->sc_cs; regs[tDS] = scp->sc_ds; regs[tES] = scp->sc_es; regs[tSS] = scp->sc_ss; regs[tISP] = scp->sc_isp; if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) return(EINVAL); if (scp->sc_onstack & 01) - p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else - p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; p->p_sigmask = scp->sc_mask &~ (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); regs[tEBP] = scp->sc_fp; regs[tESP] = scp->sc_sp; regs[tEIP] = scp->sc_pc; regs[tEFLAGS] = eflags; return(EJUSTRETURN); } static int waittime = -1; static struct pcb dumppcb; __dead void boot(howto) int howto; { if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { register struct buf *bp; int iter, nbusy; waittime = 0; printf("\nsyncing disks... "); sync(&proc0, NULL, NULL); for (iter = 0; iter < 20; iter++) { nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { nbusy++; } } if (nbusy == 0) break; printf("%d ", nbusy); DELAY(40000 * iter); } if (nbusy) { /* * Failed to sync all blocks. Indicate this and don't * unmount filesystems (thus forcing an fsck on reboot). */ printf("giving up\n"); #ifdef SHOW_BUSYBUFS nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { nbusy++; printf("%d: dev:%08x, flags:%08x, blkno:%d, lblkno:%d\n", nbusy, bp->b_dev, bp->b_flags, bp->b_blkno, bp->b_lblkno); } } DELAY(5000000); /* 5 seconds */ #endif } else { printf("done\n"); /* * Unmount filesystems */ if (panicstr == 0) vfs_unmountall(); } DELAY(100000); /* wait for console output to finish */ dev_shutdownall(FALSE); } splhigh(); if (howto & RB_HALT) { printf("\n"); printf("The operating system has halted.\n"); printf("Please press any key to reboot.\n\n"); cngetc(); } else { if (howto & RB_DUMP) { if (!cold) { savectx(&dumppcb); dumppcb.pcb_ptd = rcr3(); dumpsys(); } if (PANIC_REBOOT_WAIT_TIME != 0) { if (PANIC_REBOOT_WAIT_TIME != -1) { int loop; printf("Automatic reboot in %d seconds - press a key on the console to abort\n", PANIC_REBOOT_WAIT_TIME); for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) { DELAY(1000 * 100); /* 1/10th second */ if (cncheckc()) /* Did user type a key? */ break; } if (!loop) goto die; } } else { /* zero time specified - reboot NOW */ goto die; } printf("--> Press a key on the console to reboot <--\n"); cngetc(); } } die: printf("Rebooting...\n"); DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ cpu_reset(); for(;;) ; /* NOTREACHED */ } /* * Magic number for savecore * * exported (symorder) and used at least by savecore(8) * */ u_long dumpmag = 0x8fca0101UL; static int dumpsize = 0; /* also for savecore */ static int dodump = 1; SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, ""); /* * Doadump comes here after turning off memory management and * getting on the dump stack, either when called above, or by * the auto-restart code. */ static void dumpsys() { if (!dodump) return; if (dumpdev == NODEV) return; if ((minor(dumpdev)&07) != 1) return; if (!(bdevsw[major(dumpdev)])) return; if (!(bdevsw[major(dumpdev)]->d_dump)) return; dumpsize = Maxmem; printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); printf("dump "); switch ((*bdevsw[major(dumpdev)]->d_dump)(dumpdev)) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; default: printf("succeeded\n"); break; } } /* * Clear registers on exec */ void setregs(p, entry, stack) struct proc *p; u_long entry; u_long stack; { int *regs = p->p_md.md_regs; bzero(regs, sizeof(struct trapframe)); regs[tEIP] = entry; regs[tESP] = stack; regs[tEFLAGS] = PSL_USER | (regs[tEFLAGS] & PSL_T); regs[tSS] = _udatasel; regs[tDS] = _udatasel; regs[tES] = _udatasel; regs[tCS] = _ucodesel; p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ load_cr0(rcr0() | CR0_TS); /* start emulating */ #if NNPX > 0 npxinit(__INITIAL_NPXCW__); #endif /* NNPX > 0 */ } static int sysctl_machdep_adjkerntz SYSCTL_HANDLER_ARGS { int error; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) resettodr(); return (error); } SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set, 0, ""); SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, CTLFLAG_RD, &bootinfo, bootinfo, ""); /* * Initialize 386 and configure to run kernel */ /* * Initialize segments & interrupt table */ int currentldt; int _default_ldt; union descriptor gdt[NGDT]; /* global descriptor table */ struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */ union descriptor ldt[NLDT]; /* local descriptor table */ static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; extern struct user *proc0paddr; /* software prototypes -- in more palatable form */ struct soft_segment_descriptor gdt_segs[] = { /* GNULL_SEL 0 Null Descriptor */ { 0x0, /* segment base address */ 0x0, /* length */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GCODE_SEL 1 Code Descriptor for kernel */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GDATA_SEL 2 Data Descriptor for kernel */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMRWA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GLDT_SEL 3 LDT Descriptor */ { (int) ldt, /* segment base address */ sizeof(ldt)-1, /* length - all address space */ SDT_SYSLDT, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GTGATE_SEL 4 Null Descriptor - Placeholder */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GPANIC_SEL 5 Panic Tss Descriptor */ { (int) &dblfault_tss, /* segment base address */ sizeof(struct i386tss)-1,/* length - all address space */ SDT_SYS386TSS, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GPROC0_SEL 6 Proc 0 Tss Descriptor */ { (int) kstack, /* segment base address */ sizeof(struct i386tss)-1,/* length - all address space */ SDT_SYS386TSS, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GUSERLDT_SEL 7 User LDT Descriptor per process */ { (int) ldt, /* segment base address */ (512 * sizeof(union descriptor)-1), /* length */ SDT_SYSLDT, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GAPMCODE32_SEL 8 APM BIOS 32-bit interface (32bit Code) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GAPMCODE16_SEL 9 APM BIOS 32-bit interface (16bit Code) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GAPMDATA_SEL 10 APM BIOS 32-bit interface (Data) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMRWA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, }; static struct soft_segment_descriptor ldt_segs[] = { /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Code Descriptor for user */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMERA, /* segment type */ SEL_UPL, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* Data Descriptor for user */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMRWA, /* segment type */ SEL_UPL, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, }; void setidt(idx, func, typ, dpl, selec) int idx; inthand_t *func; int typ; int dpl; int selec; { struct gate_descriptor *ip = idt + idx; ip->gd_looffset = (int)func; ip->gd_selector = selec; ip->gd_stkcpy = 0; ip->gd_xx = 0; ip->gd_type = typ; ip->gd_dpl = dpl; ip->gd_p = 1; ip->gd_hioffset = ((int)func)>>16 ; } #define IDTVEC(name) __CONCAT(X,name) extern inthand_t IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), - IDTVEC(syscall); - -#if defined(COMPAT_LINUX) || defined(LINUX) -extern inthand_t - IDTVEC(linux_syscall); -#endif + IDTVEC(syscall), IDTVEC(int0x80_syscall); void sdtossd(sd, ssd) struct segment_descriptor *sd; struct soft_segment_descriptor *ssd; { ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; ssd->ssd_type = sd->sd_type; ssd->ssd_dpl = sd->sd_dpl; ssd->ssd_p = sd->sd_p; ssd->ssd_def32 = sd->sd_def32; ssd->ssd_gran = sd->sd_gran; } void init386(first) int first; { int x; unsigned biosbasemem, biosextmem; struct gate_descriptor *gdp; int gsel_tss; /* table descriptors - used to load tables by microp */ struct region_descriptor r_gdt, r_idt; int pagesinbase, pagesinext; int target_page, pa_indx; proc0.p_addr = proc0paddr; /* * Initialize the console before we print anything out. */ cninit(); /* * make gdt memory segments, the code segment goes up to end of the * page with etext in it, the data segment goes to the end of * the address space */ /* * XXX text protection is temporarily (?) disabled. The limit was * i386_btop(round_page(etext)) - 1. */ gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1; gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1; for (x = 0; x < NGDT; x++) ssdtosd(&gdt_segs[x], &gdt[x].sd); /* make ldt memory segments */ /* * The data segment limit must not cover the user area because we * don't want the user area to be writable in copyout() etc. (page * level protection is lost in kernel mode on 386's). Also, we * don't want the user area to be writable directly (page level * protection of the user area is not available on 486's with * CR0_WP set, because there is no user-read/kernel-write mode). * * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it * should be spelled ...MAX_USER... */ #define VM_END_USER_RW_ADDRESS VM_MAXUSER_ADDRESS /* * The code segment limit has to cover the user area until we move * the signal trampoline out of the user area. This is safe because * the code segment cannot be written to directly. */ #define VM_END_USER_R_ADDRESS (VM_END_USER_RW_ADDRESS + UPAGES * NBPG) ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1; ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1; /* Note. eventually want private ldts per process */ for (x = 0; x < NLDT; x++) ssdtosd(&ldt_segs[x], &ldt[x].sd); /* exceptions */ for (x = 0; x < NIDT; x++) setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL)); setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#if defined(COMPAT_LINUX) || defined(LINUX) - setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); -#endif + setidt(0x80, &IDTVEC(int0x80_syscall), + SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); #include "isa.h" #if NISA >0 isa_defaultirq(); #endif rand_initialize(); r_gdt.rd_limit = sizeof(gdt) - 1; r_gdt.rd_base = (int) gdt; lgdt(&r_gdt); r_idt.rd_limit = sizeof(idt) - 1; r_idt.rd_base = (int) idt; lidt(&r_idt); _default_ldt = GSEL(GLDT_SEL, SEL_KPL); lldt(_default_ldt); currentldt = _default_ldt; #ifdef DDB kdb_init(); if (boothowto & RB_KDB) Debugger("Boot flags requested debugger"); #endif /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. */ biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); /* * Print a warning if the official BIOS interface disagrees * with the hackish interface used above. Eventually only * the official interface should be used. */ if (bootinfo.bi_memsizes_valid) { if (bootinfo.bi_basemem != biosbasemem) printf("BIOS basemem (%ldK) != RTC basemem (%dK)\n", bootinfo.bi_basemem, biosbasemem); if (bootinfo.bi_extmem != biosextmem) printf("BIOS extmem (%ldK) != RTC extmem (%dK)\n", bootinfo.bi_extmem, biosextmem); } /* * If BIOS tells us that it has more than 640k in the basemem, * don't believe it - set it to 640k. */ if (biosbasemem > 640) biosbasemem = 640; /* * Some 386 machines might give us a bogus number for extended * mem. If this happens, stop now. */ #ifndef LARGEMEM if (biosextmem > 65536) { panic("extended memory beyond limit of 64MB"); /* NOTREACHED */ } #endif pagesinbase = biosbasemem * 1024 / NBPG; pagesinext = biosextmem * 1024 / NBPG; /* * Special hack for chipsets that still remap the 384k hole when * there's 16MB of memory - this really confuses people that * are trying to use bus mastering ISA controllers with the * "16MB limit"; they only have 16MB, but the remapping puts * them beyond the limit. */ /* * If extended memory is between 15-16MB (16-17MB phys address range), * chop it to 15MB. */ if ((pagesinext > 3840) && (pagesinext < 4096)) pagesinext = 3840; /* * Maxmem isn't the "maximum memory", it's one larger than the * highest page of of the physical address space. It */ Maxmem = pagesinext + 0x100000/PAGE_SIZE; #ifdef MAXMEM Maxmem = MAXMEM/4; #endif /* call pmap initialization to make new kernel address space */ pmap_bootstrap (first, 0); /* * Size up each available chunk of physical memory. */ /* * We currently don't bother testing base memory. * XXX ...but we probably should. */ pa_indx = 0; badpages = 0; if (pagesinbase > 1) { phys_avail[pa_indx++] = PAGE_SIZE; /* skip first page of memory */ phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */ physmem = pagesinbase - 1; } else { /* point at first chunk end */ pa_indx++; } for (target_page = avail_start; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) { int tmp, page_bad = FALSE; /* * map page into kernel: valid, read/write, non-cacheable */ *(int *)CMAP1 = PG_V | PG_KW | PG_N | target_page; pmap_update(); tmp = *(int *)CADDR1; /* * Test for alternating 1's and 0's */ *(volatile int *)CADDR1 = 0xaaaaaaaa; if (*(volatile int *)CADDR1 != 0xaaaaaaaa) { page_bad = TRUE; } /* * Test for alternating 0's and 1's */ *(volatile int *)CADDR1 = 0x55555555; if (*(volatile int *)CADDR1 != 0x55555555) { page_bad = TRUE; } /* * Test for all 1's */ *(volatile int *)CADDR1 = 0xffffffff; if (*(volatile int *)CADDR1 != 0xffffffff) { page_bad = TRUE; } /* * Test for all 0's */ *(volatile int *)CADDR1 = 0x0; if (*(volatile int *)CADDR1 != 0x0) { /* * test of page failed */ page_bad = TRUE; } /* * Restore original value. */ *(int *)CADDR1 = tmp; /* * Adjust array of valid/good pages. */ if (page_bad == FALSE) { /* * If this good page is a continuation of the * previous set of good pages, then just increase * the end pointer. Otherwise start a new chunk. * Note that "end" points one higher than end, * making the range >= start and < end. */ if (phys_avail[pa_indx] == target_page) { phys_avail[pa_indx] += PAGE_SIZE; } else { pa_indx++; if (pa_indx == PHYS_AVAIL_ARRAY_END) { printf("Too many holes in the physical address space, giving up\n"); pa_indx--; break; } phys_avail[pa_indx++] = target_page; /* start */ phys_avail[pa_indx] = target_page + PAGE_SIZE; /* end */ } physmem++; } else { badpages++; page_bad = FALSE; } } *(int *)CMAP1 = 0; pmap_update(); /* * XXX * The last chunk must contain at least one page plus the message * buffer to avoid complicating other code (message buffer address * calculation, etc.). */ while (phys_avail[pa_indx - 1] + PAGE_SIZE + round_page(sizeof(struct msgbuf)) >= phys_avail[pa_indx]) { physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); phys_avail[pa_indx--] = 0; phys_avail[pa_indx--] = 0; } Maxmem = atop(phys_avail[pa_indx]); /* Trim off space for the message buffer. */ phys_avail[pa_indx] -= round_page(sizeof(struct msgbuf)); avail_end = phys_avail[pa_indx]; /* now running on new page tables, configured,and u/iom is accessible */ /* make a initial tss so microp can get interrupt stack on syscall! */ proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 = dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)]; dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 = dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL); dblfault_tss.tss_cr3 = IdlePTD; dblfault_tss.tss_eip = (int) dblfault_handler; dblfault_tss.tss_eflags = PSL_KERNEL; dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_fs = dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL); dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); ((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt = (sizeof(struct i386tss))<<16; ltr(gsel_tss); /* make a call gate to reenter kernel with */ gdp = &ldt[LSYS5CALLS_SEL].gd; x = (int) &IDTVEC(syscall); gdp->gd_looffset = x++; gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); gdp->gd_stkcpy = 1; gdp->gd_type = SDT_SYS386CGT; gdp->gd_dpl = SEL_UPL; gdp->gd_p = 1; gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; /* transfer to user mode */ _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); _udatasel = LSEL(LUDATA_SEL, SEL_UPL); /* setup proc 0's pcb */ - bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); proc0.p_addr->u_pcb.pcb_flags = 0; proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; } /* * The registers are in the frame; the frame is in the user area of * the process in question; when the process is active, the registers * are in "the kernel stack"; when it's not, they're still there, but * things get flipped around. So, since p->p_md.md_regs is the whole address * of the register set, take its offset from the kernel stack, and * index into the user block. Don't you just *love* virtual memory? * (I'm starting to think seymour is right...) */ #define TF_REGP(p) ((struct trapframe *) \ ((char *)(p)->p_addr \ + ((char *)(p)->p_md.md_regs - kstack))) int ptrace_set_pc(p, addr) struct proc *p; unsigned int addr; { TF_REGP(p)->tf_eip = addr; return (0); } int ptrace_single_step(p) struct proc *p; { TF_REGP(p)->tf_eflags |= PSL_T; return (0); } int ptrace_write_u(p, off, data) struct proc *p; vm_offset_t off; int data; { struct trapframe frame_copy; vm_offset_t min; struct trapframe *tp; /* * Privileged kernel state is scattered all over the user area. * Only allow write access to parts of regs and to fpregs. */ min = (char *)p->p_md.md_regs - kstack; if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) { tp = TF_REGP(p); frame_copy = *tp; *(int *)((char *)&frame_copy + (off - min)) = data; if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) || !CS_SECURE(frame_copy.tf_cs)) return (EINVAL); *(int*)((char *)p->p_addr + off) = data; return (0); } min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu); if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) { *(int*)((char *)p->p_addr + off) = data; return (0); } return (EFAULT); } int fill_regs(p, regs) struct proc *p; struct reg *regs; { struct trapframe *tp; tp = TF_REGP(p); regs->r_es = tp->tf_es; regs->r_ds = tp->tf_ds; regs->r_edi = tp->tf_edi; regs->r_esi = tp->tf_esi; regs->r_ebp = tp->tf_ebp; regs->r_ebx = tp->tf_ebx; regs->r_edx = tp->tf_edx; regs->r_ecx = tp->tf_ecx; regs->r_eax = tp->tf_eax; regs->r_eip = tp->tf_eip; regs->r_cs = tp->tf_cs; regs->r_eflags = tp->tf_eflags; regs->r_esp = tp->tf_esp; regs->r_ss = tp->tf_ss; return (0); } int set_regs(p, regs) struct proc *p; struct reg *regs; { struct trapframe *tp; tp = TF_REGP(p); if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; tp->tf_edi = regs->r_edi; tp->tf_esi = regs->r_esi; tp->tf_ebp = regs->r_ebp; tp->tf_ebx = regs->r_ebx; tp->tf_edx = regs->r_edx; tp->tf_ecx = regs->r_ecx; tp->tf_eax = regs->r_eax; tp->tf_eip = regs->r_eip; tp->tf_cs = regs->r_cs; tp->tf_eflags = regs->r_eflags; tp->tf_esp = regs->r_esp; tp->tf_ss = regs->r_ss; return (0); } #ifndef DDB void Debugger(const char *msg) { printf("Debugger(\"%s\") called.\n", msg); } #endif /* no DDB */ #include #define b_cylin b_resid /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. Adjust transfer * if needed, and signal errors or early completion. */ int bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel) { struct partition *p = lp->d_partitions + dkpart(bp->b_dev); int labelsect = lp->d_partitions[0].p_offset; int maxsz = p->p_size, sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; /* overwriting disk label ? */ /* XXX should also protect bootstrap in first 8K */ if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && #if LABELSECTOR != 0 bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && #endif (bp->b_flags & B_READ) == 0 && wlabel == 0) { bp->b_error = EROFS; goto bad; } #if defined(DOSBBSECTOR) && defined(notyet) /* overwriting master boot record? */ if (bp->b_blkno + p->p_offset <= DOSBBSECTOR && (bp->b_flags & B_READ) == 0 && wlabel == 0) { bp->b_error = EROFS; goto bad; } #endif /* beyond partition? */ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { /* if exactly at end of disk, return an EOF */ if (bp->b_blkno == maxsz) { bp->b_resid = bp->b_bcount; return(0); } /* or truncate if part of it fits */ sz = maxsz - bp->b_blkno; if (sz <= 0) { bp->b_error = EINVAL; goto bad; } bp->b_bcount = sz << DEV_BSHIFT; } /* calculate cylinder for disksort to order transfers with */ bp->b_pblkno = bp->b_blkno + p->p_offset; bp->b_cylin = bp->b_pblkno / lp->d_secpercyl; return(1); bad: bp->b_flags |= B_ERROR; return(-1); } int disk_externalize(int drive, struct sysctl_req *req) { return SYSCTL_OUT(req, &drive, sizeof drive); } diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index e270a58dbf16..8ecc51166c61 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -1,1063 +1,972 @@ /*- * Copyright (C) 1994, David Greenman * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the University of Utah, and William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.71 1996/01/19 03:57:42 dyson Exp $ + * $Id: trap.c,v 1.72 1996/02/25 03:02:46 dyson Exp $ */ /* * 386 Trap and System call handling */ #include "opt_ktrace.h" #include "opt_ddb.h" #include #include #include #include #include #include #include #include #include #ifdef KTRACE #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef POWERFAIL_NMI # include # include #endif #include "isa.h" #include "npx.h" int (*pmath_emulate) __P((struct trapframe *)); extern void trap __P((struct trapframe frame)); extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); -extern void linux_syscall __P((struct trapframe frame)); static int trap_pfault __P((struct trapframe *, int)); static void trap_fatal __P((struct trapframe *)); void dblfault_handler __P((void)); extern inthand_t IDTVEC(syscall); #define MAX_TRAP_MSG 27 static char *trap_msg[] = { "", /* 0 unused */ "privileged instruction fault", /* 1 T_PRIVINFLT */ "", /* 2 unused */ "breakpoint instruction fault", /* 3 T_BPTFLT */ "", /* 4 unused */ "", /* 5 unused */ "arithmetic trap", /* 6 T_ARITHTRAP */ "system forced exception", /* 7 T_ASTFLT */ "", /* 8 unused */ "general protection fault", /* 9 T_PROTFLT */ "trace trap", /* 10 T_TRCTRAP */ "", /* 11 unused */ "page fault", /* 12 T_PAGEFLT */ "", /* 13 unused */ "alignment fault", /* 14 T_ALIGNFLT */ "", /* 15 unused */ "", /* 16 unused */ "", /* 17 unused */ "integer divide fault", /* 18 T_DIVIDE */ "non-maskable interrupt trap", /* 19 T_NMI */ "overflow trap", /* 20 T_OFLOW */ "FPU bounds check fault", /* 21 T_BOUND */ "FPU device not available", /* 22 T_DNA */ "double fault", /* 23 T_DOUBLEFLT */ "FPU operand fetch fault", /* 24 T_FPOPFLT */ "invalid TSS fault", /* 25 T_TSSFLT */ "segment not present fault", /* 26 T_SEGNPFLT */ "stack fault", /* 27 T_STKFLT */ }; static void userret __P((struct proc *p, struct trapframe *frame, u_quad_t oticks)); static inline void userret(p, frame, oticks) struct proc *p; struct trapframe *frame; u_quad_t oticks; { int sig, s; while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; if (want_resched) { /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we setrunqueue ourselves but before we * mi_switch()'ed, we might not be on the queue indicated by * our priority. */ s = splclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); splx(s); while ((sig = CURSIG(p)) != 0) postsig(sig); } /* * Charge system time if profiling. */ if (p->p_flag & P_PROFIL) { u_quad_t ticks = p->p_sticks - oticks; if (ticks) { #ifdef PROFTIMER extern int profscale; addupc(frame->tf_eip, &p->p_stats->p_prof, ticks * profscale); #else addupc(frame->tf_eip, &p->p_stats->p_prof, ticks); #endif } } curpriority = p->p_priority; } /* * Exception, fault, and trap interface to the FreeBSD kernel. * This common code is called from assembly language IDT gate entry * routines that prepare a suitable stack frame, and restore this * frame after the exception has been processed. */ void trap(frame) struct trapframe frame; { struct proc *p = curproc; u_quad_t sticks = 0; int i = 0, ucode = 0, type, code; #ifdef DEBUG u_long eva; #endif type = frame.tf_trapno; code = frame.tf_err; if (ISPL(frame.tf_cs) == SEL_UPL) { /* user trap */ sticks = p->p_sticks; p->p_md.md_regs = (int *)&frame; switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ ucode = type; i = SIGILL; break; case T_BPTFLT: /* bpt instruction fault */ case T_TRCTRAP: /* trace trap */ frame.tf_eflags &= ~PSL_T; i = SIGTRAP; break; case T_ARITHTRAP: /* arithmetic trap */ ucode = code; i = SIGFPE; break; case T_ASTFLT: /* Allow process switch */ astoff(); cnt.v_soft++; if (p->p_flag & P_OWEUPC) { addupc(frame.tf_eip, &p->p_stats->p_prof, 1); p->p_flag &= ~P_OWEUPC; } goto out; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ case T_STKFLT: /* stack fault */ case T_TSSFLT: /* invalid TSS fault */ case T_DOUBLEFLT: /* double fault */ default: ucode = code + BUS_SEGM_FAULT ; i = SIGBUS; break; case T_PAGEFLT: /* page fault */ i = trap_pfault(&frame, TRUE); if (i == -1) return; if (i == 0) goto out; ucode = T_PAGEFLT; break; case T_DIVIDE: /* integer divide fault */ ucode = FPE_INTDIV_TRAP; i = SIGFPE; break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI goto handle_powerfail; #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; panic("NMI indicates hardware failure"); #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ case T_OFLOW: /* integer overflow fault */ ucode = FPE_INTOVF_TRAP; i = SIGFPE; break; case T_BOUND: /* bounds check fault */ ucode = FPE_SUBRNG_TRAP; i = SIGFPE; break; case T_DNA: #if NNPX > 0 /* if a transparent fault (due to context switch "late") */ if (npxdna()) return; #endif /* NNPX > 0 */ if (!pmath_emulate) { i = SIGFPE; ucode = FPE_FPU_NP_TRAP; break; } i = (*pmath_emulate)(&frame); if (i == 0) { if (!(frame.tf_eflags & PSL_T)) return; frame.tf_eflags &= ~PSL_T; i = SIGTRAP; } /* else ucode = emulator_only_knows() XXX */ break; case T_FPOPFLT: /* FPU operand fetch fault */ ucode = T_FPOPFLT; i = SIGILL; break; } } else { /* kernel trap */ switch (type) { case T_PAGEFLT: /* page fault */ (void) trap_pfault(&frame, FALSE); return; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ /* * Invalid segment selectors and out of bounds * %eip's and %esp's can be set up in user mode. * This causes a fault in kernel mode when the * kernel tries to return to user mode. We want * to get this fault so that we can fix the * problem here and not have to check all the * selectors and pointers when the user changes * them. */ #define MAYBE_DORETI_FAULT(where, whereto) \ do { \ if (frame.tf_eip == (int)where) { \ frame.tf_eip = (int)whereto; \ return; \ } \ } while (0) if (intr_nesting_level == 0) { MAYBE_DORETI_FAULT(doreti_iret, doreti_iret_fault); MAYBE_DORETI_FAULT(doreti_popl_ds, doreti_popl_ds_fault); MAYBE_DORETI_FAULT(doreti_popl_es, doreti_popl_es_fault); } if (curpcb && curpcb->pcb_onfault) { frame.tf_eip = (int)curpcb->pcb_onfault; return; } break; case T_TSSFLT: /* * PSL_NT can be set in user mode and isn't cleared * automatically when the kernel is entered. This * causes a TSS fault when the kernel attempts to * `iret' because the TSS link is uninitialized. We * want to get this fault so that we can fix the * problem here and not every time the kernel is * entered. */ if (frame.tf_eflags & PSL_NT) { frame.tf_eflags &= ~PSL_NT; return; } break; case T_TRCTRAP: /* trace trap */ if (frame.tf_eip == (int)IDTVEC(syscall)) { /* * We've just entered system mode via the * syscall lcall. Continue single stepping * silently until the syscall handler has * saved the flags. */ return; } if (frame.tf_eip == (int)IDTVEC(syscall) + 1) { /* * The syscall handler has now saved the * flags. Stop single stepping it. */ frame.tf_eflags &= ~PSL_T; return; } /* * Fall through. */ case T_BPTFLT: /* * If DDB is enabled, let it handle the debugger trap. * Otherwise, debugger traps "can't happen". */ #ifdef DDB if (kdb_trap (type, 0, &frame)) return; #endif break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI #ifndef TIMER_FREQ # define TIMER_FREQ 1193182 #endif handle_powerfail: { static unsigned lastalert = 0; if(time.tv_sec - lastalert > 10) { log(LOG_WARNING, "NMI: power fail\n"); sysbeep(TIMER_FREQ/880, hz); lastalert = time.tv_sec; } return; } #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; /* FALL THROUGH */ #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ } trap_fatal(&frame); return; } trapsignal(p, i, ucode); #ifdef DEBUG eva = rcr2(); if (type <= MAX_TRAP_MSG) { uprintf("fatal process exception: %s", trap_msg[type]); if ((type == T_PAGEFLT) || (type == T_PROTFLT)) uprintf(", fault VA = 0x%x", eva); uprintf("\n"); } #endif out: userret(p, &frame, sticks); } #ifdef notyet /* * This version doesn't allow a page fault to user space while * in the kernel. The rest of the kernel needs to be made "safe" * before this can be used. I think the only things remaining * to be made safe are the iBCS2 code and the process tracing/ * debugging code. */ static int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va < VM_MIN_KERNEL_ADDRESS) { vm_offset_t v; vm_page_t mpte; if (p == NULL || (!usermode && va < VM_MAXUSER_ADDRESS && (curpcb == NULL || curpcb->pcb_onfault == NULL))) { trap_fatal(frame); return (-1); } /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(kernel_map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } #endif int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va >= KERNBASE) { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; map = kernel_map; } else { /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ if (p != NULL) vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; } if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; if (map != kernel_map) { vm_offset_t v; vm_page_t mpte; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } static void trap_fatal(frame) struct trapframe *frame; { int code, type, eva; struct soft_segment_descriptor softseg; code = frame->tf_err; type = frame->tf_trapno; eva = rcr2(); sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); if (type <= MAX_TRAP_MSG) printf("\n\nFatal trap %d: %s while in %s mode\n", type, trap_msg[type], ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); if (type == T_PAGEFLT) { printf("fault virtual address = 0x%x\n", eva); printf("fault code = %s %s, %s\n", code & PGEX_U ? "user" : "supervisor", code & PGEX_W ? "write" : "read", code & PGEX_P ? "protection violation" : "page not present"); } printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); printf(" = DPL %d, pres %d, def32 %d, gran %d\n", softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran); printf("processor eflags = "); if (frame->tf_eflags & PSL_T) printf("trace/trap, "); if (frame->tf_eflags & PSL_I) printf("interrupt enabled, "); if (frame->tf_eflags & PSL_NT) printf("nested task, "); if (frame->tf_eflags & PSL_RF) printf("resume, "); if (frame->tf_eflags & PSL_VM) printf("vm86, "); printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); printf("current process = "); if (curproc) { printf("%lu (%s)\n", (u_long)curproc->p_pid, curproc->p_comm ? curproc->p_comm : ""); } else { printf("Idle\n"); } printf("interrupt mask = "); if ((cpl & net_imask) == net_imask) printf("net "); if ((cpl & tty_imask) == tty_imask) printf("tty "); if ((cpl & bio_imask) == bio_imask) printf("bio "); if (cpl == 0) printf("none"); printf("\n"); #ifdef KDB if (kdb_trap(&psl)) return; #endif #ifdef DDB if (kdb_trap (type, 0, frame)) return; #endif if (type <= MAX_TRAP_MSG) panic(trap_msg[type]); else panic("unknown/reserved trap"); } /* * Double fault handler. Called when a fault occurs while writing * a frame for a trap/exception onto the stack. This usually occurs * when the stack overflows (such is the case with infinite recursion, * for example). * * XXX Note that the current PTD gets replaced by IdlePTD when the * task switch occurs. This means that the stack that was active at * the time of the double fault is not available at unless * the machine was idle when the double fault occurred. The downside * of this is that "trace " in ddb won't work. */ void dblfault_handler() { struct pcb *pcb = curpcb; if (pcb != NULL) { printf("\nFatal double fault:\n"); printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip); printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp); printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp); } panic("double fault"); } /* * Compensate for 386 brain damage (missing URKR). * This is a little simpler than the pagefault handler in trap() because * it the page tables have already been faulted in and high addresses * are thrown out early for other reasons. */ int trapwrite(addr) unsigned addr; { struct proc *p; vm_offset_t va, v; struct vmspace *vm; int rv; va = trunc_page((vm_offset_t)addr); /* * XXX - MAX is END. Changed > to >= for temp. fix. */ if (va >= VM_MAXUSER_ADDRESS) return (1); p = curproc; vm = p->p_vmspace; ++p->p_lock; if ((caddr_t)va >= vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { --p->p_lock; return (1); } } v = trunc_page(vtopte(va)); /* * wire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE); } /* * fault the data page */ rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); /* * unwire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE); } --p->p_lock; if (rv != KERN_SUCCESS) return 1; return (0); } /* * System call request from POSIX system call gate interface to kernel. * Like trap(), argument is call by reference. */ void syscall(frame) struct trapframe frame; { caddr_t params; int i; struct sysent *callp; struct proc *p = curproc; u_quad_t sticks; int error; int args[8], rval[2]; u_int code; sticks = p->p_sticks; if (ISPL(frame.tf_cs) != SEL_UPL) panic("syscall"); p->p_md.md_regs = (int *)&frame; params = (caddr_t)frame.tf_esp + sizeof(int); code = frame.tf_eax; - /* - * Need to check if this is a 32 bit or 64 bit syscall. - */ - if (code == SYS_syscall) { - /* - * Code is first argument, followed by actual args. - */ - code = fuword(params); - params += sizeof(int); - } else if (code == SYS___syscall) { + if (p->p_sysent->sv_prepsyscall) { + (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms); + } else { /* - * Like syscall, but code is a quad, so as to maintain - * quad alignment for the rest of the arguments. + * Need to check if this is a 32 bit or 64 bit syscall. */ - code = fuword(params); - params += sizeof(quad_t); + if (code == SYS_syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = fuword(params); + params += sizeof(int); + } else if (code == SYS___syscall) { + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + code = fuword(params); + params += sizeof(quad_t); + } } if (p->p_sysent->sv_mask) code &= p->p_sysent->sv_mask; if (code >= p->p_sysent->sv_size) callp = &p->p_sysent->sv_table[0]; else callp = &p->p_sysent->sv_table[code]; - if ((i = callp->sy_narg * sizeof(int)) && + if (params && (i = callp->sy_narg * sizeof(int)) && (error = copyin(params, (caddr_t)args, (u_int)i))) { #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif goto bad; } #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif rval[0] = 0; rval[1] = frame.tf_edx; error = (*callp->sy_call)(p, args, rval); switch (error) { case 0: /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; frame.tf_eax = rval[0]; frame.tf_edx = rval[1]; frame.tf_eflags &= ~PSL_C; break; case ERESTART: /* - * Reconstruct pc, assuming lcall $X,y is 7 bytes. + * Reconstruct pc, assuming lcall $X,y is 7 bytes, + * int 0x80 is 2 bytes. We saved this in tf_err. */ - frame.tf_eip -= 7; + frame.tf_eip -= frame.tf_err; break; case EJUSTRETURN: break; default: bad: if (p->p_sysent->sv_errsize) if (error >= p->p_sysent->sv_errsize) error = -1; /* XXX */ else error = p->p_sysent->sv_errtbl[error]; frame.tf_eax = error; frame.tf_eflags |= PSL_C; break; } if (frame.tf_eflags & PSL_T) { /* Traced syscall. */ frame.tf_eflags &= ~PSL_T; trapsignal(p, SIGTRAP, 0); } userret(p, &frame, sticks); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } - -#if defined(COMPAT_LINUX) || defined(LINUX) -void -linux_syscall(frame) - struct trapframe frame; -{ - struct proc *p = curproc; - struct sysent *callp; - u_quad_t sticks; - int error; - int rval[2]; - u_int code; - struct linux_syscall_args { - int arg1; - int arg2; - int arg3; - int arg4; - int arg5; - } args; - - args.arg1 = frame.tf_ebx; - args.arg2 = frame.tf_ecx; - args.arg3 = frame.tf_edx; - args.arg4 = frame.tf_esi; - args.arg5 = frame.tf_edi; - - sticks = p->p_sticks; - if (ISPL(frame.tf_cs) != SEL_UPL) - panic("linux syscall"); - - p->p_md.md_regs = (int *)&frame; - code = frame.tf_eax; - - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; - - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, callp->sy_narg, (int *)&args); -#endif - - rval[0] = 0; - - error = (*callp->sy_call)(p, &args, rval); - - switch (error) { - - case 0: - /* - * Reinitialize proc pointer `p' as it may be different - * if this is a child returning from fork syscall. - */ - p = curproc; - frame.tf_eax = rval[0]; - frame.tf_eflags &= ~PSL_C; - break; - - case ERESTART: - /* Reconstruct pc, subtract size of int 0x80 */ - frame.tf_eip -= 2; - break; - - case EJUSTRETURN: - break; - - default: - if (p->p_sysent->sv_errsize) - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; - frame.tf_eax = -error; - frame.tf_eflags |= PSL_C; - break; - } - - if (frame.tf_eflags & PSL_T) { - /* Traced syscall. */ - frame.tf_eflags &= ~PSL_T; - trapsignal(p, SIGTRAP, 0); - } - - userret(p, &frame, sticks); - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, error, rval[0]); -#endif -} -#endif /* COMPAT_LINUX || LINUX */ diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 19e282248150..5e280304abdc 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -1,66 +1,66 @@ /*- * Copyright (c) 1995 Bruce D. Evans. * 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. Neither the name of the author nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: md_var.h,v 1.6 1996/01/27 02:33:25 bde Exp $ + * $Id: md_var.h,v 1.7 1996/02/04 21:20:52 davidg Exp $ */ #ifndef _MACHINE_MD_VAR_H_ #define _MACHINE_MD_VAR_H_ /* * Miscellaneous machine-dependent declarations. */ extern int Maxmem; extern u_long cpu_feature; extern u_long cpu_high; extern u_long cpu_id; extern char cpu_vendor[]; extern char etext[]; extern char kstack[]; extern void (*netisrs[32]) __P((void)); extern int nfs_diskless_valid; -extern int sigcode; +extern char sigcode[]; extern int szsigcode; struct proc; struct reg; void cpu_reset __P((void)); void doreti_iret __P((void)) __asm(__STRING(doreti_iret)); void doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault)); void doreti_popl_ds __P((void)) __asm(__STRING(doreti_popl_ds)); void doreti_popl_ds_fault __P((void)) __asm(__STRING(doreti_popl_ds_fault)); void doreti_popl_es __P((void)) __asm(__STRING(doreti_popl_es)); void doreti_popl_es_fault __P((void)) __asm(__STRING(doreti_popl_es_fault)); int fill_regs __P((struct proc *p, struct reg *regs)); void userconfig __P((void)); void vm_bounce_init __P((void)); int vm_page_zero_idle __P((void)); #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index f8ea0dc06f25..a3f2005e7f45 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -1,86 +1,85 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)pcb.h 5.10 (Berkeley) 5/12/91 - * $Id: pcb.h,v 1.9 1995/08/17 11:30:03 davidg Exp $ + * $Id: pcb.h,v 1.10 1996/01/23 02:39:24 davidg Exp $ */ #ifndef _I386_PCB_H_ #define _I386_PCB_H_ /* * Intel 386 process control block */ #include #include struct pcb { struct i386tss pcb_tss; #define pcb_ksp pcb_tss.tss_esp0 #define pcb_ptd pcb_tss.tss_cr3 #define pcb_cr3 pcb_ptd #define pcb_pc pcb_tss.tss_eip #define pcb_psl pcb_tss.tss_eflags #define pcb_usp pcb_tss.tss_esp #define pcb_fp pcb_tss.tss_ebp #ifdef notyet u_char pcb_iomap[NPORT/sizeof(u_char)]; /* i/o port bitmap */ #endif caddr_t pcb_ldt; /* per process (user) LDT */ int pcb_ldt_len; /* number of LDT entries */ struct save87 pcb_savefpu; /* floating point state for 287/387 */ /* * Software pcb (extension) */ u_char pcb_flags; #define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ u_char pcb_inl; /* intr_nesting_level at context switch */ caddr_t pcb_onfault; /* copyin/out fault recovery */ - long pcb_sigc[8]; /* XXX signal code trampoline */ }; /* * The pcb is augmented with machine-dependent additional data for * core dumps. For the i386: ??? */ struct md_coredump { }; #ifdef KERNEL extern struct pcb *curpcb; /* our current running pcb */ int savectx __P((struct pcb*)); #endif #endif /* _I386_PCB_H_ */ diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 0918f221fd3f..93932dfca75f 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -1,452 +1,763 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include #include #include -#include - -struct linux_creat_args { - char *path; - int mode; -}; +#include +#include int linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) { struct open_args /* { char *path; 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", p->p_pid, args->path, args->mode); #endif bsd_open_args.path = args->path; bsd_open_args.mode = args->mode; bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 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) { struct open_args /* { char *path; int flags; 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); #endif bsd_open_args.flags = 0; if (args->flags & LINUX_O_RDONLY) bsd_open_args.flags |= O_RDONLY; if (args->flags & LINUX_O_WRONLY) bsd_open_args.flags |= O_WRONLY; if (args->flags & LINUX_O_RDWR) bsd_open_args.flags |= O_RDWR; if (args->flags & LINUX_O_NDELAY) bsd_open_args.flags |= O_NONBLOCK; if (args->flags & LINUX_O_APPEND) bsd_open_args.flags |= O_APPEND; if (args->flags & LINUX_O_SYNC) bsd_open_args.flags |= O_FSYNC; if (args->flags & LINUX_O_NONBLOCK) bsd_open_args.flags |= O_NONBLOCK; if (args->flags & LINUX_FASYNC) bsd_open_args.flags |= O_ASYNC; if (args->flags & LINUX_O_CREAT) bsd_open_args.flags |= O_CREAT; if (args->flags & LINUX_O_TRUNC) bsd_open_args.flags |= O_TRUNC; if (args->flags & LINUX_O_EXCL) bsd_open_args.flags |= O_EXCL; if (args->flags & LINUX_O_NOCTTY) bsd_open_args.flags |= O_NOCTTY; bsd_open_args.path = args->path; bsd_open_args.mode = args->mode; error = open(p, &bsd_open_args, retval); if (!error && !(bsd_open_args.flags & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { struct filedesc *fdp = p->p_fd; struct file *fp = fdp->fd_ofiles[*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; } struct linux_flock { short l_type; short l_whence; linux_off_t l_start; linux_off_t l_len; linux_pid_t l_pid; }; static void linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) { switch (linux_flock->l_type) { case LINUX_F_RDLCK: bsd_flock->l_type = F_RDLCK; break; case LINUX_F_WRLCK: bsd_flock->l_type = F_WRLCK; break; case LINUX_F_UNLCK: bsd_flock->l_type = F_UNLCK; break; } bsd_flock->l_whence = linux_flock->l_whence; bsd_flock->l_start = (off_t)linux_flock->l_start; bsd_flock->l_len = (off_t)linux_flock->l_len; bsd_flock->l_pid = (pid_t)linux_flock->l_pid; } static void bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) { switch (bsd_flock->l_type) { case F_RDLCK: linux_flock->l_type = LINUX_F_RDLCK; break; case F_WRLCK: linux_flock->l_type = LINUX_F_WRLCK; break; case F_UNLCK: linux_flock->l_type = LINUX_F_UNLCK; break; } linux_flock->l_whence = bsd_flock->l_whence; linux_flock->l_start = (linux_off_t)bsd_flock->l_start; linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 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) { int error, result; struct fcntl_args /* { int fd; int cmd; 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", p->p_pid, args->fd, args->cmd); #endif fcntl_args.fd = args->fd; fcntl_args.arg = 0; switch (args->cmd) { case LINUX_F_DUPFD: fcntl_args.cmd = F_DUPFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETFD: fcntl_args.cmd = F_GETFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_SETFD: fcntl_args.cmd = F_SETFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETFL: fcntl_args.cmd = F_GETFL; error = fcntl(p, &fcntl_args, &result); *retval = 0; if (result & O_RDONLY) *retval |= LINUX_O_RDONLY; if (result & O_WRONLY) *retval |= LINUX_O_WRONLY; if (result & O_RDWR) *retval |= LINUX_O_RDWR; if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK; if (result & O_APPEND) *retval |= LINUX_O_APPEND; if (result & O_FSYNC) *retval |= LINUX_O_SYNC; return error; case LINUX_F_SETFL: if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; fcntl_args.cmd = F_SETFL; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETLK: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_GETLK; fcntl_args.arg = (int)bsd_flock; if (error = fcntl(p, &fcntl_args, retval)) return error; bsd_to_linux_flock(bsd_flock, &linux_flock); return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, sizeof(struct linux_flock)); case LINUX_F_SETLK: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_SETLK; fcntl_args.arg = (int)bsd_flock; return fcntl(p, &fcntl_args, retval); case LINUX_F_SETLKW: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_SETLKW; fcntl_args.arg = (int)bsd_flock; 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) { struct lseek_args /* { int fd; int pad; off_t offset; int whence; } */ tmp_args; int error; #ifdef DEBUG printf("Linux-emul(%d): lseek(%d, %d, %d)\n", p->p_pid, args->fdes, args->off, args->whence); #endif tmp_args.fd = args->fdes; tmp_args.offset = (off_t)args->off; tmp_args.whence = args->whence; error = lseek(p, &tmp_args, 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; unsigned short dreclen; char dname[LINUX_NAME_MAX + 1]; }; #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 */ int len, reclen; /* BSD-format */ caddr_t outp; /* Linux-format */ int resid, linuxreclen=0; /* Linux-format */ struct file *fp; struct uio auio; struct iovec aiov; struct vattr va; off_t off; struct linux_dirent linux_dirent; 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); vp = (struct vnode *) fp->f_data; if (vp->v_type != VDIR) return (EINVAL); if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { return error; } nbytes = args->count; if (nbytes == 1) { nbytes = sizeof (struct linux_dirent); justone = 1; } else justone = 0; off = fp->f_offset; blockoff = off % DIRBLKSIZ; buflen = max(DIRBLKSIZ, nbytes + blockoff); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); VOP_LOCK(vp); again: aiov.iov_base = buf; aiov.iov_len = buflen; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_resid = buflen; auio.uio_offset = off - (off_t)blockoff; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (int *) NULL, (u_int **) NULL); if (error) { goto out; -} + } inp = buf; inp += blockoff; outp = (caddr_t) args->dent; resid = nbytes; if ((len = buflen - auio.uio_resid - blockoff) == 0) { goto eof; - } + } while (len > 0) { bdp = (struct dirent *) inp; reclen = bdp->d_reclen; if (reclen & 3) { printf("linux_readdir: reclen=%d\n", reclen); error = EFAULT; goto out; } if (bdp->d_fileno == 0) { inp += reclen; off += reclen; len -= reclen; continue; } linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); if (reclen > len || resid < linuxreclen) { outp++; break; } linux_dirent.dino = (long) bdp->d_fileno; linux_dirent.doff = (linux_off_t) linuxreclen; linux_dirent.dreclen = (u_short) bdp->d_namlen; strcpy(linux_dirent.dname, bdp->d_name); if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { goto out; - } + } inp += reclen; off += reclen; outp += linuxreclen; resid -= linuxreclen; len -= reclen; if (justone) break; } if (outp == (caddr_t) args->dent) goto again; fp->f_offset = off; if (justone) nbytes = resid + linuxreclen; eof: *retval = nbytes - resid; out: VOP_UNLOCK(vp); 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/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 03bc0315e942..968092862bd9 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -1,559 +1,588 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include -#include +#include struct linux_termios { unsigned long c_iflag; unsigned long c_oflag; unsigned long c_cflag; unsigned long c_lflag; unsigned char c_line; unsigned char c_cc[LINUX_NCCS]; }; struct linux_winsize { unsigned short ws_row, ws_col; unsigned short ws_xpixel, ws_ypixel; }; static struct speedtab sptab[] = { { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, { 19200, 14 }, { 38400, 15 }, { 57600, 4097 }, { 115200, 4098 }, {-1, -1 } }; static int linux_to_bsd_speed(int code, struct speedtab *table) { for ( ; table->sp_code != -1; table++) if (table->sp_code == code) return (table->sp_speed); return -1; } static int bsd_to_linux_speed(int speed, struct speedtab *table) { for ( ; table->sp_speed != -1; table++) if (table->sp_speed == speed) return (table->sp_code); return -1; } static void bsd_to_linux_termios(struct termios *bsd_termios, struct linux_termios *linux_termios) { int i, speed; #ifdef DEBUG printf("LINUX: BSD termios structure (input):\n"); printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", bsd_termios->c_iflag, bsd_termios->c_oflag, bsd_termios->c_cflag, bsd_termios->c_lflag, bsd_termios->c_ispeed, bsd_termios->c_ospeed); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif linux_termios->c_iflag = 0; if (bsd_termios->c_iflag & IGNBRK) linux_termios->c_iflag |= LINUX_IGNBRK; if (bsd_termios->c_iflag & BRKINT) linux_termios->c_iflag |= LINUX_BRKINT; if (bsd_termios->c_iflag & IGNPAR) linux_termios->c_iflag |= LINUX_IGNPAR; if (bsd_termios->c_iflag & PARMRK) linux_termios->c_iflag |= LINUX_PARMRK; if (bsd_termios->c_iflag & INPCK) linux_termios->c_iflag |= LINUX_INPCK; if (bsd_termios->c_iflag & ISTRIP) linux_termios->c_iflag |= LINUX_ISTRIP; if (bsd_termios->c_iflag & INLCR) linux_termios->c_iflag |= LINUX_INLCR; if (bsd_termios->c_iflag & IGNCR) linux_termios->c_iflag |= LINUX_IGNCR; if (bsd_termios->c_iflag & ICRNL) linux_termios->c_iflag |= LINUX_ICRNL; if (bsd_termios->c_iflag & IXON) linux_termios->c_iflag |= LINUX_IXANY; if (bsd_termios->c_iflag & IXON) linux_termios->c_iflag |= LINUX_IXON; if (bsd_termios->c_iflag & IXOFF) linux_termios->c_iflag |= LINUX_IXOFF; if (bsd_termios->c_iflag & IMAXBEL) linux_termios->c_iflag |= LINUX_IMAXBEL; linux_termios->c_oflag = 0; if (bsd_termios->c_oflag & OPOST) linux_termios->c_oflag |= LINUX_OPOST; if (bsd_termios->c_oflag & ONLCR) linux_termios->c_oflag |= LINUX_ONLCR; if (bsd_termios->c_oflag & OXTABS) linux_termios->c_oflag |= LINUX_XTABS; linux_termios->c_cflag = bsd_to_linux_speed(bsd_termios->c_ispeed, sptab); linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4; if (bsd_termios->c_cflag & CSTOPB) linux_termios->c_cflag |= LINUX_CSTOPB; if (bsd_termios->c_cflag & CREAD) linux_termios->c_cflag |= LINUX_CREAD; if (bsd_termios->c_cflag & PARENB) linux_termios->c_cflag |= LINUX_PARENB; if (bsd_termios->c_cflag & PARODD) linux_termios->c_cflag |= LINUX_PARODD; if (bsd_termios->c_cflag & HUPCL) linux_termios->c_cflag |= LINUX_HUPCL; if (bsd_termios->c_cflag & CLOCAL) linux_termios->c_cflag |= LINUX_CLOCAL; if (bsd_termios->c_cflag & CRTSCTS) linux_termios->c_cflag |= LINUX_CRTSCTS; linux_termios->c_lflag = 0; if (bsd_termios->c_lflag & ISIG) linux_termios->c_lflag |= LINUX_ISIG; if (bsd_termios->c_lflag & ICANON) linux_termios->c_lflag |= LINUX_ICANON; if (bsd_termios->c_lflag & ECHO) linux_termios->c_lflag |= LINUX_ECHO; if (bsd_termios->c_lflag & ECHOE) linux_termios->c_lflag |= LINUX_ECHOE; if (bsd_termios->c_lflag & ECHOK) linux_termios->c_lflag |= LINUX_ECHOK; if (bsd_termios->c_lflag & ECHONL) linux_termios->c_lflag |= LINUX_ECHONL; if (bsd_termios->c_lflag & NOFLSH) linux_termios->c_lflag |= LINUX_NOFLSH; if (bsd_termios->c_lflag & TOSTOP) linux_termios->c_lflag |= LINUX_TOSTOP; if (bsd_termios->c_lflag & ECHOCTL) linux_termios->c_lflag |= LINUX_ECHOCTL; if (bsd_termios->c_lflag & ECHOPRT) linux_termios->c_lflag |= LINUX_ECHOPRT; if (bsd_termios->c_lflag & ECHOKE) linux_termios->c_lflag |= LINUX_ECHOKE; if (bsd_termios->c_lflag & FLUSHO) linux_termios->c_lflag |= LINUX_FLUSHO; if (bsd_termios->c_lflag & PENDIN) linux_termios->c_lflag |= LINUX_PENDIN; if (bsd_termios->c_lflag & IEXTEN) linux_termios->c_lflag |= LINUX_IEXTEN; for (i=0; ic_cc[i] = _POSIX_VDISABLE; linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR]; linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT]; linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE]; linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL]; linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF]; linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL]; linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN]; linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME]; linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2]; linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE; linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP]; linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART]; linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP]; linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT]; linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD]; linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE]; linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT]; linux_termios->c_line = 0; #ifdef DEBUG printf("LINUX: LINUX termios structure (output):\n"); printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, linux_termios->c_lflag, linux_termios->c_line); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif } static void linux_to_bsd_termios(struct linux_termios *linux_termios, struct termios *bsd_termios) { int i, speed; #ifdef DEBUG printf("LINUX: LINUX termios structure (input):\n"); printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, linux_termios->c_lflag, linux_termios->c_line); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif bsd_termios->c_iflag = 0; if (linux_termios->c_iflag & LINUX_IGNBRK) bsd_termios->c_iflag |= IGNBRK; if (linux_termios->c_iflag & LINUX_BRKINT) bsd_termios->c_iflag |= BRKINT; if (linux_termios->c_iflag & LINUX_IGNPAR) bsd_termios->c_iflag |= IGNPAR; if (linux_termios->c_iflag & LINUX_PARMRK) bsd_termios->c_iflag |= PARMRK; if (linux_termios->c_iflag & LINUX_INPCK) bsd_termios->c_iflag |= INPCK; if (linux_termios->c_iflag & LINUX_ISTRIP) bsd_termios->c_iflag |= ISTRIP; if (linux_termios->c_iflag & LINUX_INLCR) bsd_termios->c_iflag |= INLCR; if (linux_termios->c_iflag & LINUX_IGNCR) bsd_termios->c_iflag |= IGNCR; if (linux_termios->c_iflag & LINUX_ICRNL) bsd_termios->c_iflag |= ICRNL; if (linux_termios->c_iflag & LINUX_IXON) bsd_termios->c_iflag |= IXANY; if (linux_termios->c_iflag & LINUX_IXON) bsd_termios->c_iflag |= IXON; if (linux_termios->c_iflag & LINUX_IXOFF) bsd_termios->c_iflag |= IXOFF; if (linux_termios->c_iflag & LINUX_IMAXBEL) bsd_termios->c_iflag |= IMAXBEL; bsd_termios->c_oflag = 0; if (linux_termios->c_oflag & LINUX_OPOST) bsd_termios->c_oflag |= OPOST; if (linux_termios->c_oflag & LINUX_ONLCR) bsd_termios->c_oflag |= ONLCR; if (linux_termios->c_oflag & LINUX_XTABS) bsd_termios->c_oflag |= OXTABS; bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4; if (linux_termios->c_cflag & LINUX_CSTOPB) bsd_termios->c_cflag |= CSTOPB; if (linux_termios->c_cflag & LINUX_PARENB) bsd_termios->c_cflag |= PARENB; if (linux_termios->c_cflag & LINUX_PARODD) bsd_termios->c_cflag |= PARODD; if (linux_termios->c_cflag & LINUX_HUPCL) bsd_termios->c_cflag |= HUPCL; if (linux_termios->c_cflag & LINUX_CLOCAL) bsd_termios->c_cflag |= CLOCAL; if (linux_termios->c_cflag & LINUX_CRTSCTS) bsd_termios->c_cflag |= CRTSCTS; bsd_termios->c_lflag = 0; if (linux_termios->c_lflag & LINUX_ISIG) bsd_termios->c_lflag |= ISIG; if (linux_termios->c_lflag & LINUX_ICANON) bsd_termios->c_lflag |= ICANON; if (linux_termios->c_lflag & LINUX_ECHO) bsd_termios->c_lflag |= ECHO; if (linux_termios->c_lflag & LINUX_ECHOE) bsd_termios->c_lflag |= ECHOE; if (linux_termios->c_lflag & LINUX_ECHOK) bsd_termios->c_lflag |= ECHOK; if (linux_termios->c_lflag & LINUX_ECHONL) bsd_termios->c_lflag |= ECHONL; if (linux_termios->c_lflag & LINUX_NOFLSH) bsd_termios->c_lflag |= NOFLSH; if (linux_termios->c_lflag & LINUX_TOSTOP) bsd_termios->c_lflag |= TOSTOP; if (linux_termios->c_lflag & LINUX_ECHOCTL) bsd_termios->c_lflag |= ECHOCTL; if (linux_termios->c_lflag & LINUX_ECHOPRT) bsd_termios->c_lflag |= ECHOPRT; if (linux_termios->c_lflag & LINUX_ECHOKE) bsd_termios->c_lflag |= ECHOKE; if (linux_termios->c_lflag & LINUX_FLUSHO) bsd_termios->c_lflag |= FLUSHO; if (linux_termios->c_lflag & LINUX_PENDIN) bsd_termios->c_lflag |= PENDIN; if (linux_termios->c_lflag & IEXTEN) bsd_termios->c_lflag |= IEXTEN; for (i=0; ic_cc[i] = _POSIX_VDISABLE; bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR]; bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT]; bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE]; bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL]; bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF]; bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL]; bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN]; bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME]; bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2]; bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP]; bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART]; bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP]; bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT]; bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD]; bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE]; bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT]; bsd_termios->c_ispeed = bsd_termios->c_ospeed = linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab); #ifdef DEBUG printf("LINUX: BSD termios structure (output):\n"); printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", bsd_termios->c_iflag, bsd_termios->c_oflag, bsd_termios->c_cflag, bsd_termios->c_lflag, bsd_termios->c_ispeed, bsd_termios->c_ospeed); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif } - -struct linux_ioctl_args { - int fd; - int cmd; - int arg; -}; - int linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval) { struct termios bsd_termios; struct winsize bsd_winsize; struct linux_termios linux_termios; struct linux_winsize linux_winsize; struct filedesc *fdp = p->p_fd; struct file *fp; int (*func)(struct file *fp, int com, caddr_t data, struct proc *p); int bsd_line, linux_line; int error; #ifdef DEBUG printf("Linux-emul(%d): ioctl(%d, %04x, *)\n", p->p_pid, args->fd, args->cmd); #endif if ((unsigned)args->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[args->fd]) == 0) return EBADF; if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { return EBADF; } func = fp->f_ops->fo_ioctl; switch (args->cmd & 0xffff) { case LINUX_TCGETS: if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) return error; bsd_to_linux_termios(&bsd_termios, &linux_termios); return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, sizeof(linux_termios)); case LINUX_TCSETS: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); case LINUX_TCSETSW: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); case LINUX_TCSETSF: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); case LINUX_TIOCGPGRP: args->cmd = TIOCGPGRP; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCSPGRP: args->cmd = TIOCSPGRP; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCGWINSZ: args->cmd = TIOCGWINSZ; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCSWINSZ: args->cmd = TIOCSWINSZ; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONREAD: args->cmd = FIONREAD; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONBIO: args->cmd = FIONBIO; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIOASYNC: args->cmd = FIOASYNC; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONCLEX: args->cmd = FIONCLEX; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIOCLEX: args->cmd = FIOCLEX; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCEXCL: args->cmd = TIOCEXCL; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCNXCL: args->cmd = TIOCNXCL; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCCONS: args->cmd = TIOCCONS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCNOTTY: 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: bsd_line = TTYDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); case LINUX_N_SLIP: bsd_line = SLIPDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); case LINUX_N_PPP: bsd_line = PPPDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); default: return EINVAL; } case LINUX_TIOCGETD: bsd_line = TTYDISC; if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p)) return error; switch (bsd_line) { case TTYDISC: linux_line = LINUX_N_TTY; break; case SLIPDISC: linux_line = LINUX_N_SLIP; break; case PPPDISC: linux_line = LINUX_N_PPP; break; default: return EINVAL; } return copyout(&linux_line, (caddr_t)args->arg, sizeof(int)); case LINUX_SNDCTL_DSP_RESET: args->cmd = SNDCTL_DSP_RESET; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SYNC: args->cmd = SNDCTL_DSP_SYNC; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SPEED: args->cmd = SNDCTL_DSP_SPEED; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_STEREO: args->cmd = SNDCTL_DSP_STEREO; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ args->cmd = SNDCTL_DSP_GETBLKSIZE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SETFMT: args->cmd = SNDCTL_DSP_SETFMT; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SOUND_PCM_WRITE_CHANNELS: args->cmd = SOUND_PCM_WRITE_CHANNELS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SOUND_PCM_WRITE_FILTER: args->cmd = SOUND_PCM_WRITE_FILTER; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_POST: args->cmd = SNDCTL_DSP_POST; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SUBDIVIDE: args->cmd = SNDCTL_DSP_SUBDIVIDE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SETFRAGMENT: args->cmd = SNDCTL_DSP_SETFRAGMENT; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETFMTS: args->cmd = SNDCTL_DSP_GETFMTS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETOSPACE: args->cmd = SNDCTL_DSP_GETOSPACE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETISPACE: args->cmd = SNDCTL_DSP_GETISPACE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_NONBLOCK: args->cmd = SNDCTL_DSP_NONBLOCK; return ioctl(p, (struct ioctl_args *)args, retval); } uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", args->fd, (args->cmd&0xffff00)>>8, (args->cmd&0xffff00)>>8, args->cmd&0xff); return EINVAL; } diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index 2e5b924bc38c..854766b99cc8 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -1,347 +1,353 @@ /*- * 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_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 $ */ #include #include #include #include #include #include -#include +#include +#include + +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; unsigned short uid; unsigned short gid; unsigned short cuid; unsigned short cgid; unsigned short mode; unsigned short seq; }; static void linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) { bpp->key = lpp->key; bpp->uid = lpp->uid; bpp->gid = lpp->gid; bpp->cuid = lpp->cuid; bpp->cgid = lpp->cgid; bpp->mode = lpp->mode; bpp->seq = lpp->seq; } static void bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) { lpp->key = bpp->key; lpp->uid = bpp->uid; lpp->gid = bpp->gid; lpp->cuid = bpp->cuid; lpp->cgid = bpp->cgid; lpp->mode = bpp->mode; lpp->seq = bpp->seq; } struct linux_shmid_ds { struct linux_ipc_perm shm_perm; int shm_segsz; linux_time_t shm_atime; linux_time_t shm_dtime; linux_time_t shm_ctime; ushort shm_cpid; ushort shm_lpid; short shm_nattch; ushort private1; void *private2; void *private3; }; static void linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); bsp->shm_segsz = lsp->shm_segsz; bsp->shm_lpid = lsp->shm_lpid; bsp->shm_cpid = lsp->shm_cpid; bsp->shm_nattch = lsp->shm_nattch; bsp->shm_atime = lsp->shm_atime; bsp->shm_dtime = lsp->shm_dtime; bsp->shm_ctime = lsp->shm_ctime; bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ } static void bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); lsp->shm_segsz = bsp->shm_segsz; lsp->shm_lpid = bsp->shm_lpid; lsp->shm_cpid = bsp->shm_cpid; lsp->shm_nattch = bsp->shm_nattch; lsp->shm_atime = bsp->shm_atime; lsp->shm_dtime = bsp->shm_dtime; lsp->shm_ctime = bsp->shm_ctime; 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 /* { int msqid; void *msgp; size_t msgsz; int msgflg; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.msgp = args->ptr; bsd_args.msgsz = args->arg2; bsd_args.msgflg = args->arg3; return msgsnd(p, &bsd_args, retval); } -int +static int linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgrcv_args /* { int msqid; void *msgp; size_t msgsz; long msgtyp; int msgflg; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.msgp = args->ptr; bsd_args.msgsz = args->arg2; bsd_args.msgtyp = 0; bsd_args.msgflg = args->arg3; return msgrcv(p, &bsd_args, retval); } -int +static int linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgget_args /* { key_t key; int msgflg; } */ bsd_args; bsd_args.key = args->arg1; bsd_args.msgflg = args->arg2; return msgget(p, &bsd_args, retval); } -int +static int linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgctl_args /* { int msqid; int cmd; struct msqid_ds *buf; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.cmd = args->arg2; bsd_args.buf = (struct msqid_ds *)args->ptr; return msgctl(p, &bsd_args, retval); } -int +static int linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmat_args /* { int shmid; void *shmaddr; int shmflg; } */ bsd_args; int error; bsd_args.shmid = args->arg1; bsd_args.shmaddr = args->ptr; bsd_args.shmflg = args->arg2; if ((error = shmat(p, &bsd_args, retval))) return error; if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) return error; retval[0] = 0; return 0; } -int +static int linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmdt_args /* { void *shmaddr; } */ bsd_args; bsd_args.shmaddr = args->ptr; return shmdt(p, &bsd_args, retval); } -int +static int linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmget_args /* { key_t key; int size; int shmflg; } */ bsd_args; bsd_args.key = args->arg1; bsd_args.size = args->arg2; bsd_args.shmflg = args->arg3; 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; struct linux_shmid_ds linux_shmid; struct shmctl_args /* { int shmid; int cmd; 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, sizeof(struct shmid_ds)))) return error; bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); case LINUX_IPC_SET: if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 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; bsd_args.shmid = args->arg1; bsd_args.cmd = IPC_SET; return shmctl(p, &bsd_args, retval); case LINUX_IPC_RMID: bsd_args.shmid = args->arg1; bsd_args.cmd = IPC_RMID; if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 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; return shmctl(p, &bsd_args, retval); case LINUX_IPC_INFO: case LINUX_SHM_STAT: case LINUX_SHM_INFO: case LINUX_SHM_LOCK: case LINUX_SHM_UNLOCK: default: uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); return EINVAL; } } int linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) { switch (args->what) { case LINUX_SEMOP: return linux_semop(p, args, retval); case LINUX_SEMGET: return linux_semget(p, args, retval); case LINUX_SEMCTL: return linux_semctl(p, args, retval); case LINUX_MSGSND: return linux_msgsnd(p, args, retval); case LINUX_MSGRCV: return linux_msgrcv(p, args, retval); case LINUX_MSGGET: return linux_msgget(p, args, retval); case LINUX_MSGCTL: return linux_msgctl(p, args, retval); case LINUX_SHMAT: return linux_shmat(p, args, retval); case LINUX_SHMDT: return linux_shmdt(p, args, retval); case LINUX_SHMGET: return linux_shmget(p, args, retval); case LINUX_SHMCTL: return linux_shmctl(p, args, retval); default: uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); return ENOSYS; } } diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index bc6e8d824b29..069ca28cf739 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1,781 +1,914 @@ /*- * 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 + * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include -#include - -struct linux_alarm_args { - unsigned int secs; -}; +#include +#include int linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval) { struct itimerval it, old_it; struct timeval tv; int s; #ifdef DEBUG printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs); #endif it.it_value.tv_sec = (long)args->secs; it.it_value.tv_usec = 0; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; s = splclock(); old_it = p->p_realtimer; tv = time; if (timerisset(&old_it.it_value)) if (timercmp(&old_it.it_value, &tv, <)) timerclear(&old_it.it_value); else timevalsub(&old_it.it_value, &tv); splx(s); if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) return EINVAL; s = splclock(); untimeout(realitexpire, (caddr_t)p); tv = time; if (timerisset(&it.it_value)) { timevaladd(&it.it_value, &tv); timeout(realitexpire, (caddr_t)p, hzto(&it.it_value)); } p->p_realtimer = it; splx(s); if (old_it.it_value.tv_usec) old_it.it_value.tv_sec++; *retval = old_it.it_value.tv_sec; return 0; } -struct linux_brk_args { - linux_caddr_t dsend; -}; - int linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) { #if 0 struct vmspace *vm = p->p_vmspace; vm_offset_t new, old; int error; if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) return EINVAL; if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) > p->p_rlimit[RLIMIT_DATA].rlim_cur) return ENOMEM; old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); new = round_page((vm_offset_t)args->dsend); *retval = old; if ((new-old) > 0) { if (swap_pager_full) 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)); } return 0; #else struct vmspace *vm = p->p_vmspace; vm_offset_t new, old; struct obreak_args /* { char * nsize; } */ tmp; #ifdef DEBUG printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend); #endif old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); new = (vm_offset_t)args->dsend; tmp.nsize = (char *) new; if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval)) retval[0] = (int)new; else retval[0] = (int)old; return 0; #endif } -struct linux_uselib_args { - char *library; -}; - int linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) { struct nameidata ni; struct vnode *vp; struct exec *a_out; struct vattr attr; 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 a_out = NULL; 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; vp = ni.ni_vp; if (vp == NULL) { error = ENOEXEC; /* ?? */ goto cleanup; } /* * From here on down, we have a locked vnode that must be unlocked. */ locked++; /* * Writable? */ if (vp->v_writecount) { error = ETXTBSY; goto cleanup; } /* * Executable? */ if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) goto cleanup; if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { error = ENOEXEC; goto cleanup; } /* * Sensible size? */ if (attr.va_size == 0) { error = ENOEXEC; goto cleanup; } /* * Can we access it? */ if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) goto cleanup; if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) goto cleanup; /* * Lock no longer needed */ VOP_UNLOCK(vp); locked = 0; /* * Pull in executable header into kernel_map */ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); if (error) goto cleanup; /* * Is it a Linux binary ? */ if (((a_out->a_magic >> 16) & 0xff) != 0x64) { error = ENOEXEC; goto cleanup; } /* While we are here, we should REALLY do some more checks */ /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: /* ZMAGIC */ file_offset = 1024; break; case 0314: /* QMAGIC */ file_offset = 0; break; default: error = ENOEXEC; goto cleanup; } bss_size = round_page(a_out->a_bss); /* * Check various fields in header for validity/bounds. */ if (a_out->a_text % NBPG || a_out->a_data % NBPG) { error = ENOEXEC; goto cleanup; } /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > attr.va_size) { error = EFAULT; goto cleanup; } /* * text/data/bss must not exceed limits * XXX: this is not complete. it should check current usage PLUS * the resources needed by this library. */ if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || a_out->a_data+bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { error = ENOMEM; goto cleanup; } /* * prevent more writers */ vp->v_flag |= VTEXT; /* * Check if file_offset page aligned,. * Currently we cannot handle misalinged file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PGOFSET) { #ifdef DEBUG printf("uselib: Non page aligned binary %d\n", file_offset); #endif /* * Map text+data read/write/execute */ /* a_entry is the load address and is page aligned */ vmaddr = trunc_page(a_out->a_entry); /* get anon user mapping, read+write+execute */ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto cleanup; /* map file into kernel_map */ error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, MAP_FILE, (caddr_t)vp, trunc_page(file_offset)); if (error) 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 */ vm_map_remove(kernel_map, buffer, round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) goto cleanup; } else { #ifdef DEBUG printf("uselib: Page aligned binary %d\n", file_offset); #endif /* * for QMAGIC, a_entry is 20 bytes beyond the load address * to skip the executable header */ vmaddr = trunc_page(a_out->a_entry); /* * Map it all into the process's space as a single copy-on-write * "data" segment. */ error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset); if (error) goto cleanup; } #ifdef DEBUG printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]); #endif if (bss_size != 0) { /* * Calculate BSS start address */ vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; /* * 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) goto cleanup; } cleanup: /* * Unlock vnode if needed */ if (locked) VOP_UNLOCK(vp); /* * Release the kernel mapping. */ if (a_out) vm_map_remove(kernel_map, (vm_offset_t)a_out, PAGE_SIZE); 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) { struct proc *curproc; #ifdef DEBUG printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid); #endif if (args->pid != p->p_pid) { if (!(curproc = pfind(args->pid))) return ESRCH; } else curproc = p; *retval = curproc->p_pgid; return 0; } 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; int prot; int flags; int fd; long pad; 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; if (linux_args.flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (linux_args.flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; if (linux_args.flags & LINUX_MAP_FIXED) bsd_args.flags |= MAP_FIXED; if (linux_args.flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; bsd_args.addr = linux_args.addr; bsd_args.len = linux_args.len; bsd_args.prot = linux_args.prot; bsd_args.fd = linux_args.fd; bsd_args.pos = linux_args.pos; bsd_args.pad = 0; 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) { int error; #ifdef DEBUG printf("Linux-emul(%d): pipe(*)\n", p->p_pid); #endif if (error = pipe(p, 0, retval)) return error; if (error = copyout(retval, args->pipefds, 2*sizeof(int))) return error; *retval = 0; return 0; } -struct linux_time_args { - linux_time_t *tm; -}; - int linux_time(struct proc *p, struct linux_time_args *args, int *retval) { struct timeval tv; linux_time_t tm; int error; #ifdef DEBUG printf("Linux-emul(%d): time(*)\n", p->p_pid); #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); #endif tms.tms_utime = p->p_uticks; tms.tms_stime = p->p_sticks; tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz + ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000); tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz + ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000); 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]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; -struct linux_newuname_args { - char *buf; -}; - int linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval) { struct linux_newuname_t linux_newuname; #ifdef DEBUG printf("Linux-emul(%d): newuname(*)\n", p->p_pid); #endif bzero(&linux_newuname, sizeof(struct linux_newuname_args)); strncpy(linux_newuname.sysname, ostype, 64); strncpy(linux_newuname.nodename, hostname, 64); strncpy(linux_newuname.release, osrelease, 64); strncpy(linux_newuname.version, version, 64); strncpy(linux_newuname.machine, machine, 64); strncpy(linux_newuname.domainname, domainname, 64); return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf, 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) { struct utimes_args /* { char *path; 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) { struct wait_args /* { int pid; int *status; int options; struct rusage *rusage; } */ tmp; 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; tmp.options = args->options; tmp.rusage = NULL; 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 /* { int pid; int *status; int options; struct rusage *rusage; } */ tmp; 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; tmp.options = args->options; tmp.rusage = args->rusage; 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/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index fc5c2cd7c274..32648cb217a9 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -1,261 +1,311 @@ /*- * 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_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 #include #include #include #include #include #include #include -#include - -#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD)) +#include +#include 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; } sa.signum = linux_to_bsd_signal[args->sig]; sa.nsa = nsa; sa.osa = osa; if ((error = sigaction(p, &sa, retval))) return error; 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, int *retval) { int error, s; sigset_t mask; sigset_t omask; #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; } if (!(args->mask)) return 0; 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; break; } splx(s); return error; } 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) { linux_sigset_t linux_sig; #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) { struct kill_args /* { int pid; int signum; } */ tmp; #ifdef DEBUG printf("Linux-emul(%d): kill(%d, %d)\n", p->p_pid, args->pid, args->signum); #endif tmp.pid = args->pid; tmp.signum = linux_to_bsd_signal[args->signum]; return kill(p, &tmp, retval); } diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index da4668c674e1..63b33d50c9be 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -1,601 +1,596 @@ /*- * Copyright (c) 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_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. */ #define COMPAT_43 1 #include #include #include #include #include #include #include #include -#include +#include static int linux_to_bsd_domain(int domain) { switch (domain) { case LINUX_AF_UNSPEC: return AF_UNSPEC; case LINUX_AF_UNIX: return AF_LOCAL; case LINUX_AF_INET: return AF_INET; case LINUX_AF_AX25: return AF_CCITT; case LINUX_AF_IPX: return AF_IPX; case LINUX_AF_APPLETALK: return AF_APPLETALK; default: return -1; } } static int linux_to_bsd_sockopt_level(int level) { switch (level) { case LINUX_SOL_SOCKET: return SOL_SOCKET; default: return level; } } static int linux_to_bsd_ip_sockopt(int opt) { switch (opt) { case LINUX_IP_TOS: return IP_TOS; case LINUX_IP_TTL: return IP_TTL; default: return -1; } } static int linux_to_bsd_so_sockopt(int opt) { switch (opt) { case LINUX_SO_DEBUG: return SO_DEBUG; case LINUX_SO_REUSEADDR: return SO_REUSEADDR; case LINUX_SO_TYPE: return SO_TYPE; case LINUX_SO_ERROR: return SO_ERROR; case LINUX_SO_DONTROUTE: return SO_DONTROUTE; case LINUX_SO_BROADCAST: return SO_BROADCAST; case LINUX_SO_SNDBUF: return SO_SNDBUF; case LINUX_SO_RCVBUF: return SO_RCVBUF; case LINUX_SO_KEEPALIVE: return SO_KEEPALIVE; case LINUX_SO_OOBINLINE: return SO_OOBINLINE; case LINUX_SO_LINGER: return SO_LINGER; case LINUX_SO_PRIORITY: case LINUX_SO_NO_CHECK: default: return -1; } } struct linux_socket_args { int domain; int type; int protocol; }; static int linux_socket(struct proc *p, struct linux_socket_args *args, int *retval) { struct linux_socket_args linux_args; struct socket_args /* { int domain; int type; int protocol; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.protocol = linux_args.protocol; bsd_args.type = linux_args.type; bsd_args.domain = linux_to_bsd_domain(linux_args.domain); if (bsd_args.domain == -1) return EINVAL; return socket(p, &bsd_args, retval); } struct linux_bind_args { int s; struct sockaddr *name; int namelen; }; static int linux_bind(struct proc *p, struct linux_bind_args *args, int *retval) { struct linux_bind_args linux_args; struct bind_args /* { int s; caddr_t name; int namelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.name; bsd_args.namelen = linux_args.namelen; return bind(p, &bsd_args, retval); } struct linux_connect_args { int s; struct sockaddr * name; int namelen; }; static int linux_connect(struct proc *p, struct linux_connect_args *args, int *retval) { struct linux_connect_args linux_args; struct connect_args /* { int s; caddr_t name; int namelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.name; bsd_args.namelen = linux_args.namelen; return connect(p, &bsd_args, retval); } struct linux_listen_args { int s; int backlog; }; static int linux_listen(struct proc *p, struct linux_listen_args *args, int *retval) { struct linux_listen_args linux_args; struct listen_args /* { int s; int backlog; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.backlog = linux_args.backlog; return listen(p, &bsd_args, retval); } struct linux_accept_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_accept(struct proc *p, struct linux_accept_args *args, int *retval) { struct linux_accept_args linux_args; struct accept_args /* { int s; caddr_t name; int *anamelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.addr; bsd_args.anamelen = linux_args.namelen; return oaccept(p, &bsd_args, retval); } struct linux_getsockname_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval) { struct linux_getsockname_args linux_args; struct getsockname_args /* { int fdes; caddr_t asa; int *alen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.fdes = linux_args.s; bsd_args.asa = (caddr_t) linux_args.addr; bsd_args.alen = linux_args.namelen; return ogetsockname(p, &bsd_args, retval); } struct linux_getpeername_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval) { struct linux_getpeername_args linux_args; struct ogetpeername_args /* { int fdes; caddr_t asa; int *alen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.fdes = linux_args.s; bsd_args.asa = (caddr_t) linux_args.addr; bsd_args.alen = linux_args.namelen; return ogetpeername(p, &bsd_args, retval); } struct linux_socketpair_args { int domain; int type; int protocol; int *rsv; }; static int linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval) { struct linux_socketpair_args linux_args; struct socketpair_args /* { int domain; int type; int protocol; int *rsv; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.domain = linux_to_bsd_domain(linux_args.domain); if (bsd_args.domain == -1) return EINVAL; bsd_args.type = linux_args.type; bsd_args.protocol = linux_args.protocol; bsd_args.rsv = linux_args.rsv; return socketpair(p, &bsd_args, retval); } struct linux_send_args { int s; void *msg; int len; int flags; }; static int linux_send(struct proc *p, struct linux_send_args *args, int *retval) { struct linux_send_args linux_args; struct osend_args /* { int s; caddr_t buf; int len; int flags; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; return osend(p, &bsd_args, retval); } struct linux_recv_args { int s; void *msg; int len; int flags; }; static int linux_recv(struct proc *p, struct linux_recv_args *args, int *retval) { struct linux_recv_args linux_args; struct orecv_args /* { int s; caddr_t buf; int len; int flags; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; return orecv(p, &bsd_args, retval); } struct linux_sendto_args { int s; void *msg; int len; int flags; caddr_t to; int tolen; }; static int linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval) { struct linux_sendto_args linux_args; struct sendto_args /* { int s; caddr_t buf; size_t len; int flags; caddr_t to; int tolen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; bsd_args.to = linux_args.to; bsd_args.tolen = linux_args.tolen; return sendto(p, &bsd_args, retval); } struct linux_recvfrom_args { int s; void *buf; int len; int flags; caddr_t from; int *fromlen; }; static int linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval) { struct linux_recvfrom_args linux_args; struct recvfrom_args /* { int s; caddr_t buf; size_t len; int flags; caddr_t from; int *fromlenaddr; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.buf; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; bsd_args.from = linux_args.from; bsd_args.fromlenaddr = linux_args.fromlen; return orecvfrom(p, &bsd_args, retval); } struct linux_shutdown_args { int s; int how; }; static int linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval) { struct linux_shutdown_args linux_args; struct shutdown_args /* { int s; int how; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.how = linux_args.how; return shutdown(p, &bsd_args, retval); } struct linux_setsockopt_args { int s; int level; int optname; void *optval; int optlen; }; static int linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval) { struct linux_setsockopt_args linux_args; struct setsockopt_args /* { int s; int level; int name; caddr_t val; int valsize; } */ bsd_args; int error, name; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); switch (bsd_args.level) { case SOL_SOCKET: name = linux_to_bsd_so_sockopt(linux_args.optname); break; case IPPROTO_IP: name = linux_to_bsd_ip_sockopt(linux_args.optname); break; default: return EINVAL; } if (name == -1) return EINVAL; bsd_args.name = name; bsd_args.val = linux_args.optval; bsd_args.valsize = linux_args.optlen; return setsockopt(p, &bsd_args, retval); } struct linux_getsockopt_args { int s; int level; int optname; void *optval; int *optlen; }; static int linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval) { struct linux_getsockopt_args linux_args; struct getsockopt_args /* { int s; int level; int name; caddr_t val; int *avalsize; } */ bsd_args; int error, name; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); switch (bsd_args.level) { case SOL_SOCKET: name = linux_to_bsd_so_sockopt(linux_args.optname); break; case IPPROTO_IP: name = linux_to_bsd_ip_sockopt(linux_args.optname); break; default: return EINVAL; } if (name == -1) return EINVAL; bsd_args.val = linux_args.optval; bsd_args.avalsize = linux_args.optlen; 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) { switch (args->what) { case LINUX_SOCKET: return linux_socket(p, args->args, retval); case LINUX_BIND: return linux_bind(p, args->args, retval); case LINUX_CONNECT: return linux_connect(p, args->args, retval); case LINUX_LISTEN: return linux_listen(p, args->args, retval); case LINUX_ACCEPT: return linux_accept(p, args->args, retval); case LINUX_GETSOCKNAME: return linux_getsockname(p, args->args, retval); case LINUX_GETPEERNAME: return linux_getpeername(p, args->args, retval); case LINUX_SOCKETPAIR: return linux_socketpair(p, args->args, retval); case LINUX_SEND: return linux_send(p, args->args, retval); case LINUX_RECV: return linux_recv(p, args->args, retval); case LINUX_SENDTO: return linux_sendto(p, args->args, retval); case LINUX_RECVFROM: return linux_recvfrom(p, args->args, retval); case LINUX_SHUTDOWN: return linux_shutdown(p, args->args, retval); case LINUX_SETSOCKOPT: return linux_setsockopt(p, args->args, retval); case LINUX_GETSOCKOPT: return linux_getsockopt(p, args->args, retval); default: uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); return ENOSYS; } } diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 327343bd544f..8d562e0eff72 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -1,270 +1,297 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include +#include struct linux_newstat { unsigned short stat_dev; unsigned short __pad1; unsigned long stat_ino; unsigned short stat_mode; unsigned short stat_nlink; unsigned short stat_uid; unsigned short stat_gid; unsigned short stat_rdev; unsigned short __pad2; unsigned long stat_size; unsigned long stat_blksize; unsigned long stat_blocks; unsigned long stat_atime; unsigned long __unused1; unsigned long stat_mtime; unsigned long __unused2; unsigned long stat_ctime; unsigned long __unused3; unsigned long __unused4; unsigned long __unused5; }; -struct linux_newstat_args { - char *path; - struct linux_newstat *buf; -}; static int newstat_copyout(struct stat *buf, void *ubuf) { struct linux_newstat tbuf; tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10); tbuf.stat_ino = buf->st_ino; tbuf.stat_mode = buf->st_mode; tbuf.stat_nlink = buf->st_nlink; tbuf.stat_uid = buf->st_uid; tbuf.stat_gid = buf->st_gid; tbuf.stat_rdev = buf->st_rdev; tbuf.stat_size = buf->st_size; tbuf.stat_atime = buf->st_atime; tbuf.stat_mtime = buf->st_mtime; tbuf.stat_ctime = buf->st_ctime; tbuf.stat_blksize = buf->st_blksize; tbuf.stat_blocks = buf->st_blocks; return copyout(&tbuf, ubuf, sizeof(tbuf)); } 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); #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; } +/* + * 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) return EBADF; switch (fp->f_type) { case DTYPE_VNODE: error = vn_stat((struct vnode *)fp->f_data, &buf, p); break; case DTYPE_SOCKET: error = soo_stat((struct socket *)fp->f_data, &buf); break; case DTYPE_PIPE: error = pipe_stat((struct pipe *)fp->f_data, &buf); break; default: panic("LINUX newfstat"); } if (!error) error = newstat_copyout(&buf, args->buf); return error; } -struct linux_statfs { +struct linux_statfs_buf { long ftype; long fbsize; long fblocks; long fbfree; long fbavail; long ffiles; long fffree; linux_fsid_t ffsid; long fnamelen; 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) { struct mount *mp; 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); #endif ndp = &nd; NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curproc); if (error = namei(ndp)) return error; mp = ndp->ni_vp->v_mount; bsd_statfs = &mp->mnt_stat; vrele(ndp->ni_vp); 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 printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd); #endif if (error = getvnode(p->p_fd, args->fd, &fp)) return error; mp = ((struct vnode *)fp->f_data)->v_mount; bsd_statfs = &mp->mnt_stat; 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/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c new file mode 100644 index 000000000000..1785fd315a10 --- /dev/null +++ b/sys/compat/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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/compat/linux/linux_util.h similarity index 50% rename from sys/i386/linux/linux_generic.c rename to sys/compat/linux/linux_util.h index da528c18daa5..46edfc52aae9 100644 --- a/sys/i386/linux/linux_generic.c +++ b/sys/compat/linux/linux_util.h @@ -1,61 +1,92 @@ -/*- - * 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 * 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_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 -#include -#include +/* + * This file is pretty much the same as Christos' svr4_util.h + * (for now). + */ -#include /* XXX for a macro in exec.h */ +#ifndef _LINUX_UTIL_H_ +#define _LINUX_UTIL_H_ + +#include #include #include #include +#include +#include +#include -#include +#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/conf/Makefile.i386 b/sys/conf/Makefile.i386 index f88dd84a6bda..3ba84a5d1008 100644 --- a/sys/conf/Makefile.i386 +++ b/sys/conf/Makefile.i386 @@ -1,186 +1,187 @@ # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.74 1996/01/07 22:31:27 phk Exp $ +# $Id: Makefile.i386,v 1.75 1996/01/08 03:55:36 peter Exp $ # # Makefile for FreeBSD # # This makefile is constructed from a machine description: # config machineid # Most changes should be made in the machine description # /sys/i386/conf/``machineid'' # after which you should do # config machineid # Generic makefile changes should be made in # /sys/i386/conf/Makefile.i386 # after which config should be rerun for all machines. # CC?= cc CPP?= cpp LD?= /usr/bin/ld .if exists(./@/.) S= ./@ .else S= ../.. .endif I386= ${S}/i386 CWARNFLAGS?= -W -Wreturn-type -Wcomment -Wredundant-decls -Wimplicit \ -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes \ -Winline # # The following flags are next up for working on: # -Wall # # When working on removing warnings from code, the `-Werror' flag should be # of material assistance. # COPTFLAGS?=-O # Not ready for -I- yet. #include "foo.h" where foo.h is in the srcdir fails. INCLUDES= -nostdinc -I. -I$S -I$S/sys # This hack is to allow kernel compiles to succeed on machines w/out srcdist .if exists($S/../include) INCLUDES+= -I$S/../include .else INCLUDES+= -I/usr/include .endif COPTS= ${INCLUDES} ${IDENT} -DKERNEL ASFLAGS= CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} LOAD_ADDRESS?= F0100000 NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< # XXX errors leak out of all the pipes. Should use cc *.S. # XXX LOCORE means "don't declare C stuff" not "for locore.s". NORMAL_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< DRIVER_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< SYSTEM_CFILES= ioconf.c param.c vnode_if.c SYSTEM_SFILES= ${I386}/i386/locore.s SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ SYSTEM_LD= @${LD} -Bstatic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o .if ${CFLAGS:M-g} == "" SYMORDER_EXCLUDE=-x symbols.exclude .endif SYSTEM_LD_TAIL= @echo rearranging symbols; \ symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \ size $@; chmod 755 $@ %BEFORE_DEPEND %OBJS %CFILES %SFILES %LOAD %CLEAN clean: rm -f *.o *.s eddep errs genassym kernel linterrs \ makelinks param.c symbols.exclude symbols.sort tags \ vers.c vnode_if.c vnode_if.h ${CLEAN} #lint: /tmp param.c # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ # ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ # grep -v 'struct/union .* never defined' | \ # grep -v 'possible pointer alignment problem' symbols.exclude: Makefile echo "gcc2_compiled." >symbols.exclude echo "___gnu_compiled_c" >>symbols.exclude symbols.sort: ${I386}/i386/symbols.raw grep -v '^#' ${I386}/i386/symbols.raw \ | sed 's/^ //' | sort -u > symbols.sort locore.o: ${I386}/i386/locore.s assym.s ${NORMAL_S} # everything potentially depends on the Makefile since everything potentially # depends on the options. Some things are more dependent on the Makefile for # historical reasons. machdep.o: Makefile # the following is necessary because autoconf.o depends on #if GENERIC autoconf.o: Makefile # XXX - may no longer be needed locore.o: Makefile # depends on KDB (cons.o also depends on GENERIC) trap.o cons.o: Makefile # this rule stops ./assym.s in .depend from causing problems ./assym.s: assym.s assym.s: genassym ./genassym >assym.s # Some of the defines that genassym outputs may well depend on the # value of kernel options. genassym.o: ${I386}/i386/genassym.c Makefile ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c genassym: genassym.o ${CC} -static ${CFLAGS} ${PARAM} genassym.o -o $@ # XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} - mkdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + rm -f .depend + mkdep -a ${COPTS} ${CFILES} ${SYSTEM_CFILES} mkdep -a ${COPTS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c MKDEP_CPP=${CPP} ; export MKDEP_CPP ; \ mkdep -a -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} links: egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ sort -u | comm -23 - dontlink | \ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink tags: @echo "see $S/kern/Makefile for tags" install: chflags noschg /kernel mv /kernel /kernel.old if [ `sysctl -n kern.bootfile` = "/kernel" ] ; then \ sysctl -w kern.bootfile=/kernel.old ; \ mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ fi install -c -m 555 -o root -g wheel -fschg kernel / ioconf.o: ioconf.c $S/sys/param.h machine/pte.h $S/sys/buf.h \ ${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h ${CC} -c ${CFLAGS} ioconf.c param.c: $S/conf/param.c -rm -f param.c cp $S/conf/param.c . param.o: param.c Makefile ${CC} -c ${CFLAGS} ${PARAM} param.c vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} ${CC} ${CFLAGS} -c vers.c vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src %RULES # DO NOT DELETE THIS LINE -- make depend uses it diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc index f88dd84a6bda..3ba84a5d1008 100644 --- a/sys/conf/Makefile.powerpc +++ b/sys/conf/Makefile.powerpc @@ -1,186 +1,187 @@ # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.74 1996/01/07 22:31:27 phk Exp $ +# $Id: Makefile.i386,v 1.75 1996/01/08 03:55:36 peter Exp $ # # Makefile for FreeBSD # # This makefile is constructed from a machine description: # config machineid # Most changes should be made in the machine description # /sys/i386/conf/``machineid'' # after which you should do # config machineid # Generic makefile changes should be made in # /sys/i386/conf/Makefile.i386 # after which config should be rerun for all machines. # CC?= cc CPP?= cpp LD?= /usr/bin/ld .if exists(./@/.) S= ./@ .else S= ../.. .endif I386= ${S}/i386 CWARNFLAGS?= -W -Wreturn-type -Wcomment -Wredundant-decls -Wimplicit \ -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes \ -Winline # # The following flags are next up for working on: # -Wall # # When working on removing warnings from code, the `-Werror' flag should be # of material assistance. # COPTFLAGS?=-O # Not ready for -I- yet. #include "foo.h" where foo.h is in the srcdir fails. INCLUDES= -nostdinc -I. -I$S -I$S/sys # This hack is to allow kernel compiles to succeed on machines w/out srcdist .if exists($S/../include) INCLUDES+= -I$S/../include .else INCLUDES+= -I/usr/include .endif COPTS= ${INCLUDES} ${IDENT} -DKERNEL ASFLAGS= CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} LOAD_ADDRESS?= F0100000 NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< # XXX errors leak out of all the pipes. Should use cc *.S. # XXX LOCORE means "don't declare C stuff" not "for locore.s". NORMAL_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< DRIVER_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< SYSTEM_CFILES= ioconf.c param.c vnode_if.c SYSTEM_SFILES= ${I386}/i386/locore.s SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ SYSTEM_LD= @${LD} -Bstatic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o .if ${CFLAGS:M-g} == "" SYMORDER_EXCLUDE=-x symbols.exclude .endif SYSTEM_LD_TAIL= @echo rearranging symbols; \ symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \ size $@; chmod 755 $@ %BEFORE_DEPEND %OBJS %CFILES %SFILES %LOAD %CLEAN clean: rm -f *.o *.s eddep errs genassym kernel linterrs \ makelinks param.c symbols.exclude symbols.sort tags \ vers.c vnode_if.c vnode_if.h ${CLEAN} #lint: /tmp param.c # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ # ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ # grep -v 'struct/union .* never defined' | \ # grep -v 'possible pointer alignment problem' symbols.exclude: Makefile echo "gcc2_compiled." >symbols.exclude echo "___gnu_compiled_c" >>symbols.exclude symbols.sort: ${I386}/i386/symbols.raw grep -v '^#' ${I386}/i386/symbols.raw \ | sed 's/^ //' | sort -u > symbols.sort locore.o: ${I386}/i386/locore.s assym.s ${NORMAL_S} # everything potentially depends on the Makefile since everything potentially # depends on the options. Some things are more dependent on the Makefile for # historical reasons. machdep.o: Makefile # the following is necessary because autoconf.o depends on #if GENERIC autoconf.o: Makefile # XXX - may no longer be needed locore.o: Makefile # depends on KDB (cons.o also depends on GENERIC) trap.o cons.o: Makefile # this rule stops ./assym.s in .depend from causing problems ./assym.s: assym.s assym.s: genassym ./genassym >assym.s # Some of the defines that genassym outputs may well depend on the # value of kernel options. genassym.o: ${I386}/i386/genassym.c Makefile ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c genassym: genassym.o ${CC} -static ${CFLAGS} ${PARAM} genassym.o -o $@ # XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} - mkdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + rm -f .depend + mkdep -a ${COPTS} ${CFILES} ${SYSTEM_CFILES} mkdep -a ${COPTS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c MKDEP_CPP=${CPP} ; export MKDEP_CPP ; \ mkdep -a -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} links: egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ sort -u | comm -23 - dontlink | \ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink tags: @echo "see $S/kern/Makefile for tags" install: chflags noschg /kernel mv /kernel /kernel.old if [ `sysctl -n kern.bootfile` = "/kernel" ] ; then \ sysctl -w kern.bootfile=/kernel.old ; \ mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ fi install -c -m 555 -o root -g wheel -fschg kernel / ioconf.o: ioconf.c $S/sys/param.h machine/pte.h $S/sys/buf.h \ ${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h ${CC} -c ${CFLAGS} ioconf.c param.c: $S/conf/param.c -rm -f param.c cp $S/conf/param.c . param.o: param.c Makefile ${CC} -c ${CFLAGS} ${PARAM} param.c vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} ${CC} ${CFLAGS} -c vers.c vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src %RULES # DO NOT DELETE THIS LINE -- make depend uses it diff --git a/sys/conf/NOTES b/sys/conf/NOTES index ce1bae2667ec..c2e6a38fb084 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1,855 +1,854 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.240 1996/02/23 15:47:41 phk Exp $ +# $Id: LINT,v 1.241 1996/02/28 21:39:54 gpalmer Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family. You must also specify # at least one CPU (the one you intend to run on); deleting the # specification for CPUs you don't need to use may make parts of the # system run faster # machine "i386" cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Under some circumstances it is necessary to make the default max # number of processes per user and open files per user more than the # defaults on bootup. (an example is a large news server in which # the uid, news, can sometimes need > 100 simultaneous processes running, # or perhaps a user using lots of windows under X). options CHILD_MAX=128 options OPEN_MAX=128 # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # Allow ordinary users to take the console - this is useful for X. options UCONSOLE ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service), ISO (OSI), and # CCITT (X.25) families is provided for amusement value, although we # try to ensure that it actually compiles. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options IPXPRINTFS=0 #IPX/SPX Console Debugging Information options IPX_ERRPRINTFS=0 #IPX/SPX Console Debugging Information # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NS #Xerox NS protocols #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE does # the obvious thing. # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # THis DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. The `isdn', `ii', `ity', `itel', and `ispy' devices # are all required when ISDN support is used. If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 64 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. # These are non-optional for ISDN pseudo-device isdn pseudo-device ii 4 pseudo-device ity 4 pseudo-device itel 2 pseudo-device ispy 1 # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # Currently there is no separate support for EISA. There should be. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # DUMMY_NOPS disables extra delays for some bus operations. The delays # are mostly for older systems and aren't used consistently. Probably # works OK on most EISA bus machines. # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # #options "AUTO_EOI_2" options BOUNCE_BUFFERS #options DUMMY_NOPS #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr # # Options for `sc': # # HARDFONTS allows the driver to load an ISO-8859-1 font to replace # the default font in your display adapter's memory. # options HARDFONTS # # MAXCONS is maximum number of virtual consoles, no more than 16 # default value: 12 # options MAXCONS=16 # # This device is mandatory. # # The Numeric Processing eXtension is used to either enable the # coprocessor or enable math emulation. If your machine doesn't contain # a math co-processor, you must *also* add the option "MATH_EMULATE". # THIS IS NOT AN OPTIONAL ENTRY, DO NOT REMOVE IT # device npx0 at isa? port "IO_NPX" irq 13 vector npxintr # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_NO_RESET #don't reset mouse hardware (some laptops) device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr # Options for sio: options COMCONSOLE #prefer serial console to video console options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # fea: DEC DEFEA EISA FDDI adapter # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device fe0 at isa? port 0x240 net irq ? vector feintr device fea0 at isa? net irq ? vector feaintr device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ISDN drivers - `isdn'. # # Uncomment one (and only one) of the following two drivers for the appropriate # ISDN device you have. For more information on what's considered appropriate # for your given set of circumstances, please read # /usr/src/gnu/usr.sbin/isdn/docs/INSTALL. It's a bit sparse at present, but # it's the best we have right now. The snic driver is also disabled at present, # waiting for someone to upgrade the driver to 2.0 (it's in /sys/gnu/scsi/). # device nic0 at isa? port "IO_COM3" iomem 0xe0000 tty irq 9 vector nicintr device nnic0 at isa? port 0x150 iomem 0xe0000 tty irq 12 vector nnicintr # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 7 conflicts drq 1 vector sbintr device sbxvi0 at isa? drq 5 device sbmidi0 at isa? port 0x330 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # controller eisa0 controller ahb0 controller ahc0 # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The PROBE_VERBOSE option enables a long listing of chip set registers # for supported PCI chip sets (currently only intel Saturn and Mercury). # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # controller pci0 controller ahc1 device ncr0 device de0 device fxp0 device vx0 device fpa0 device meteor0 options PROBE_VERBOSE # # PCCARD/PCMCIA # controller crd0 controller pcic0 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # options PSM_NO_RESET for the `psm' driver # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing # More undocumented options for linting. options APM_SLOWSTART=1 -options COMPAT_LINUX options DEBUG options "EXT2FS" options "IBCS2" options LINUX options "SCSI_2_DEF" options SHOW_BUSYBUFS # List buffers that prevent root unmount diff --git a/sys/conf/files b/sys/conf/files index 76552c0f479a..4f383abc1eb9 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,384 +1,385 @@ ddb/db_access.c optional ddb ddb/db_aout.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_trap.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb dev/vn/vn.c optional vn gnu/isdn/iitel.c optional itel device-driver gnu/isdn/iitty.c optional ity device-driver gnu/isdn/if_ii.c optional ii device-driver gnu/isdn/isdn.c optional isdn device-driver gnu/isdn/iispy.c optional ispy device-driver isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 kdb/kdb_access.c optional kadb kdb/kdb_command.c optional kadb kdb/kdb_ctype.c optional kadb kdb/kdb_expr.c optional kadb kdb/kdb_format.c optional kadb kdb/kdb_input.c optional kadb kdb/kdb_message.c optional kadb kdb/kdb_output.c optional kadb kdb/kdb_pcs.c optional kadb kdb/kdb_print.c optional kadb kdb/kdb_runpcs.c optional kadb kdb/kdb_sym.c optional kadb kdb/kdb_trap.c optional kadb kern/imgact_aout.c standard kern/imgact_gzip.c optional gzip kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard +kern/init_sysvec.c standard kern/kern_acct.c standard kern/kern_clock.c standard kern/kern_conf.c standard kern/kern_descrip.c standard kern/kern_devconf.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_ktrace.c standard kern/kern_lkm.c standard kern/kern_lockf.c standard kern/kern_malloc.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_synch.c standard kern/kern_sysctl.c standard kern/kern_time.c standard kern/kern_xxx.c standard kern/subr_diskslice.c standard kern/subr_dkbad.c standard kern/subr_log.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rlist.c standard kern/subr_xxx.c standard kern/sys_generic.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/sys_pipe.c standard kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_pty.c optional pty kern/tty_snoop.c optional snp kern/tty_subr.c standard kern/tty_tb.c optional tb kern/tty_tty.c standard kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_proto.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_conf.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard miscfs/deadfs/dead_vnops.c standard miscfs/fdesc/fdesc_vfsops.c optional fdesc miscfs/fdesc/fdesc_vnops.c optional fdesc miscfs/fifofs/fifo_vnops.c standard miscfs/kernfs/kernfs_vfsops.c optional kernfs miscfs/kernfs/kernfs_vnops.c optional kernfs miscfs/nullfs/null_subr.c optional nullfs miscfs/nullfs/null_vfsops.c optional nullfs miscfs/nullfs/null_vnops.c optional nullfs miscfs/portal/portal_vfsops.c optional portal miscfs/portal/portal_vnops.c optional portal miscfs/procfs/procfs_ctl.c optional procfs miscfs/procfs/procfs_fpregs.c standard miscfs/procfs/procfs_mem.c standard miscfs/procfs/procfs_note.c optional procfs miscfs/procfs/procfs_regs.c standard miscfs/procfs/procfs_status.c optional procfs miscfs/procfs/procfs_subr.c optional procfs miscfs/procfs/procfs_vfsops.c optional procfs miscfs/procfs/procfs_vnops.c optional procfs miscfs/specfs/spec_vnops.c standard miscfs/umapfs/umap_subr.c optional umapfs miscfs/umapfs/umap_vfsops.c optional umapfs miscfs/umapfs/umap_vnops.c optional umapfs miscfs/union/union_subr.c optional union miscfs/union/union_vfsops.c optional union miscfs/union/union_vnops.c optional union miscfs/devfs/devfs_vnops.c optional devfs miscfs/devfs/devfs_vfsops.c optional devfs miscfs/devfs/devfs_tree.c optional devfs msdosfs/msdosfs_conv.c optional msdosfs msdosfs/msdosfs_denode.c optional msdosfs msdosfs/msdosfs_fat.c optional msdosfs msdosfs/msdosfs_lookup.c optional msdosfs msdosfs/msdosfs_vfsops.c optional msdosfs msdosfs/msdosfs_vnops.c optional msdosfs net/bpf.c optional bpfilter net/bpf_filter.c optional bpfilter net/bsd_comp.c optional ppp net/if.c standard net/if_disc.c optional disc net/if_ethersubr.c optional ether net/if_fddisubr.c optional fddi net/if_loop.c optional loop net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/ppp_tty.c optional ppp net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional ppp net/slcompress.c optional sl net/if_tun.c optional tun #netccitt/ccitt_proto.c optional ccitt #netccitt/hd_debug.c optional hdlc #netccitt/hd_input.c optional hdlc #netccitt/hd_output.c optional hdlc #netccitt/hd_subr.c optional hdlc #netccitt/hd_timer.c optional hdlc #netccitt/if_x25subr.c optional ccitt #netccitt/llc_input.c optional llc #netccitt/llc_output.c optional llc #netccitt/llc_subr.c optional llc #netccitt/llc_timer.c optional llc #netccitt/pk_acct.c optional ccitt #netccitt/pk_debug.c optional ccitt #netccitt/pk_input.c optional ccitt #netccitt/pk_llcsubr.c optional hdlc #netccitt/pk_llcsubr.c optional llc #netccitt/pk_output.c optional ccitt #netccitt/pk_subr.c optional ccitt #netccitt/pk_timer.c optional ccitt #netccitt/pk_usrreq.c optional ccitt #netimp/if_imp.c optional imp #netimp/if_imphost.c optional imp #netimp/raw_imp.c optional imp netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/ip_fw.c optional ipfirewall netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netipx/ipx_usrreq.c optional ipx netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_error.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_tun.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx #netiso/clnp_debug.c optional iso #netiso/clnp_er.c optional iso #netiso/clnp_frag.c optional iso #netiso/clnp_input.c optional iso #netiso/clnp_options.c optional iso #netiso/clnp_output.c optional iso #netiso/clnp_raw.c optional iso #netiso/clnp_subr.c optional iso #netiso/clnp_timer.c optional iso #netiso/cltp_usrreq.c optional iso #netiso/esis.c optional iso #netiso/idrp_usrreq.c optional iso #netiso/if_eon.c optional eon #netiso/iso.c optional iso #netiso/iso_chksum.c optional iso #netiso/iso_pcb.c optional iso #netiso/iso_proto.c optional iso #netiso/iso_snpac.c optional iso #netiso/tp_astring.c optional iso #netiso/tp_astring.c optional tpip #netiso/tp_cons.c optional iso #netiso/tp_driver.c optional iso #netiso/tp_driver.c optional tpip #netiso/tp_emit.c optional iso #netiso/tp_emit.c optional tpip #netiso/tp_inet.c optional iso #netiso/tp_inet.c optional tpip #netiso/tp_input.c optional iso #netiso/tp_input.c optional tpip #netiso/tp_iso.c optional iso #netiso/tp_meas.c optional iso #netiso/tp_meas.c optional tpip #netiso/tp_output.c optional iso #netiso/tp_output.c optional tpip #netiso/tp_pcb.c optional iso #netiso/tp_pcb.c optional tpip #netiso/tp_subr.c optional iso #netiso/tp_subr.c optional tpip #netiso/tp_subr2.c optional iso #netiso/tp_subr2.c optional tpip #netiso/tp_timer.c optional iso #netiso/tp_timer.c optional tpip #netiso/tp_trace.c optional iso #netiso/tp_trace.c optional tpip #netiso/tp_usrreq.c optional iso #netiso/tp_usrreq.c optional tpip #netiso/tuba_subr.c optional iso tuba #netiso/tuba_table.c optional iso tuba #netiso/tuba_usrreq.c optional iso tuba #netns/idp_usrreq.c optional ns #netns/ns.c optional ns #netns/ns_error.c optional ns #netns/ns_input.c optional ns #netns/ns_ip.c optional ns #netns/ns_output.c optional ns #netns/ns_pcb.c optional ns #netns/ns_proto.c optional ns #netns/spp_debug.c optional ns #netns/spp_usrreq.c optional ns nfs/nfs_bio.c optional nfs nfs/nfs_node.c optional nfs nfs/nfs_nqlease.c optional nfs nfs/nfs_serv.c optional nfs nfs/nfs_socket.c optional nfs nfs/nfs_srvcache.c optional nfs nfs/nfs_subs.c optional nfs nfs/nfs_syscalls.c optional nfs nfs/nfs_vfsops.c optional nfs nfs/nfs_vnops.c optional nfs pccard/pccard.c optional crd pccard/pcic.c optional pcic device-driver pci/aic7870.c optional ahc device-driver pci/bt9xx.c optional bt device-driver pci/if_de.c optional de device-driver pci/if_fxp.c optional fxp device-driver pci/if_vx.c optional vx device-driver pci/ncr.c optional ncr device-driver pci/pci.c optional pci device-driver pci/pcisupport.c optional pci pci/if_pdq.c optional fea device-driver pci/pdq.c optional fea device-driver pci/if_pdq.c optional fpa device-driver pci/pdq.c optional fpa device-driver pci/meteor.c optional meteor device-driver scsi/cd.c optional cd scsi/ch.c optional ch scsi/od.c optional od scsi/scsi_base.c optional scbus scsi/scsi_sense.c optional scbus scsi/scsi_ioctl.c optional scbus scsi/scsiconf.c optional scbus scsi/scsi_driver.c optional scbus scsi/uk.c optional scbus scsi/pt.c optional pt scsi/sd.c optional sd scsi/st.c optional st scsi/worm.c optional worm scsi/su.c optional su scsi/ssc.c optional ssc scsi/sctarg.c optional sctarg ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_alloc.c optional mfs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_balloc.c optional mfs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_inode.c optional mfs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_subr.c optional mfs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_tables.c optional mfs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vfsops.c optional mfs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_vnops.c optional mfs ufs/lfs/lfs_alloc.c optional lfs ufs/lfs/lfs_balloc.c optional lfs ufs/lfs/lfs_bio.c optional lfs ufs/lfs/lfs_cksum.c optional lfs ufs/lfs/lfs_debug.c optional lfs ufs/lfs/lfs_inode.c optional lfs ufs/lfs/lfs_segment.c optional lfs ufs/lfs/lfs_subr.c optional lfs ufs/lfs/lfs_syscalls.c optional lfs ufs/lfs/lfs_vfsops.c optional lfs ufs/lfs/lfs_vnops.c optional lfs ufs/mfs/mfs_vfsops.c optional mfs ufs/mfs/mfs_vnops.c optional mfs gnu/ext2fs/ext2_balloc.c optional ext2fs gnu/ext2fs/ext2_inode.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs gnu/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/ext2fs/ext2_alloc.c optional ext2fs ufs/ufs/ufs_bmap.c standard ufs/ufs/ufs_disksubr.c standard ufs/ufs/ufs_ihash.c standard ufs/ufs/ufs_inode.c standard ufs/ufs/ufs_lookup.c standard ufs/ufs/ufs_quota.c standard ufs/ufs/ufs_vfsops.c standard ufs/ufs/ufs_vnops.c standard vm/default_pager.c standard vm/device_pager.c standard vm/kern_lock.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_swap.c standard vm/vm_unix.c standard vm/vnode_pager.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index bef328a46106..5c0bef2d4e5c 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,253 +1,266 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.128 1996/02/26 00:58:38 gibbs Exp $ +# $Id: files.i386,v 1.129 1996/03/02 03:48:11 pst Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \ compile-with "${CC} -Wall -o $@ $>" \ no-obj no-implicit-rule \ clean "aic7xxx_asm" +# aic7xxx_seq.h optional ahc device-driver \ compile-with "./aic7xxx_asm -o $@ $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic7xxx_seq.h" \ dependency "$S/dev/aic7xxx/aic7xxx_reg.h $S/dev/aic7xxx/aic7xxx.seq aic7xxx_asm" +# +linux_genassym optional linux \ + dependency "$S/i386/linux/linux_genassym.c $S/i386/linux/linux.h" \ + compile-with "${CC} ${CFLAGS} -o $@ $<" \ + no-obj no-implicit-rule \ + clean "linux_genassym" +# +linux_assym.h optional linux \ + dependency "linux_genassym" \ + compile-with "./linux_genassym > $@" \ + no-obj no-implicit-rule before-depend \ + clean "linux_assym.h" +# i386/scsi/93cx6.c optional ahc device-driver i386/apm/apm.c optional apm device-driver i386/apm/apm_setup.s optional apm i386/eisa/3c5x9.c optional ep device-driver i386/eisa/aic7770.c optional ahc device-driver i386/eisa/aha1742.c optional ahb device-driver i386/eisa/bt74x.c optional bt device-driver i386/eisa/eisaconf.c optional eisa i386/i386/autoconf.c standard device-driver i386/i386/cons.c standard i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb i386/i386/exception.s standard i386/i386/in_cksum.c optional inet # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard i386/i386/machdep.c standard i386/i386/math_emulate.c optional math_emulate i386/i386/mem.c standard i386/i386/microtime.s standard i386/i386/ns_cksum.c optional ns i386/i386/pmap.c standard -# used by ptrace now i386/i386/procfs_machdep.c standard i386/i386/support.s standard i386/i386/swtch.s standard i386/i386/sys_machdep.c standard i386/i386/trap.c standard i386/i386/userconfig.c standard i386/i386/vm_machdep.c standard i386/ibcs2/ibcs2_fcntl.c optional ibcs2 i386/ibcs2/ibcs2_stat.c optional ibcs2 i386/ibcs2/ibcs2_ipc.c optional ibcs2 i386/ibcs2/ibcs2_msg.c optional ibcs2 i386/ibcs2/ibcs2_misc.c optional ibcs2 i386/ibcs2/ibcs2_other.c optional ibcs2 i386/ibcs2/ibcs2_signal.c optional ibcs2 i386/ibcs2/ibcs2_ioctl.c optional ibcs2 i386/ibcs2/ibcs2_socksys.c optional ibcs2 i386/ibcs2/ibcs2_sysi86.c optional ibcs2 i386/ibcs2/ibcs2_util.c optional ibcs2 i386/ibcs2/ibcs2_isc.c optional ibcs2 i386/ibcs2/ibcs2_isc_sysent.c optional ibcs2 i386/ibcs2/ibcs2_xenix.c optional ibcs2 i386/ibcs2/ibcs2_xenix_sysent.c optional ibcs2 i386/ibcs2/ibcs2_errno.c optional ibcs2 i386/ibcs2/ibcs2_sysent.c optional ibcs2 i386/ibcs2/ibcs2_sysvec.c optional ibcs2 i386/ibcs2/imgact_coff.c optional ibcs2 -#i386/ibcs2/imgact_elf.c optional svr4 -#i386/ibcs2/imgact_xout.c optional ibcs2 i386/isa/aha1542.c optional aha device-driver i386/isa/aic6360.c optional aic device-driver i386/isa/ata.c optional ata device-driver i386/isa/b004.c optional bqu device-driver i386/isa/bt5xx-445.c optional bt device-driver i386/isa/clock.c standard i386/isa/cronyx.c optional cx device-driver i386/isa/ctx.c optional ctx device-driver i386/isa/cx.c optional cx device-driver i386/isa/cy.c optional cy device-driver i386/isa/diskslice_machdep.c standard i386/isa/elink.c optional ep device-driver i386/isa/elink.c optional ie device-driver i386/isa/fd.c optional fd device-driver i386/isa/ft.c optional ft device-driver i386/isa/gpib.c optional gp device-driver i386/isa/asc.c optional asc device-driver i386/isa/gsc.c optional gsc device-driver i386/isa/if_ar.c optional ar device-driver i386/isa/if_cx.c optional cx device-driver i386/isa/if_ed.c optional ed device-driver i386/isa/if_eg.c optional eg device-driver i386/isa/if_el.c optional el device-driver i386/isa/if_ep.c optional ep device-driver i386/isa/if_fe.c optional fe device-driver i386/isa/if_ie.c optional ie device-driver i386/isa/if_is.c optional is device-driver i386/isa/if_ix.c optional ix device-driver i386/isa/if_le.c optional le device-driver i386/isa/if_lnc.c optional lnc device-driver i386/isa/if_ze.c optional ze device-driver i386/isa/if_zp.c optional zp device-driver i386/isa/isa.c optional isa device-driver i386/isa/joy.c optional joy device-driver i386/isa/lpt.c optional lpt device-driver i386/isa/labpc.c optional labpc device-driver i386/isa/mcd.c optional mcd device-driver i386/isa/mse.c optional mse device-driver i386/isa/ncr5380.c optional nca device-driver i386/isa/npx.c optional npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver i386/isa/pcvt/pcvt_drv.c optional vt device-driver i386/isa/pcvt/pcvt_ext.c optional vt device-driver i386/isa/pcvt/pcvt_kbd.c optional vt device-driver i386/isa/pcvt/pcvt_out.c optional vt device-driver i386/isa/pcvt/pcvt_sup.c optional vt device-driver i386/isa/pcvt/pcvt_vtf.c optional vt device-driver i386/isa/prof_machdep.c optional profiling-routine i386/isa/psm.c optional psm device-driver i386/isa/qcam.c optional qcam device-driver i386/isa/qcamio.c optional qcam device-driver i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver i386/isa/scd.c optional scd device-driver i386/isa/seagate.c optional sea device-driver i386/isa/si.c optional si device-driver i386/isa/si_code.c optional si device-driver i386/isa/sio.c optional sio device-driver i386/isa/sound/dev_table.c optional snd device-driver i386/isa/sound/soundcard.c optional snd device-driver i386/isa/sound/sound_switch.c optional snd device-driver i386/isa/sound/audio.c optional snd device-driver i386/isa/sound/dmabuf.c optional snd device-driver i386/isa/sound/sys_timer.c optional snd device-driver i386/isa/sound/sequencer.c optional snd device-driver i386/isa/sound/patmgr.c optional snd device-driver i386/isa/sound/adlib_card.c optional opl device-driver i386/isa/sound/opl3.c optional opl device-driver i386/isa/sound/gus_card.c optional gus device-driver i386/isa/sound/gus_midi.c optional gus device-driver i386/isa/sound/gus_vol.c optional gus device-driver i386/isa/sound/gus_wave.c optional gus device-driver i386/isa/sound/ics2101.c optional gus device-driver i386/isa/sound/sound_timer.c optional gus device-driver i386/isa/sound/midi_synth.c optional gus device-driver i386/isa/sound/midibuf.c optional gus device-driver i386/isa/sound/ad1848.c optional gusxvi device-driver i386/isa/sound/ad1848.c optional gus device-driver i386/isa/sound/ad1848.c optional mss device-driver i386/isa/sound/midi_synth.c optional mss device-driver i386/isa/sound/midibuf.c optional mss device-driver i386/isa/sound/mpu401.c optional mpu device-driver i386/isa/sound/midi_synth.c optional mpu device-driver i386/isa/sound/midibuf.c optional mpu device-driver i386/isa/sound/pas2_card.c optional pas device-driver i386/isa/sound/pas2_midi.c optional pas device-driver i386/isa/sound/pas2_mixer.c optional pas device-driver i386/isa/sound/pas2_pcm.c optional pas device-driver i386/isa/sound/midi_synth.c optional pas device-driver i386/isa/sound/midibuf.c optional pas device-driver i386/isa/sound/sb_card.c optional sb device-driver i386/isa/sound/sb_dsp.c optional sb device-driver i386/isa/sound/sb_midi.c optional sb device-driver i386/isa/sound/sb_mixer.c optional sb device-driver i386/isa/sound/midi_synth.c optional sb device-driver i386/isa/sound/midibuf.c optional sb device-driver i386/isa/sound/sb16_dsp.c optional sbxvi device-driver i386/isa/sound/sb16_midi.c optional sbmidi device-driver i386/isa/sound/uart6850.c optional uart device-driver i386/isa/sound/midi_synth.c optional uart device-driver i386/isa/sound/midibuf.c optional uart device-driver i386/isa/sound/trix.c optional trix device-driver i386/isa/sound/sscape.c optional sscape device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/syscons.c optional sc device-driver i386/isa/tw.c optional tw device-driver i386/isa/ultra14f.c optional uha device-driver i386/isa/wd.c optional wdc device-driver i386/isa/wd.c optional wd device-driver i386/isa/atapi.c optional atapi device-driver i386/isa/wcd.c optional wcd device-driver i386/isa/wd7000.c optional wds device-driver i386/isa/wt.c optional wt device-driver i386/linux/imgact_linux.c optional linux i386/linux/linux_dummy.c optional linux i386/linux/linux_file.c optional linux -i386/linux/linux_generic.c optional linux i386/linux/linux_ioctl.c optional linux i386/linux/linux_ipc.c optional linux +i386/linux/linux_locore.s optional linux i386/linux/linux_misc.c optional linux i386/linux/linux_signal.c optional linux i386/linux/linux_socket.c optional linux i386/linux/linux_stats.c optional linux i386/linux/linux_sysent.c optional linux +i386/linux/linux_sysvec.c optional linux +i386/linux/linux_util.c optional linux i386/scsi/aic7xxx.c optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_reg.h aic7xxx_seq.h" i386/scsi/bt.c optional bt device-driver libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/moddi3.c standard libkern/qdivrem.c standard libkern/qsort.c standard libkern/random.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/udivdi3.c standard libkern/umoddi3.c standard gnu/i386/fpemul/div_small.s optional gpl_math_emulate gnu/i386/fpemul/errors.c optional gpl_math_emulate gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate gnu/i386/fpemul/get_address.c optional gpl_math_emulate gnu/i386/fpemul/load_store.c optional gpl_math_emulate gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate gnu/i386/fpemul/poly_div.s optional gpl_math_emulate gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate gnu/i386/fpemul/polynomial.s optional gpl_math_emulate gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate gnu/i386/fpemul/reg_div.s optional gpl_math_emulate gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate gnu/i386/fpemul/reg_round.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate gnu/i386/isa/dgb.c optional dgb device-driver gnu/i386/isa/nic3008.c optional nic device-driver gnu/i386/isa/nic3009.c optional nnic device-driver pci/wd82371.c optional wd device-driver diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index b48ef2c90b1e..f30187dd58dd 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,10 +1,12 @@ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h GPL_MATH_EMULATE opt_math_emulate.h MAXCONS opt_syscons.h IBCS2 opt_ibcs2.h SHOW_BUSYBUFS opt_machdep.h PANIC_REBOOT_WAIT_TIME opt_machdep.h LARGEMEM opt_machdep.h MAXMEM opt_machdep.h +LINUX opt_linux.h +COMPAT_LINUX opt_linux.h diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index ce1bae2667ec..c2e6a38fb084 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -1,855 +1,854 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.240 1996/02/23 15:47:41 phk Exp $ +# $Id: LINT,v 1.241 1996/02/28 21:39:54 gpalmer Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family. You must also specify # at least one CPU (the one you intend to run on); deleting the # specification for CPUs you don't need to use may make parts of the # system run faster # machine "i386" cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Under some circumstances it is necessary to make the default max # number of processes per user and open files per user more than the # defaults on bootup. (an example is a large news server in which # the uid, news, can sometimes need > 100 simultaneous processes running, # or perhaps a user using lots of windows under X). options CHILD_MAX=128 options OPEN_MAX=128 # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # Allow ordinary users to take the console - this is useful for X. options UCONSOLE ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service), ISO (OSI), and # CCITT (X.25) families is provided for amusement value, although we # try to ensure that it actually compiles. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options IPXPRINTFS=0 #IPX/SPX Console Debugging Information options IPX_ERRPRINTFS=0 #IPX/SPX Console Debugging Information # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NS #Xerox NS protocols #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE does # the obvious thing. # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # THis DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. The `isdn', `ii', `ity', `itel', and `ispy' devices # are all required when ISDN support is used. If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 64 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. # These are non-optional for ISDN pseudo-device isdn pseudo-device ii 4 pseudo-device ity 4 pseudo-device itel 2 pseudo-device ispy 1 # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # Currently there is no separate support for EISA. There should be. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # DUMMY_NOPS disables extra delays for some bus operations. The delays # are mostly for older systems and aren't used consistently. Probably # works OK on most EISA bus machines. # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # #options "AUTO_EOI_2" options BOUNCE_BUFFERS #options DUMMY_NOPS #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr # # Options for `sc': # # HARDFONTS allows the driver to load an ISO-8859-1 font to replace # the default font in your display adapter's memory. # options HARDFONTS # # MAXCONS is maximum number of virtual consoles, no more than 16 # default value: 12 # options MAXCONS=16 # # This device is mandatory. # # The Numeric Processing eXtension is used to either enable the # coprocessor or enable math emulation. If your machine doesn't contain # a math co-processor, you must *also* add the option "MATH_EMULATE". # THIS IS NOT AN OPTIONAL ENTRY, DO NOT REMOVE IT # device npx0 at isa? port "IO_NPX" irq 13 vector npxintr # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_NO_RESET #don't reset mouse hardware (some laptops) device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr # Options for sio: options COMCONSOLE #prefer serial console to video console options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # fea: DEC DEFEA EISA FDDI adapter # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device fe0 at isa? port 0x240 net irq ? vector feintr device fea0 at isa? net irq ? vector feaintr device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ISDN drivers - `isdn'. # # Uncomment one (and only one) of the following two drivers for the appropriate # ISDN device you have. For more information on what's considered appropriate # for your given set of circumstances, please read # /usr/src/gnu/usr.sbin/isdn/docs/INSTALL. It's a bit sparse at present, but # it's the best we have right now. The snic driver is also disabled at present, # waiting for someone to upgrade the driver to 2.0 (it's in /sys/gnu/scsi/). # device nic0 at isa? port "IO_COM3" iomem 0xe0000 tty irq 9 vector nicintr device nnic0 at isa? port 0x150 iomem 0xe0000 tty irq 12 vector nnicintr # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 7 conflicts drq 1 vector sbintr device sbxvi0 at isa? drq 5 device sbmidi0 at isa? port 0x330 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # controller eisa0 controller ahb0 controller ahc0 # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The PROBE_VERBOSE option enables a long listing of chip set registers # for supported PCI chip sets (currently only intel Saturn and Mercury). # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # controller pci0 controller ahc1 device ncr0 device de0 device fxp0 device vx0 device fpa0 device meteor0 options PROBE_VERBOSE # # PCCARD/PCMCIA # controller crd0 controller pcic0 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # options PSM_NO_RESET for the `psm' driver # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing # More undocumented options for linting. options APM_SLOWSTART=1 -options COMPAT_LINUX options DEBUG options "EXT2FS" options "IBCS2" options LINUX options "SCSI_2_DEF" options SHOW_BUSYBUFS # List buffers that prevent root unmount diff --git a/sys/i386/conf/Makefile.i386 b/sys/i386/conf/Makefile.i386 index f88dd84a6bda..3ba84a5d1008 100644 --- a/sys/i386/conf/Makefile.i386 +++ b/sys/i386/conf/Makefile.i386 @@ -1,186 +1,187 @@ # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.74 1996/01/07 22:31:27 phk Exp $ +# $Id: Makefile.i386,v 1.75 1996/01/08 03:55:36 peter Exp $ # # Makefile for FreeBSD # # This makefile is constructed from a machine description: # config machineid # Most changes should be made in the machine description # /sys/i386/conf/``machineid'' # after which you should do # config machineid # Generic makefile changes should be made in # /sys/i386/conf/Makefile.i386 # after which config should be rerun for all machines. # CC?= cc CPP?= cpp LD?= /usr/bin/ld .if exists(./@/.) S= ./@ .else S= ../.. .endif I386= ${S}/i386 CWARNFLAGS?= -W -Wreturn-type -Wcomment -Wredundant-decls -Wimplicit \ -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes \ -Winline # # The following flags are next up for working on: # -Wall # # When working on removing warnings from code, the `-Werror' flag should be # of material assistance. # COPTFLAGS?=-O # Not ready for -I- yet. #include "foo.h" where foo.h is in the srcdir fails. INCLUDES= -nostdinc -I. -I$S -I$S/sys # This hack is to allow kernel compiles to succeed on machines w/out srcdist .if exists($S/../include) INCLUDES+= -I$S/../include .else INCLUDES+= -I/usr/include .endif COPTS= ${INCLUDES} ${IDENT} -DKERNEL ASFLAGS= CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS} LOAD_ADDRESS?= F0100000 NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $< NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< # XXX errors leak out of all the pipes. Should use cc *.S. # XXX LOCORE means "don't declare C stuff" not "for locore.s". NORMAL_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $< DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $< DRIVER_S= ${CPP} -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o PROFILE_C= ${CC} -c ${CFLAGS} ${PARAM} $< SYSTEM_CFILES= ioconf.c param.c vnode_if.c SYSTEM_SFILES= ${I386}/i386/locore.s SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} ioconf.o param.o SYSTEM_DEP= Makefile symbols.exclude symbols.sort ${SYSTEM_OBJS} SYSTEM_LD_HEAD= @echo loading $@; rm -f $@ SYSTEM_LD= @${LD} -Bstatic -Z -T ${LOAD_ADDRESS} -o $@ -X ${SYSTEM_OBJS} vers.o .if ${CFLAGS:M-g} == "" SYMORDER_EXCLUDE=-x symbols.exclude .endif SYSTEM_LD_TAIL= @echo rearranging symbols; \ symorder -m ${SYMORDER_EXCLUDE} symbols.sort $@; \ size $@; chmod 755 $@ %BEFORE_DEPEND %OBJS %CFILES %SFILES %LOAD %CLEAN clean: rm -f *.o *.s eddep errs genassym kernel linterrs \ makelinks param.c symbols.exclude symbols.sort tags \ vers.c vnode_if.c vnode_if.h ${CLEAN} #lint: /tmp param.c # @lint -hbxn -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \ # ${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \ # grep -v 'struct/union .* never defined' | \ # grep -v 'possible pointer alignment problem' symbols.exclude: Makefile echo "gcc2_compiled." >symbols.exclude echo "___gnu_compiled_c" >>symbols.exclude symbols.sort: ${I386}/i386/symbols.raw grep -v '^#' ${I386}/i386/symbols.raw \ | sed 's/^ //' | sort -u > symbols.sort locore.o: ${I386}/i386/locore.s assym.s ${NORMAL_S} # everything potentially depends on the Makefile since everything potentially # depends on the options. Some things are more dependent on the Makefile for # historical reasons. machdep.o: Makefile # the following is necessary because autoconf.o depends on #if GENERIC autoconf.o: Makefile # XXX - may no longer be needed locore.o: Makefile # depends on KDB (cons.o also depends on GENERIC) trap.o cons.o: Makefile # this rule stops ./assym.s in .depend from causing problems ./assym.s: assym.s assym.s: genassym ./genassym >assym.s # Some of the defines that genassym outputs may well depend on the # value of kernel options. genassym.o: ${I386}/i386/genassym.c Makefile ${CC} -c ${CFLAGS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c genassym: genassym.o ${CC} -static ${CFLAGS} ${PARAM} genassym.o -o $@ # XXX this assumes that the options for NORMAL_C* and DRIVER_C* are identical. depend: assym.s param.c vnode_if.h ${BEFORE_DEPEND} - mkdep ${COPTS} ${CFILES} ${SYSTEM_CFILES} + rm -f .depend + mkdep -a ${COPTS} ${CFILES} ${SYSTEM_CFILES} mkdep -a ${COPTS} ${PARAM} -UKERNEL ${I386}/i386/genassym.c MKDEP_CPP=${CPP} ; export MKDEP_CPP ; \ mkdep -a -DLOCORE ${COPTS} ${SFILES} ${SYSTEM_SFILES} links: egrep '#if' ${CFILES:Nswapkernel.c} | sed -f $S/conf/defines | \ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink echo ${CFILES:Nswapkernel.c} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \ sort -u | comm -23 - dontlink | \ sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks sh makelinks && rm -f dontlink tags: @echo "see $S/kern/Makefile for tags" install: chflags noschg /kernel mv /kernel /kernel.old if [ `sysctl -n kern.bootfile` = "/kernel" ] ; then \ sysctl -w kern.bootfile=/kernel.old ; \ mv -f /var/db/kvm_kernel.db /var/db/kvm_kernel.old.db ; \ fi install -c -m 555 -o root -g wheel -fschg kernel / ioconf.o: ioconf.c $S/sys/param.h machine/pte.h $S/sys/buf.h \ ${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h ${CC} -c ${CFLAGS} ioconf.c param.c: $S/conf/param.c -rm -f param.c cp $S/conf/param.c . param.o: param.c Makefile ${CC} -c ${CFLAGS} ${PARAM} param.c vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP} sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT} ${CC} ${CFLAGS} -c vers.c vnode_if.c: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src vnode_if.h: $S/kern/vnode_if.sh $S/kern/vnode_if.src sh $S/kern/vnode_if.sh $S/kern/vnode_if.src %RULES # DO NOT DELETE THIS LINE -- make depend uses it diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index ce1bae2667ec..c2e6a38fb084 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -1,855 +1,854 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.240 1996/02/23 15:47:41 phk Exp $ +# $Id: LINT,v 1.241 1996/02/28 21:39:54 gpalmer Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family. You must also specify # at least one CPU (the one you intend to run on); deleting the # specification for CPUs you don't need to use may make parts of the # system run faster # machine "i386" cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Under some circumstances it is necessary to make the default max # number of processes per user and open files per user more than the # defaults on bootup. (an example is a large news server in which # the uid, news, can sometimes need > 100 simultaneous processes running, # or perhaps a user using lots of windows under X). options CHILD_MAX=128 options OPEN_MAX=128 # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # Allow ordinary users to take the console - this is useful for X. options UCONSOLE ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service), ISO (OSI), and # CCITT (X.25) families is provided for amusement value, although we # try to ensure that it actually compiles. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options IPXPRINTFS=0 #IPX/SPX Console Debugging Information options IPX_ERRPRINTFS=0 #IPX/SPX Console Debugging Information # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NS #Xerox NS protocols #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE does # the obvious thing. # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # THis DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. The `isdn', `ii', `ity', `itel', and `ispy' devices # are all required when ISDN support is used. If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 64 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. # These are non-optional for ISDN pseudo-device isdn pseudo-device ii 4 pseudo-device ity 4 pseudo-device itel 2 pseudo-device ispy 1 # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # Currently there is no separate support for EISA. There should be. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # DUMMY_NOPS disables extra delays for some bus operations. The delays # are mostly for older systems and aren't used consistently. Probably # works OK on most EISA bus machines. # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # #options "AUTO_EOI_2" options BOUNCE_BUFFERS #options DUMMY_NOPS #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr # # Options for `sc': # # HARDFONTS allows the driver to load an ISO-8859-1 font to replace # the default font in your display adapter's memory. # options HARDFONTS # # MAXCONS is maximum number of virtual consoles, no more than 16 # default value: 12 # options MAXCONS=16 # # This device is mandatory. # # The Numeric Processing eXtension is used to either enable the # coprocessor or enable math emulation. If your machine doesn't contain # a math co-processor, you must *also* add the option "MATH_EMULATE". # THIS IS NOT AN OPTIONAL ENTRY, DO NOT REMOVE IT # device npx0 at isa? port "IO_NPX" irq 13 vector npxintr # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_NO_RESET #don't reset mouse hardware (some laptops) device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr # Options for sio: options COMCONSOLE #prefer serial console to video console options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # fea: DEC DEFEA EISA FDDI adapter # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device fe0 at isa? port 0x240 net irq ? vector feintr device fea0 at isa? net irq ? vector feaintr device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ISDN drivers - `isdn'. # # Uncomment one (and only one) of the following two drivers for the appropriate # ISDN device you have. For more information on what's considered appropriate # for your given set of circumstances, please read # /usr/src/gnu/usr.sbin/isdn/docs/INSTALL. It's a bit sparse at present, but # it's the best we have right now. The snic driver is also disabled at present, # waiting for someone to upgrade the driver to 2.0 (it's in /sys/gnu/scsi/). # device nic0 at isa? port "IO_COM3" iomem 0xe0000 tty irq 9 vector nicintr device nnic0 at isa? port 0x150 iomem 0xe0000 tty irq 12 vector nnicintr # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 7 conflicts drq 1 vector sbintr device sbxvi0 at isa? drq 5 device sbmidi0 at isa? port 0x330 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # controller eisa0 controller ahb0 controller ahc0 # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The PROBE_VERBOSE option enables a long listing of chip set registers # for supported PCI chip sets (currently only intel Saturn and Mercury). # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # controller pci0 controller ahc1 device ncr0 device de0 device fxp0 device vx0 device fpa0 device meteor0 options PROBE_VERBOSE # # PCCARD/PCMCIA # controller crd0 controller pcic0 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # options PSM_NO_RESET for the `psm' driver # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing # More undocumented options for linting. options APM_SLOWSTART=1 -options COMPAT_LINUX options DEBUG options "EXT2FS" options "IBCS2" options LINUX options "SCSI_2_DEF" options SHOW_BUSYBUFS # List buffers that prevent root unmount diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index bef328a46106..5c0bef2d4e5c 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,253 +1,266 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.128 1996/02/26 00:58:38 gibbs Exp $ +# $Id: files.i386,v 1.129 1996/03/02 03:48:11 pst Exp $ # aic7xxx_asm optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \ compile-with "${CC} -Wall -o $@ $>" \ no-obj no-implicit-rule \ clean "aic7xxx_asm" +# aic7xxx_seq.h optional ahc device-driver \ compile-with "./aic7xxx_asm -o $@ $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend \ clean "aic7xxx_seq.h" \ dependency "$S/dev/aic7xxx/aic7xxx_reg.h $S/dev/aic7xxx/aic7xxx.seq aic7xxx_asm" +# +linux_genassym optional linux \ + dependency "$S/i386/linux/linux_genassym.c $S/i386/linux/linux.h" \ + compile-with "${CC} ${CFLAGS} -o $@ $<" \ + no-obj no-implicit-rule \ + clean "linux_genassym" +# +linux_assym.h optional linux \ + dependency "linux_genassym" \ + compile-with "./linux_genassym > $@" \ + no-obj no-implicit-rule before-depend \ + clean "linux_assym.h" +# i386/scsi/93cx6.c optional ahc device-driver i386/apm/apm.c optional apm device-driver i386/apm/apm_setup.s optional apm i386/eisa/3c5x9.c optional ep device-driver i386/eisa/aic7770.c optional ahc device-driver i386/eisa/aha1742.c optional ahb device-driver i386/eisa/bt74x.c optional bt device-driver i386/eisa/eisaconf.c optional eisa i386/i386/autoconf.c standard device-driver i386/i386/cons.c standard i386/i386/db_disasm.c optional ddb i386/i386/db_interface.c optional ddb i386/i386/db_trace.c optional ddb i386/i386/exception.s standard i386/i386/in_cksum.c optional inet # locore.s needs to be handled in Makefile to put it first. Otherwise it's # now normal. # i386/i386/locore.s standard i386/i386/machdep.c standard i386/i386/math_emulate.c optional math_emulate i386/i386/mem.c standard i386/i386/microtime.s standard i386/i386/ns_cksum.c optional ns i386/i386/pmap.c standard -# used by ptrace now i386/i386/procfs_machdep.c standard i386/i386/support.s standard i386/i386/swtch.s standard i386/i386/sys_machdep.c standard i386/i386/trap.c standard i386/i386/userconfig.c standard i386/i386/vm_machdep.c standard i386/ibcs2/ibcs2_fcntl.c optional ibcs2 i386/ibcs2/ibcs2_stat.c optional ibcs2 i386/ibcs2/ibcs2_ipc.c optional ibcs2 i386/ibcs2/ibcs2_msg.c optional ibcs2 i386/ibcs2/ibcs2_misc.c optional ibcs2 i386/ibcs2/ibcs2_other.c optional ibcs2 i386/ibcs2/ibcs2_signal.c optional ibcs2 i386/ibcs2/ibcs2_ioctl.c optional ibcs2 i386/ibcs2/ibcs2_socksys.c optional ibcs2 i386/ibcs2/ibcs2_sysi86.c optional ibcs2 i386/ibcs2/ibcs2_util.c optional ibcs2 i386/ibcs2/ibcs2_isc.c optional ibcs2 i386/ibcs2/ibcs2_isc_sysent.c optional ibcs2 i386/ibcs2/ibcs2_xenix.c optional ibcs2 i386/ibcs2/ibcs2_xenix_sysent.c optional ibcs2 i386/ibcs2/ibcs2_errno.c optional ibcs2 i386/ibcs2/ibcs2_sysent.c optional ibcs2 i386/ibcs2/ibcs2_sysvec.c optional ibcs2 i386/ibcs2/imgact_coff.c optional ibcs2 -#i386/ibcs2/imgact_elf.c optional svr4 -#i386/ibcs2/imgact_xout.c optional ibcs2 i386/isa/aha1542.c optional aha device-driver i386/isa/aic6360.c optional aic device-driver i386/isa/ata.c optional ata device-driver i386/isa/b004.c optional bqu device-driver i386/isa/bt5xx-445.c optional bt device-driver i386/isa/clock.c standard i386/isa/cronyx.c optional cx device-driver i386/isa/ctx.c optional ctx device-driver i386/isa/cx.c optional cx device-driver i386/isa/cy.c optional cy device-driver i386/isa/diskslice_machdep.c standard i386/isa/elink.c optional ep device-driver i386/isa/elink.c optional ie device-driver i386/isa/fd.c optional fd device-driver i386/isa/ft.c optional ft device-driver i386/isa/gpib.c optional gp device-driver i386/isa/asc.c optional asc device-driver i386/isa/gsc.c optional gsc device-driver i386/isa/if_ar.c optional ar device-driver i386/isa/if_cx.c optional cx device-driver i386/isa/if_ed.c optional ed device-driver i386/isa/if_eg.c optional eg device-driver i386/isa/if_el.c optional el device-driver i386/isa/if_ep.c optional ep device-driver i386/isa/if_fe.c optional fe device-driver i386/isa/if_ie.c optional ie device-driver i386/isa/if_is.c optional is device-driver i386/isa/if_ix.c optional ix device-driver i386/isa/if_le.c optional le device-driver i386/isa/if_lnc.c optional lnc device-driver i386/isa/if_ze.c optional ze device-driver i386/isa/if_zp.c optional zp device-driver i386/isa/isa.c optional isa device-driver i386/isa/joy.c optional joy device-driver i386/isa/lpt.c optional lpt device-driver i386/isa/labpc.c optional labpc device-driver i386/isa/mcd.c optional mcd device-driver i386/isa/mse.c optional mse device-driver i386/isa/ncr5380.c optional nca device-driver i386/isa/npx.c optional npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver i386/isa/pcvt/pcvt_drv.c optional vt device-driver i386/isa/pcvt/pcvt_ext.c optional vt device-driver i386/isa/pcvt/pcvt_kbd.c optional vt device-driver i386/isa/pcvt/pcvt_out.c optional vt device-driver i386/isa/pcvt/pcvt_sup.c optional vt device-driver i386/isa/pcvt/pcvt_vtf.c optional vt device-driver i386/isa/prof_machdep.c optional profiling-routine i386/isa/psm.c optional psm device-driver i386/isa/qcam.c optional qcam device-driver i386/isa/qcamio.c optional qcam device-driver i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver i386/isa/scd.c optional scd device-driver i386/isa/seagate.c optional sea device-driver i386/isa/si.c optional si device-driver i386/isa/si_code.c optional si device-driver i386/isa/sio.c optional sio device-driver i386/isa/sound/dev_table.c optional snd device-driver i386/isa/sound/soundcard.c optional snd device-driver i386/isa/sound/sound_switch.c optional snd device-driver i386/isa/sound/audio.c optional snd device-driver i386/isa/sound/dmabuf.c optional snd device-driver i386/isa/sound/sys_timer.c optional snd device-driver i386/isa/sound/sequencer.c optional snd device-driver i386/isa/sound/patmgr.c optional snd device-driver i386/isa/sound/adlib_card.c optional opl device-driver i386/isa/sound/opl3.c optional opl device-driver i386/isa/sound/gus_card.c optional gus device-driver i386/isa/sound/gus_midi.c optional gus device-driver i386/isa/sound/gus_vol.c optional gus device-driver i386/isa/sound/gus_wave.c optional gus device-driver i386/isa/sound/ics2101.c optional gus device-driver i386/isa/sound/sound_timer.c optional gus device-driver i386/isa/sound/midi_synth.c optional gus device-driver i386/isa/sound/midibuf.c optional gus device-driver i386/isa/sound/ad1848.c optional gusxvi device-driver i386/isa/sound/ad1848.c optional gus device-driver i386/isa/sound/ad1848.c optional mss device-driver i386/isa/sound/midi_synth.c optional mss device-driver i386/isa/sound/midibuf.c optional mss device-driver i386/isa/sound/mpu401.c optional mpu device-driver i386/isa/sound/midi_synth.c optional mpu device-driver i386/isa/sound/midibuf.c optional mpu device-driver i386/isa/sound/pas2_card.c optional pas device-driver i386/isa/sound/pas2_midi.c optional pas device-driver i386/isa/sound/pas2_mixer.c optional pas device-driver i386/isa/sound/pas2_pcm.c optional pas device-driver i386/isa/sound/midi_synth.c optional pas device-driver i386/isa/sound/midibuf.c optional pas device-driver i386/isa/sound/sb_card.c optional sb device-driver i386/isa/sound/sb_dsp.c optional sb device-driver i386/isa/sound/sb_midi.c optional sb device-driver i386/isa/sound/sb_mixer.c optional sb device-driver i386/isa/sound/midi_synth.c optional sb device-driver i386/isa/sound/midibuf.c optional sb device-driver i386/isa/sound/sb16_dsp.c optional sbxvi device-driver i386/isa/sound/sb16_midi.c optional sbmidi device-driver i386/isa/sound/uart6850.c optional uart device-driver i386/isa/sound/midi_synth.c optional uart device-driver i386/isa/sound/midibuf.c optional uart device-driver i386/isa/sound/trix.c optional trix device-driver i386/isa/sound/sscape.c optional sscape device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/syscons.c optional sc device-driver i386/isa/tw.c optional tw device-driver i386/isa/ultra14f.c optional uha device-driver i386/isa/wd.c optional wdc device-driver i386/isa/wd.c optional wd device-driver i386/isa/atapi.c optional atapi device-driver i386/isa/wcd.c optional wcd device-driver i386/isa/wd7000.c optional wds device-driver i386/isa/wt.c optional wt device-driver i386/linux/imgact_linux.c optional linux i386/linux/linux_dummy.c optional linux i386/linux/linux_file.c optional linux -i386/linux/linux_generic.c optional linux i386/linux/linux_ioctl.c optional linux i386/linux/linux_ipc.c optional linux +i386/linux/linux_locore.s optional linux i386/linux/linux_misc.c optional linux i386/linux/linux_signal.c optional linux i386/linux/linux_socket.c optional linux i386/linux/linux_stats.c optional linux i386/linux/linux_sysent.c optional linux +i386/linux/linux_sysvec.c optional linux +i386/linux/linux_util.c optional linux i386/scsi/aic7xxx.c optional ahc device-driver \ dependency "$S/dev/aic7xxx/aic7xxx_reg.h aic7xxx_seq.h" i386/scsi/bt.c optional bt device-driver libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/moddi3.c standard libkern/qdivrem.c standard libkern/qsort.c standard libkern/random.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/udivdi3.c standard libkern/umoddi3.c standard gnu/i386/fpemul/div_small.s optional gpl_math_emulate gnu/i386/fpemul/errors.c optional gpl_math_emulate gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate gnu/i386/fpemul/get_address.c optional gpl_math_emulate gnu/i386/fpemul/load_store.c optional gpl_math_emulate gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate gnu/i386/fpemul/poly_div.s optional gpl_math_emulate gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate gnu/i386/fpemul/polynomial.s optional gpl_math_emulate gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate gnu/i386/fpemul/reg_div.s optional gpl_math_emulate gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate gnu/i386/fpemul/reg_round.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate gnu/i386/isa/dgb.c optional dgb device-driver gnu/i386/isa/nic3008.c optional nic device-driver gnu/i386/isa/nic3009.c optional nnic device-driver pci/wd82371.c optional wd device-driver diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386 index b48ef2c90b1e..f30187dd58dd 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,10 +1,12 @@ BOUNCEPAGES opt_bounce.h USER_LDT MATH_EMULATE opt_math_emulate.h GPL_MATH_EMULATE opt_math_emulate.h MAXCONS opt_syscons.h IBCS2 opt_ibcs2.h SHOW_BUSYBUFS opt_machdep.h PANIC_REBOOT_WAIT_TIME opt_machdep.h LARGEMEM opt_machdep.h MAXMEM opt_machdep.h +LINUX opt_linux.h +COMPAT_LINUX opt_linux.h diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index c32df1735d57..a22e6447646b 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -1,293 +1,293 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: exception.s,v 1.13 1995/12/19 14:30:24 davidg Exp $ + * $Id: exception.s,v 1.14 1995/12/21 19:20:57 davidg Exp $ */ #include "npx.h" /* NNPX */ #include "assym.s" /* system defines */ #include /* error return codes */ #include /* SWI_AST_MASK ... */ #include /* PSL_I */ #include /* trap codes */ #include /* syscall numbers */ #include /* miscellaneous macros */ #define KDSEL 0x10 /* kernel data selector */ #define SEL_RPL_MASK 0x0003 #define TRAPF_CS_OFF (13 * 4) .text /*****************************************************************************/ /* Trap handling */ /*****************************************************************************/ /* * Trap and fault vector routines */ #define IDTVEC(name) ALIGN_TEXT ; .globl _X/**/name ; _X/**/name: #define TRAP(a) pushl $(a) ; jmp _alltraps /* * XXX - debugger traps are now interrupt gates so at least bdb doesn't lose * control. The sti's give the standard losing behaviour for ddb and kgdb. */ #ifdef BDE_DEBUGGER #define BDBTRAP(name) \ ss ; \ cmpb $0,_bdb_exists ; \ je 1f ; \ testb $SEL_RPL_MASK,4(%esp) ; \ jne 1f ; \ ss ; \ .globl bdb_/**/name/**/_ljmp ; \ bdb_/**/name/**/_ljmp: ; \ ljmp $0,$0 ; \ 1: #else #define BDBTRAP(name) #endif #ifdef KGDB # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; \ pushl $(a) ; jmp _bpttraps #else # define BPTTRAP(a) testl $PSL_I,4+8(%esp) ; je 1f ; sti ; 1: ; TRAP(a) #endif MCOUNT_LABEL(user) MCOUNT_LABEL(btrap) IDTVEC(div) pushl $0; TRAP(T_DIVIDE) IDTVEC(dbg) BDBTRAP(dbg) pushl $0; BPTTRAP(T_TRCTRAP) IDTVEC(nmi) pushl $0; TRAP(T_NMI) IDTVEC(bpt) BDBTRAP(bpt) pushl $0; BPTTRAP(T_BPTFLT) IDTVEC(ofl) pushl $0; TRAP(T_OFLOW) IDTVEC(bnd) pushl $0; TRAP(T_BOUND) IDTVEC(ill) pushl $0; TRAP(T_PRIVINFLT) IDTVEC(dna) pushl $0; TRAP(T_DNA) IDTVEC(fpusegm) pushl $0; TRAP(T_FPOPFLT) IDTVEC(tss) TRAP(T_TSSFLT) IDTVEC(missing) TRAP(T_SEGNPFLT) IDTVEC(stk) TRAP(T_STKFLT) IDTVEC(prot) TRAP(T_PROTFLT) IDTVEC(page) TRAP(T_PAGEFLT) IDTVEC(rsvd) pushl $0; TRAP(T_RESERVED) IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can * call npxintr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. */ pushl $0 /* dumby error code */ pushl $0 /* dumby trap type */ pushal pushl %ds pushl %es /* now the stack frame is a trap frame */ movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) movl _cpl,%eax pushl %eax pushl $0 /* dummy unit to finish building intr frame */ incl _cnt+V_TRAP orl $SWI_AST_MASK,%eax movl %eax,_cpl call _npxintr incb _intr_nesting_level MEXITCOUNT jmp _doreti #else /* NNPX > 0 */ pushl $0; TRAP(T_ARITHTRAP) #endif /* NNPX > 0 */ IDTVEC(align) TRAP(T_ALIGNFLT) SUPERALIGN_TEXT _alltraps: pushal pushl %ds pushl %es alltraps_with_regs_pushed: movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) calltrap: FAKE_MCOUNT(_btrap) /* init "from" _btrap -> calltrap */ incl _cnt+V_TRAP orl $SWI_AST_MASK,_cpl call _trap /* * There was no place to save the cpl so we have to recover it * indirectly. For traps from user mode it was 0, and for traps * from kernel mode Oring SWI_AST_MASK into it didn't change it. */ subl %eax,%eax testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) jne 1f movl _cpl,%eax 1: /* * Return via _doreti to handle ASTs. Have to change trap frame * to interrupt frame. */ pushl %eax subl $4,%esp incb _intr_nesting_level MEXITCOUNT jmp _doreti #ifdef KGDB /* * This code checks for a kgdb trap, then falls through * to the regular trap code. */ SUPERALIGN_TEXT _bpttraps: pushal pushl %ds pushl %es movl $KDSEL,%eax movl %ax,%ds movl %ax,%es FAKE_MCOUNT(12*4(%esp)) testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp) /* non-kernel mode? */ jne calltrap /* yes */ call _kgdb_trap_glue MEXITCOUNT jmp calltrap #endif /* * Call gate entry for syscall. * The intersegment call has been set up to specify one dummy parameter. * This leaves a place to put eflags so that the call frame can be * converted to a trap frame. Note that the eflags is (semi-)bogusly * pushed into (what will be) tf_err and then copied later into the * final spot. It has to be done this way because esp can't be just * temporarily altered for the pushfl - an interrupt might come in * and clobber the saved cs/eip. */ SUPERALIGN_TEXT IDTVEC(syscall) pushfl /* save eflags in tf_err for now */ subl $4,%esp /* skip over tf_trapno */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es movl TF_ERR(%esp),%eax /* copy saved eflags to final spot */ movl %eax,TF_EFLAGS(%esp) + movl $7,TF_ERR(%esp) /* sizeof "lcall 7,0" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#if defined(COMPAT_LINUX) || defined(LINUX) /* - * Call gate entry for Linux syscall (int 0x80) + * Call gate entry for Linux/NetBSD syscall (int 0x80) */ SUPERALIGN_TEXT -IDTVEC(linux_syscall) +IDTVEC(int0x80_syscall) subl $8,%esp /* skip over tf_trapno and tf_err */ pushal pushl %ds pushl %es movl $KDSEL,%eax /* switch to kernel segments */ movl %ax,%ds movl %ax,%es + movl $2,TF_ERR(%esp) /* sizeof "int 0x80" */ FAKE_MCOUNT(12*4(%esp)) incl _cnt+V_SYSCALL movl $SWI_AST_MASK,_cpl - call _linux_syscall + call _syscall /* * Return via _doreti to handle ASTs. */ pushl $0 /* cpl to restore */ subl $4,%esp movb $1,_intr_nesting_level MEXITCOUNT jmp _doreti -#endif /* COMPAT_LINUX || LINUX */ /* * Include what was once config+isa-dependent code. * XXX it should be in a stand-alone file. It's still icu-dependent and * belongs in i386/isa. */ #include "i386/isa/vector.s" /* * Include what was once icu-dependent code. * XXX it should be merged into this file (also move the definition of * imen to vector.s or isa.c). * Before including it, set up a normal asm environment so that vector.s * doesn't have to know that stuff is included after it. */ .data ALIGN_DATA .text SUPERALIGN_TEXT #include "i386/isa/icu.s" diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s index 6cafa0021a4a..e578692bd401 100644 --- a/sys/i386/i386/locore.s +++ b/sys/i386/i386/locore.s @@ -1,800 +1,806 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)locore.s 7.3 (Berkeley) 5/13/91 - * $Id: locore.s,v 1.61 1996/01/30 07:59:02 davidg Exp $ + * $Id: locore.s,v 1.62 1996/02/04 21:20:32 davidg Exp $ */ /* * locore.s: FreeBSD machine support for the Intel 386 * originally from: locore.s, by William F. Jolitz * * Substantially rewritten by David Greenman, Rod Grimes, * Bruce Evans, Wolfgang Solfrank, and many others. */ #include "opt_ddb.h" #include "assym.s" /* system definitions */ #include /* processor status longword defs */ #include /* page table entry definitions */ #include /* error return codes */ #include /* x86 special registers */ #include /* x86 cpu type definitions */ #include /* system call numbers */ #include /* miscellaneous asm macros */ #include #include "apm.h" /* * XXX * * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ /* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .globl _PTmap,_PTD,_PTDpde .set _PTmap,PTDPTDI << PDRSHIFT .set _PTD,_PTmap + (PTDPTDI * NBPG) .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) /* * Sysmap is the base address of the kernel page tables. * It is a bogus interface for kgdb and isn't used by the kernel itself. */ .set _Sysmap,_PTmap + (KPTDI * NBPG) /* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .globl _APTmap,_APTD,_APTDpde .set _APTmap,APTDPTDI << PDRSHIFT .set _APTD,_APTmap + (APTDPTDI * NBPG) .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) /* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack,USRSTACK .globl _kstack /* * Globals */ .data .align 2 /* Just to be sure */ .globl tmpstk .space 0x2000 /* space for tmpstk - temporary stack */ tmpstk: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555 .globl _boothowto,_bootdev .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id,_bootinfo .globl _cpu_high, _cpu_feature _cpu: .long 0 /* are we 386, 386sx, or 486 */ _cpu_id: .long 0 /* stepping ID */ _cpu_high: .long 0 /* highest arg to CPUID */ _cpu_feature: .long 0 /* features */ _cpu_vendor: .space 20 /* CPU origin code */ _bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ _cold: .long 1 /* cold till we are not */ _atdevbase: .long 0 /* location of start of iomem in virtual */ _atdevphys: .long 0 /* location of device mapping ptes (phys) */ _KERNend: .long 0 /* phys addr end of kernel (just after bss) */ .globl _IdlePTD _IdlePTD: .long 0 /* phys addr of kernel PTD */ _KPTphys: .long 0 /* phys addr of kernel page tables */ .globl _proc0paddr _proc0paddr: .long 0 /* address of proc 0 address space */ #ifdef BDE_DEBUGGER .globl _bdb_exists /* flag to indicate BDE debugger is available */ _bdb_exists: .long 0 #endif /* * System Initialization */ .text /* * btext: beginning of text section. * Also the entry point (jumped to directly from the boot blocks). */ NON_GPROF_ENTRY(btext) movw $0x1234,0x472 /* warm boot */ /* Set up a real frame, some day we will be doing returns */ pushl %ebp movl %esp, %ebp /* Don't trust what the BIOS gives for eflags. */ pushl $PSL_KERNEL popfl /* Don't trust what the BIOS gives for %fs and %gs. */ mov %ds, %ax mov %ax, %fs mov %ax, %gs /* * This code is called in different ways depending on what loaded * and started the kernel. This is used to detect how we get the * arguments from the other code and what we do with them. * * Old disk boot blocks: * (*btext)(howto, bootdev, cyloffset, esym); * [return address == 0, and can NOT be returned to] * [cyloffset was not supported by the FreeBSD boot code * and always passed in as 0] * [esym is also known as total in the boot code, and * was never properly supported by the FreeBSD boot code] * * Old diskless netboot code: * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); * [return address != 0, and can NOT be returned to] * If we are being booted by this code it will NOT work, * so we are just going to halt if we find this case. * * New uniform boot code: * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) * [return address != 0, and can be returned to] * * There may seem to be a lot of wasted arguments in here, but * that is so the newer boot code can still load very old kernels * and old boot code can load new kernels. */ /* * The old style disk boot blocks fake a frame on the stack and * did an lret to get here. The frame on the stack has a return * address of 0. */ cmpl $0,4(%ebp) je 2f /* olddiskboot: */ /* * We have some form of return address, so this is either the * old diskless netboot code, or the new uniform code. That can * be detected by looking at the 5th argument, it if is 0 we * we are being booted by the new unifrom boot code. */ cmpl $0,24(%ebp) je 1f /* newboot: */ /* * Seems we have been loaded by the old diskless boot code, we * don't stand a chance of running as the diskless structure * changed considerably between the two, so just halt. */ hlt /* * We have been loaded by the new uniform boot code. * Lets check the bootinfo version, and if we do not understand * it we return to the loader with a status of 1 to indicate this error */ 1: /* newboot: */ movl 28(%ebp),%ebx /* &bootinfo.version */ movl BI_VERSION(%ebx),%eax cmpl $1,%eax /* We only understand version 1 */ je 1f movl $1,%eax /* Return status */ leave ret 1: /* * If we have a kernelname copy it in */ movl BI_KERNELNAME(%ebx),%esi cmpl $0,%esi je 2f /* No kernelname */ movl $MAXPATHLEN,%ecx /* Brute force!!! */ lea _kernelname-KERNBASE,%edi cmpb $'/',(%esi) /* Make sure it starts with a slash */ je 1f movb $'/',(%edi) incl %edi decl %ecx 1: cld rep movsb 2: /* * Determine the size of the boot loader's copy of the bootinfo * struct. This is impossible to do properly because old versions * of the struct don't contain a size field and there are 2 old * versions with the same version number. */ movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ je got_bi_size /* no, sizeless version */ movl BI_SIZE(%ebx),%ecx got_bi_size: /* * Copy the common part of the bootinfo struct */ movl %ebx,%esi movl $_bootinfo-KERNBASE,%edi cmpl $BOOTINFO_SIZE,%ecx jbe got_common_bi_size movl $BOOTINFO_SIZE,%ecx got_common_bi_size: cld rep movsb #ifdef NFS /* * If we have a nfs_diskless structure copy it in */ movl BI_NFS_DISKLESS(%ebx),%esi cmpl $0,%esi je 2f lea _nfs_diskless-KERNBASE,%edi movl $NFSDISKLESS_SIZE,%ecx cld rep movsb lea _nfs_diskless_valid-KERNBASE,%edi movl $1,(%edi) #endif /* * The old style disk boot. * (*btext)(howto, bootdev, cyloffset, esym); * Note that the newer boot code just falls into here to pick * up howto and bootdev, cyloffset and esym are no longer used */ 2: /* olddiskboot: */ movl 8(%ebp),%eax movl %eax,_boothowto-KERNBASE movl 12(%ebp),%eax movl %eax,_bootdev-KERNBASE #if NAPM > 0 /* call APM BIOS driver setup (i386/apm/apm_setup.s) */ call _apm_setup #endif /* NAPM */ /* Find out our CPU type. */ /* Try to toggle alignment check flag; does not exist on 386. */ pushfl popl %eax movl %eax,%ecx orl $PSL_AC,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_AC,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_386,_cpu-KERNBASE jmp 3f 1: /* Try to toggle identification flag; does not exist on early 486s. */ pushfl popl %eax movl %eax,%ecx xorl $PSL_ID,%eax pushl %eax popfl pushfl popl %eax xorl %ecx,%eax andl $PSL_ID,%eax pushl %ecx popfl testl %eax,%eax jnz 1f movl $CPU_486,_cpu-KERNBASE /* check for Cyrix 486DLC -- based on check routine */ /* documented in "Cx486SLC/e SMM Programmer's Guide" */ xorw %dx,%dx cmpw %dx,%dx # set flags to known state pushfw popw %cx # store flags in ecx movw $0xffff,%ax movw $0x0004,%bx divw %bx pushfw popw %ax andw $0x08d5,%ax # mask off important bits andw $0x08d5,%cx cmpw %ax,%cx jnz 3f # if flags changed, Intel chip movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string movw $0x0078,_cpu_vendor-KERNBASE+4 #ifndef CYRIX_CACHE_WORKS /* Disable caching of the ISA hole only. */ invd movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al orb $(CCR0_NC1|CCR0_BARB),%al movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 invd #else /* CYRIX_CACHE_WORKS */ /* Set cache parameters */ invd # Start with guaranteed clean cache movb $CCR0,%al # Configuration Register index (CCR0) outb %al,$0x22 inb $0x23,%al andb $~CCR0_NC0,%al #ifndef CYRIX_CACHE_REALLY_WORKS orb $(CCR0_NC1|CCR0_BARB),%al #else orb $CCR0_NC1,%al #endif movb %al,%ah movb $CCR0,%al outb %al,$0x22 movb %ah,%al outb %al,$0x23 /* clear non-cacheable region 1 */ movb $(NCR1+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 2 */ movb $(NCR2+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 3 */ movb $(NCR3+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* clear non-cacheable region 4 */ movb $(NCR4+2),%al outb %al,$0x22 movb $NCR_SIZE_0K,%al outb %al,$0x23 /* enable caching in CR0 */ movl %cr0,%eax andl $~(CR0_CD|CR0_NW),%eax movl %eax,%cr0 invd #endif /* CYRIX_CACHE_WORKS */ jmp 3f 1: /* Use the `cpuid' instruction. */ xorl %eax,%eax .byte 0x0f,0xa2 # cpuid 0 movl %eax,_cpu_high-KERNBASE # highest capability movl %ebx,_cpu_vendor-KERNBASE # store vendor string movl %edx,_cpu_vendor+4-KERNBASE movl %ecx,_cpu_vendor+8-KERNBASE movb $0,_cpu_vendor+12-KERNBASE movl $1,%eax .byte 0x0f,0xa2 # cpuid 1 movl %eax,_cpu_id-KERNBASE # store cpu_id movl %edx,_cpu_feature-KERNBASE # store cpu_feature rorl $8,%eax # extract family type andl $15,%eax cmpl $5,%eax jae 1f /* less than Pentium; must be 486 */ movl $CPU_486,_cpu-KERNBASE jmp 3f 1: /* a Pentium? */ cmpl $5,%eax jne 2f movl $CPU_586,_cpu-KERNBASE jmp 3f 2: /* Greater than Pentium...call it a Pentium Pro */ movl $CPU_686,_cpu-KERNBASE 3: /* * Finished with old stack; load new %esp now instead of later so * we can trace this code without having to worry about the trace * trap clobbering the memory test or the zeroing of the bss+bootstrap * page tables. * * XXX - wdboot clears the bss after testing that this is safe. * This is too wasteful - memory below 640K is scarce. The boot * program should check: * text+data <= &stack_variable - more_space_for_stack * text+data+bss+pad+space_for_page_tables <= end_of_memory * Oops, the gdt is in the carcass of the boot program so clearing * the rest of memory is still not possible. */ movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ /* * Virtual address space of kernel: * * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap * pages: 1 UPAGES (2) 1 NKPT (7) */ /* find end of kernel image */ movl $_end-KERNBASE,%ecx addl $NBPG-1,%ecx /* page align up */ andl $~(NBPG-1),%ecx movl %ecx,%esi /* esi = start of free memory */ movl %ecx,_KERNend-KERNBASE /* save end of kernel */ /* clear bss */ movl $_edata-KERNBASE,%edi subl %edi,%ecx /* get amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb #ifdef DDB /* include symbols in "kernel image" if they are loaded */ movl _bootinfo+BI_ESYMTAB-KERNBASE,%edi testl %edi,%edi je over_symalloc addl $NBPG-1,%edi andl $~(NBPG-1),%edi movl %edi,%esi movl %esi,_KERNend-KERNBASE movl $KERNBASE,%edi addl %edi,_bootinfo+BI_SYMTAB-KERNBASE addl %edi,_bootinfo+BI_ESYMTAB-KERNBASE over_symalloc: #endif /* * The value in esi is both the end of the kernel bss and a pointer to * the kernel page directory, and is used by the rest of locore to build * the tables. * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel * page table pages) is then passed on the stack to init386(first) as * the value first. esi should ALWAYS be page aligned!! */ movl %esi,%ecx /* Get current first availiable address */ /* clear pagetables, page directory, stack, etc... */ movl %esi,%edi /* base (page directory) */ movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ xorl %eax,%eax /* specify zero fill */ cld rep stosb /* physical address of Idle proc/kernel page directory */ movl %esi,_IdlePTD-KERNBASE /* * fillkpt * eax = (page frame address | control | status) == pte * ebx = address of page table * ecx = how many pages to map */ #define fillkpt \ 1: movl %eax,(%ebx) ; \ addl $NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ; /* * Map Kernel * * First step - build page tables */ #if defined (KGDB) || defined (BDE_DEBUGGER) movl _KERNend-KERNBASE,%ecx /* this much memory, */ shrl $PGSHIFT,%ecx /* for this many PTEs */ #ifdef BDE_DEBUGGER cmpl $0xa0,%ecx /* XXX - cover debugger pages */ jae 1f movl $0xa0,%ecx 1: #endif /* BDE_DEBUGGER */ movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt #else /* !KGDB && !BDE_DEBUGGER */ /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ movl $_etext-KERNBASE,%ecx /* get size of text */ addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $PG_V|PG_KR,%eax /* specify read only */ #if 0 movl $_etext,%ecx /* get size of text */ subl $_btext,%ecx addl $NBPG-1,%ecx /* round up to page */ shrl $PGSHIFT,%ecx /* for this many PTEs */ movl $_btext-KERNBASE,%eax /* get offset to physical memory */ orl $PG_V|PG_KR,%eax /* specify read only */ #endif lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ movl %ebx,_KPTphys-KERNBASE /* save in global */ fillkpt /* data and bss are r/w */ andl $PG_FRAME,%eax /* strip to just addr of bss */ movl _KERNend-KERNBASE,%ecx /* calculate size */ subl %eax,%ecx shrl $PGSHIFT,%ecx orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ fillkpt #endif /* KGDB || BDE_DEBUGGER */ /* now initialize the page dir, upages, and p0stack PT */ movl $(1+UPAGES+1),%ecx /* number of PTEs */ movl %esi,%eax /* phys address of PTD */ andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %esi,%ebx /* calculate pte offset to ptd */ shrl $PGSHIFT-2,%ebx addl %esi,%ebx /* address of page directory */ addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ fillkpt /* map I/O memory map */ movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ movl $0x100-0xa0,%ecx /* for this many pte s, */ movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ fillkpt /* map proc 0's kernel stack into user page table page */ movl $UPAGES,%ecx /* for this many pte s, */ lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ lea (KERNBASE)(%eax),%edx /* change into virtual addr */ movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ fillkpt /* * Initialize kernel page table directory */ /* install a pde for temporary double map of bottom of VA */ movl _KPTphys-KERNBASE,%eax orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ movl %eax,(%esi) /* which is where temp maps! */ /* initialize kernel pde's */ movl $(NKPT),%ecx /* for this many PDEs */ lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax /* phys address of ptd in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ /* install a pde to map kernel stack for proc 0 */ lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ orl $PG_V|PG_KW,%eax /* pde entry is valid */ movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ #ifdef BDE_DEBUGGER /* copy and convert stuff from old gdt and idt for debugger */ cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ jne 1f movb $1,_bdb_exists-KERNBASE 1: pushal subl $2*6,%esp sgdt (%esp) movl 2(%esp),%esi /* base address of current gdt */ movl $_gdt-KERNBASE,%edi movl %edi,2(%esp) movl $8*18/4,%ecx cld rep /* copy gdt */ movsl movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ movb $0x92,-8+5(%edi) sidt 6(%esp) movl 6+2(%esp),%esi /* base address of current idt */ movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ movw 8(%esi),%ax movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ movl 8+2(%esi),%eax movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ movl 24+4(%esi),%eax /* same for bpt descriptor */ movw 24(%esi),%ax movl %eax,bdb_bpt_ljmp+1-KERNBASE movl 24+2(%esi),%eax movw %ax,bdb_bpt_ljmp+5-KERNBASE movl $_idt-KERNBASE,%edi movl %edi,6+2(%esp) movl $8*4/4,%ecx cld rep /* copy idt */ movsl lgdt (%esp) lidt 6(%esp) addl $2*6,%esp popal #endif /* BDE_DEBUGGER */ /* load base of page directory and enable mapping */ movl %esi,%eax /* phys address of ptd in proc 0 */ movl %eax,%cr3 /* load ptd addr into mmu */ movl %cr0,%eax /* get control word */ orl $CR0_PE|CR0_PG,%eax /* enable paging */ movl %eax,%cr0 /* and let's page NOW! */ pushl $begin /* jump to high mem */ ret begin: /* now running relocated at KERNBASE where the system is linked to run */ movl _atdevphys,%edx /* get pte PA */ subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ shll $PGSHIFT-2,%edx /* corresponding to virt offset */ addl $KERNBASE,%edx /* add virtual base */ movl %edx,_atdevbase /* set up bootstrap stack */ movl $_kstack+UPAGES*NBPG,%esp /* bootstrap stack end location */ xorl %eax,%eax /* mark end of frames */ movl %eax,%ebp movl _proc0paddr,%eax movl %esi,PCB_CR3(%eax) #ifdef BDE_DEBUGGER /* relocate debugger gdt entries */ movl $_gdt+8*9,%eax /* adjust slots 9-17 */ movl $9,%ecx reloc_gdt: movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ addl $8,%eax /* now KERNBASE>>24 */ loop reloc_gdt cmpl $0,_bdb_exists je 1f int $3 1: #endif /* BDE_DEBUGGER */ /* * Prepare "first" - physical address of first available page * after the kernel+pdir+upages+p0stack+page tables */ lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi pushl %esi /* value of first for init386(first) */ call _init386 /* wire 386 chip for unix operation */ popl %esi .globl __ucodesel,__udatasel pushl $0 /* unused */ pushl __udatasel /* ss */ pushl $0 /* esp - filled in by execve() */ pushl $PSL_USER /* eflags (IOPL 0, int enab) */ pushl __ucodesel /* cs */ pushl $0 /* eip - filled in by execve() */ subl $(12*4),%esp /* space for rest of registers */ pushl %esp /* call main with frame pointer */ call _main /* autoconfiguration, mountroot etc */ addl $(13*4),%esp /* back to a frame we can return with */ /* * now we've run main() and determined what cpu-type we are, we can * enable write protection and alignment checking on i486 cpus and * above. */ #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) cmpl $CPUCLASS_386,_cpu_class je 1f movl %cr0,%eax /* get control word */ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ movl %eax,%cr0 /* and do it */ #endif /* * on return from main(), we are process 1 * set up address space and stack so that we can 'return' to user mode */ 1: movl __ucodesel,%eax movl __udatasel,%ecx movl %cx,%ds movl %cx,%es movl %ax,%fs /* double map cs to fs */ movl %cx,%gs /* and ds to gs */ iret /* goto user! */ #define LCALL(x,y) .byte 0x9a ; .long y ; .word x +/* + * Signal trampoline, copied to top of user stack + */ NON_GPROF_ENTRY(sigcode) call SIGF_HANDLER(%esp) lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ /* copy at 8(%esp)) */ pushl %eax pushl %eax /* junk to fake return address */ - movl $103,%eax /* XXX sigreturn() */ + movl $SYS_sigreturn,%eax /* sigreturn() */ LCALL(0x7,0) /* enter kernel with args on stack */ hlt /* never gets here */ - + .align 2 /* long word align */ +_esigcode: + .data .globl _szsigcode _szsigcode: - .long _szsigcode-_sigcode + .long _esigcode-_sigcode + .text diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 067d4e794c70..30f442e39e7f 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -1,1830 +1,1817 @@ /*- * Copyright (c) 1992 Terrence R. Lambert. * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.174 1996/02/13 10:30:36 phk Exp $ + * $Id: machdep.c,v 1.175 1996/03/02 18:24:00 peter Exp $ */ #include "npx.h" #include "isa.h" #include "opt_sysvipc.h" #include "opt_ddb.h" #include "opt_bounce.h" #include "opt_machdep.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SYSVSHM #include #endif #ifdef SYSVMSG #include #endif #ifdef SYSVSEM #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern void init386 __P((int first)); extern int ptrace_set_pc __P((struct proc *p, unsigned int addr)); extern int ptrace_single_step __P((struct proc *p)); extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data)); extern void dblfault_handler __P((void)); extern void i486_bzero __P((void *, size_t)); extern void i586_bzero __P((void *, size_t)); extern void i686_bzero __P((void *, size_t)); static void cpu_startup __P((void *)); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) static void identifycpu(void); char machine[] = "i386"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); static char cpu_model[128]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, ""); struct kern_devconf kdc_cpu0 = { 0, 0, 0, /* filled in by dev_attach */ "cpu", 0, { MDDT_CPU }, 0, 0, 0, CPU_EXTERNALLEN, 0, /* CPU has no parent */ 0, /* no parentdata */ DC_BUSY, /* the CPU is always busy */ cpu_model, /* no sense in duplication */ DC_CLS_CPU /* class */ }; #ifndef PANIC_REBOOT_WAIT_TIME #define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */ #endif #ifdef BOUNCE_BUFFERS extern char *bouncememory; extern int maxbkva; #ifdef BOUNCEPAGES int bouncepages = BOUNCEPAGES; #else int bouncepages = 0; #endif #endif /* BOUNCE_BUFFERS */ extern int freebufspace; int msgbufmapped = 0; /* set when safe to use msgbuf */ int _udatasel, _ucodesel; int physmem = 0; static int sysctl_hw_physmem SYSCTL_HANDLER_ARGS { int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); return (error); } SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_physmem, "I", ""); static int sysctl_hw_usermem SYSCTL_HANDLER_ARGS { int error = sysctl_handle_int(oidp, 0, ctob(physmem - cnt.v_wire_count), req); return (error); } SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, 0, 0, sysctl_hw_usermem, "I", ""); int boothowto = 0, bootverbose = 0, Maxmem = 0; static int badpages = 0; long dumplo; extern int bootdev; vm_offset_t phys_avail[10]; /* must be 2 less so 0 0 can signal end of chunks */ #define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) int cpu_class = CPUCLASS_386; /* smallest common denominator */ static void dumpsys __P((void)); static void setup_netisrs __P((struct linker_set *)); /* XXX declare elsewhere */ static vm_offset_t buffer_sva, buffer_eva; vm_offset_t clean_sva, clean_eva; static vm_offset_t pager_sva, pager_eva; extern struct linker_set netisr_set; #define offsetof(type, member) ((size_t)(&((type *)0)->member)) static void cpu_startup(dummy) void *dummy; { register unsigned i; register caddr_t v; vm_offset_t maxaddr; vm_size_t size = 0; int firstaddr; vm_offset_t minaddr; if (boothowto & RB_VERBOSE) bootverbose++; /* * Initialize error message buffer (at end of core). */ /* avail_end was pre-decremented in init_386() to compensate */ for (i = 0; i < btoc(sizeof (struct msgbuf)); i++) pmap_enter(pmap_kernel(), (vm_offset_t)msgbufp, avail_end + i * NBPG, VM_PROT_ALL, TRUE); msgbufmapped = 1; /* * Good {morning,afternoon,evening,night}. */ printf(version); startrtclock(); identifycpu(); printf("real memory = %d (%dK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024); /* * Display any holes after the first chunk of extended memory. */ if (badpages != 0) { int indx = 1; /* * XXX skip reporting ISA hole & unmanaged kernel memory */ if (phys_avail[0] == PAGE_SIZE) indx += 2; printf("Physical memory hole(s):\n"); for (; phys_avail[indx + 1] != 0; indx += 2) { int size = phys_avail[indx + 1] - phys_avail[indx]; printf("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[indx], phys_avail[indx + 1] - 1, size, size / PAGE_SIZE); } } /* * Quickly wire in netisrs. */ setup_netisrs(&netisr_set); /* #ifdef ISDN DONET(isdnintr, NETISR_ISDN); #endif */ /* * Allocate space for system data structures. * The first available kernel virtual address is in "v". * As pages of kernel virtual memory are allocated, "v" is incremented. * As pages of memory are allocated and cleared, * "firstaddr" is incremented. * An index into the kernel page table corresponding to the * virtual memory address maintained in "v" is kept in "mapaddr". */ /* * Make two passes. The first pass calculates how much memory is * needed and allocates it. The second pass assigns virtual * addresses to the various data structures. */ firstaddr = 0; again: v = (caddr_t)firstaddr; #define valloc(name, type, num) \ (name) = (type *)v; v = (caddr_t)((name)+(num)) #define valloclim(name, type, num, lim) \ (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) valloc(callout, struct callout, ncallout); #ifdef SYSVSHM valloc(shmsegs, struct shmid_ds, shminfo.shmmni); #endif #ifdef SYSVSEM valloc(sema, struct semid_ds, seminfo.semmni); valloc(sem, struct sem, seminfo.semmns); /* This is pretty disgusting! */ valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); #endif #ifdef SYSVMSG valloc(msgpool, char, msginfo.msgmax); valloc(msgmaps, struct msgmap, msginfo.msgseg); valloc(msghdrs, struct msg, msginfo.msgtql); valloc(msqids, struct msqid_ds, msginfo.msgmni); #endif if (nbuf == 0) { nbuf = 30; if( physmem > 1024) nbuf += min((physmem - 1024) / 12, 1024); } nswbuf = min(nbuf, 128); valloc(swbuf, struct buf, nswbuf); valloc(buf, struct buf, nbuf); #ifdef BOUNCE_BUFFERS /* * If there is more than 16MB of memory, allocate some bounce buffers */ if (Maxmem > 4096) { if (bouncepages == 0) { bouncepages = 64; bouncepages += ((Maxmem - 4096) / 2048) * 32; } v = (caddr_t)((vm_offset_t)((vm_offset_t)v + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); valloc(bouncememory, char, bouncepages * PAGE_SIZE); } #endif /* * End of first pass, size has been calculated so allocate memory */ if (firstaddr == 0) { size = (vm_size_t)(v - firstaddr); firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); if (firstaddr == 0) panic("startup: no room for tables"); goto again; } /* * End of second pass, addresses have been assigned */ if ((vm_size_t)(v - firstaddr) != size) panic("startup: table size inconsistency"); #ifdef BOUNCE_BUFFERS clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + maxbkva + pager_map_size, TRUE); io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva, FALSE); #else clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, (nbuf*MAXBSIZE) + (nswbuf*MAXPHYS) + pager_map_size, TRUE); #endif buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, (nbuf*MAXBSIZE), TRUE); pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, (nswbuf*MAXPHYS) + pager_map_size, TRUE); exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, (16*ARG_MAX), TRUE); u_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, (maxproc*UPAGES*PAGE_SIZE), FALSE); /* * Finally, allocate mbuf pool. Since mclrefcnt is an off-size * we use the more space efficient malloc in place of kmem_alloc. */ mclrefcnt = (char *)malloc(nmbclusters+CLBYTES/MCLBYTES, M_MBUF, M_NOWAIT); bzero(mclrefcnt, nmbclusters+CLBYTES/MCLBYTES); mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr, nmbclusters * MCLBYTES, FALSE); /* * Initialize callouts */ callfree = callout; for (i = 1; i < ncallout; i++) callout[i-1].c_next = &callout[i]; if (boothowto & RB_CONFIG) { userconfig(); cninit(); /* the preferred console may have changed */ } #ifdef BOUNCE_BUFFERS /* * init bounce buffers */ vm_bounce_init(); #endif printf("avail memory = %d (%dK bytes)\n", ptoa(cnt.v_free_count), ptoa(cnt.v_free_count) / 1024); /* * Set up buffers, so they can be used to read disk labels. */ bufinit(); vm_pager_bufferinit(); /* * In verbose mode, print out the BIOS's idea of the disk geometries. */ if (bootverbose) { printf("BIOS Geometries:\n"); for (i = 0; i < N_BIOS_GEOM; i++) { unsigned long bios_geom; int max_cylinder, max_head, max_sector; bios_geom = bootinfo.bi_bios_geom[i]; /* * XXX the bootstrap punts a 1200K floppy geometry * when the get-disk-geometry interrupt fails. Skip * drives that have this geometry. */ if (bios_geom == 0x4f010f) continue; printf(" %x:%08lx ", i, bios_geom); max_cylinder = bios_geom >> 16; max_head = (bios_geom >> 8) & 0xff; max_sector = bios_geom & 0xff; printf( "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", max_cylinder, max_cylinder + 1, max_head, max_head + 1, max_sector, max_sector); } printf(" %d accounted for\n", bootinfo.bi_n_bios_used); } } int register_netisr(num, handler) int num; netisr_t *handler; { if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { printf("register_netisr: bad isr number: %d\n", num); return (EINVAL); } netisrs[num] = handler; return (0); } static void setup_netisrs(ls) struct linker_set *ls; { int i; const struct netisrtab *nit; for(i = 0; ls->ls_items[i]; i++) { nit = (const struct netisrtab *)ls->ls_items[i]; register_netisr(nit->nit_num, nit->nit_isr); } } static struct cpu_nameclass i386_cpus[] = { { "Intel 80286", CPUCLASS_286 }, /* CPU_286 */ { "i386SX", CPUCLASS_386 }, /* CPU_386SX */ { "i386DX", CPUCLASS_386 }, /* CPU_386 */ { "i486SX", CPUCLASS_486 }, /* CPU_486SX */ { "i486DX", CPUCLASS_486 }, /* CPU_486 */ { "Pentium", CPUCLASS_586 }, /* CPU_586 */ { "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */ { "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */ }; static void identifycpu() { printf("CPU: "); if (cpu >= 0 && cpu < (sizeof i386_cpus/sizeof(struct cpu_nameclass))) { cpu_class = i386_cpus[cpu].cpu_class; strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model); } else { printf("unknown cpu type %d\n", cpu); panic("startup: bad cpu id"); } #if defined(I586_CPU) || defined(I686_CPU) if (cpu_class == CPUCLASS_586 || cpu_class == CPUCLASS_686) { calibrate_cyclecounter(); } #endif #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) if (!strcmp(cpu_vendor,"GenuineIntel")) { if ((cpu_id & 0xf00) > 3) { cpu_model[0] = '\0'; switch (cpu_id & 0x3000) { case 0x1000: strcpy(cpu_model, "Overdrive "); break; case 0x2000: strcpy(cpu_model, "Dual "); break; } switch (cpu_id & 0xf00) { case 0x400: strcat(cpu_model, "i486 "); break; case 0x500: strcat(cpu_model, "Pentium"); /* nb no space */ break; case 0x600: strcat(cpu_model, "Pentium Pro"); break; default: strcat(cpu_model, "unknown"); break; } switch (cpu_id & 0xff0) { case 0x400: strcat(cpu_model, "DX"); break; case 0x410: strcat(cpu_model, "DX"); break; case 0x420: strcat(cpu_model, "SX"); break; case 0x430: strcat(cpu_model, "DX2"); break; case 0x440: strcat(cpu_model, "SL"); break; case 0x450: strcat(cpu_model, "SX2"); break; case 0x470: strcat(cpu_model, "DX2 Write-Back Enhanced"); break; case 0x480: strcat(cpu_model, "DX4"); break; break; } } } #endif printf("%s (", cpu_model); switch(cpu_class) { case CPUCLASS_286: printf("286"); break; #if defined(I386_CPU) case CPUCLASS_386: printf("386"); break; #endif #if defined(I486_CPU) case CPUCLASS_486: printf("486"); bzero = i486_bzero; break; #endif #if defined(I586_CPU) case CPUCLASS_586: printf("%d.%02d-MHz ", ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100, ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100); printf("586"); bzero = i586_bzero; break; #endif #if defined(I686_CPU) case CPUCLASS_686: printf("%d.%02d-MHz ", ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100, ((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100); printf("686"); bzero = i686_bzero; break; #endif default: printf("unknown"); /* will panic below... */ } printf("-class CPU)\n"); #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) if(*cpu_vendor) printf(" Origin = \"%s\"",cpu_vendor); if(cpu_id) printf(" Id = 0x%lx",cpu_id); if (!strcmp(cpu_vendor, "GenuineIntel")) { printf(" Stepping=%ld", cpu_id & 0xf); if (cpu_high > 0) { printf("\n Features=0x%b", cpu_feature, "\020" "\001FPU" "\002VME" "\003DE" "\004PSE" "\005TSC" "\006MSR" "\007PAE" "\010MCE" "\011CX8" "\012APIC" "\013" "\014" "\015MTRR" "\016PGE" "\017MCA" "\020CMOV" ); } } /* Avoid ugly blank lines: only print newline when we have to. */ if (*cpu_vendor || cpu_id) printf("\n"); #endif /* * Now that we have told the user what they have, * let them know if that machine type isn't configured. */ switch (cpu_class) { case CPUCLASS_286: /* a 286 should not make it this far, anyway */ #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU) #error This kernel is not configured for one of the supported CPUs #endif #if !defined(I386_CPU) case CPUCLASS_386: #endif #if !defined(I486_CPU) case CPUCLASS_486: #endif #if !defined(I586_CPU) case CPUCLASS_586: #endif #if !defined(I686_CPU) case CPUCLASS_686: #endif panic("CPU class not configured"); default: break; } dev_attach(&kdc_cpu0); } /* * Send an interrupt to process. * * Stack is set up to allow sigcode stored - * in u. to call routine, followed by kcall + * at top 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. */ void sendsig(catcher, sig, mask, code) sig_t catcher; int sig, mask; unsigned code; { register struct proc *p = curproc; register int *regs; register struct sigframe *fp; struct sigframe sf; struct sigacts *psp = p->p_sigacts; int oonstack; regs = p->p_md.md_regs; - oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; + oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; /* - * Allocate and validate space for the signal handler - * context. Note that if the stack is in P0 space, the - * call to grow() is a nop, and the useracc() check - * will fail if the process has not already allocated - * the space with a `brk'. + * Allocate and validate space for the signal handler context. */ - if ((psp->ps_flags & SAS_ALTSTACK) && - (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 && + if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size - sizeof(struct sigframe)); - psp->ps_sigstk.ss_flags |= SA_ONSTACK; + psp->ps_sigstk.ss_flags |= SS_ONSTACK; } else { - fp = (struct sigframe *)(regs[tESP] - - sizeof(struct sigframe)); + fp = (struct 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 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; } sf.sf_signum = sig; sf.sf_code = code; sf.sf_scp = &fp->sf_sc; sf.sf_addr = (char *) regs[tERR]; sf.sf_handler = catcher; /* save scratch registers */ sf.sf_sc.sc_eax = regs[tEAX]; sf.sf_sc.sc_ebx = regs[tEBX]; sf.sf_sc.sc_ecx = regs[tECX]; sf.sf_sc.sc_edx = regs[tEDX]; sf.sf_sc.sc_esi = regs[tESI]; sf.sf_sc.sc_edi = regs[tEDI]; sf.sf_sc.sc_cs = regs[tCS]; sf.sf_sc.sc_ds = regs[tDS]; sf.sf_sc.sc_ss = regs[tSS]; sf.sf_sc.sc_es = regs[tES]; sf.sf_sc.sc_isp = regs[tISP]; /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = oonstack; sf.sf_sc.sc_mask = mask; sf.sf_sc.sc_sp = regs[tESP]; sf.sf_sc.sc_fp = regs[tEBP]; sf.sf_sc.sc_pc = regs[tEIP]; sf.sf_sc.sc_ps = regs[tEFLAGS]; /* * Copy the sigframe out to the user's stack. */ if (copyout(&sf, fp, sizeof(struct sigframe)) != 0) { /* * Something is wrong with the stack pointer. * ...Kill the process. */ sigexit(p, SIGILL); }; regs[tESP] = (int)fp; - regs[tEIP] = (int)((struct pcb *)kstack)->pcb_sigc; + 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 * state to gain improper privileges. */ int sigreturn(p, uap, retval) struct proc *p; struct sigreturn_args /* { struct sigcontext *sigcntxp; } */ *uap; int *retval; { register struct sigcontext *scp; register struct sigframe *fp; register int *regs = p->p_md.md_regs; int eflags; /* * (XXX old comment) regs[tESP] points to the return address. * The user scp pointer is above that. * The return address is faked in the signal trampoline code * for consistency. */ scp = uap->sigcntxp; fp = (struct sigframe *) ((caddr_t)scp - offsetof(struct sigframe, sf_sc)); if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0) return(EINVAL); /* * Don't allow users to change privileged or reserved flags. */ #define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = scp->sc_ps; /* * 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)) { #ifdef DEBUG printf("sigreturn: eflags = 0x%x\n", eflags); #endif 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(scp->sc_cs)) { #ifdef DEBUG printf("sigreturn: cs = 0x%x\n", scp->sc_cs); #endif trapsignal(p, SIGBUS, T_PROTFLT); return(EINVAL); } /* restore scratch registers */ regs[tEAX] = scp->sc_eax; regs[tEBX] = scp->sc_ebx; regs[tECX] = scp->sc_ecx; regs[tEDX] = scp->sc_edx; regs[tESI] = scp->sc_esi; regs[tEDI] = scp->sc_edi; regs[tCS] = scp->sc_cs; regs[tDS] = scp->sc_ds; regs[tES] = scp->sc_es; regs[tSS] = scp->sc_ss; regs[tISP] = scp->sc_isp; if (useracc((caddr_t)scp, sizeof (*scp), 0) == 0) return(EINVAL); if (scp->sc_onstack & 01) - p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK; + p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else - p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK; + p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; p->p_sigmask = scp->sc_mask &~ (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)); regs[tEBP] = scp->sc_fp; regs[tESP] = scp->sc_sp; regs[tEIP] = scp->sc_pc; regs[tEFLAGS] = eflags; return(EJUSTRETURN); } static int waittime = -1; static struct pcb dumppcb; __dead void boot(howto) int howto; { if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) { register struct buf *bp; int iter, nbusy; waittime = 0; printf("\nsyncing disks... "); sync(&proc0, NULL, NULL); for (iter = 0; iter < 20; iter++) { nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { nbusy++; } } if (nbusy == 0) break; printf("%d ", nbusy); DELAY(40000 * iter); } if (nbusy) { /* * Failed to sync all blocks. Indicate this and don't * unmount filesystems (thus forcing an fsck on reboot). */ printf("giving up\n"); #ifdef SHOW_BUSYBUFS nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) { if ((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) { nbusy++; printf("%d: dev:%08x, flags:%08x, blkno:%d, lblkno:%d\n", nbusy, bp->b_dev, bp->b_flags, bp->b_blkno, bp->b_lblkno); } } DELAY(5000000); /* 5 seconds */ #endif } else { printf("done\n"); /* * Unmount filesystems */ if (panicstr == 0) vfs_unmountall(); } DELAY(100000); /* wait for console output to finish */ dev_shutdownall(FALSE); } splhigh(); if (howto & RB_HALT) { printf("\n"); printf("The operating system has halted.\n"); printf("Please press any key to reboot.\n\n"); cngetc(); } else { if (howto & RB_DUMP) { if (!cold) { savectx(&dumppcb); dumppcb.pcb_ptd = rcr3(); dumpsys(); } if (PANIC_REBOOT_WAIT_TIME != 0) { if (PANIC_REBOOT_WAIT_TIME != -1) { int loop; printf("Automatic reboot in %d seconds - press a key on the console to abort\n", PANIC_REBOOT_WAIT_TIME); for (loop = PANIC_REBOOT_WAIT_TIME * 10; loop > 0; --loop) { DELAY(1000 * 100); /* 1/10th second */ if (cncheckc()) /* Did user type a key? */ break; } if (!loop) goto die; } } else { /* zero time specified - reboot NOW */ goto die; } printf("--> Press a key on the console to reboot <--\n"); cngetc(); } } die: printf("Rebooting...\n"); DELAY(1000000); /* wait 1 sec for printf's to complete and be read */ cpu_reset(); for(;;) ; /* NOTREACHED */ } /* * Magic number for savecore * * exported (symorder) and used at least by savecore(8) * */ u_long dumpmag = 0x8fca0101UL; static int dumpsize = 0; /* also for savecore */ static int dodump = 1; SYSCTL_INT(_machdep, OID_AUTO, do_dump, CTLFLAG_RW, &dodump, 0, ""); /* * Doadump comes here after turning off memory management and * getting on the dump stack, either when called above, or by * the auto-restart code. */ static void dumpsys() { if (!dodump) return; if (dumpdev == NODEV) return; if ((minor(dumpdev)&07) != 1) return; if (!(bdevsw[major(dumpdev)])) return; if (!(bdevsw[major(dumpdev)]->d_dump)) return; dumpsize = Maxmem; printf("\ndumping to dev %lx, offset %ld\n", dumpdev, dumplo); printf("dump "); switch ((*bdevsw[major(dumpdev)]->d_dump)(dumpdev)) { case ENXIO: printf("device bad\n"); break; case EFAULT: printf("device not ready\n"); break; case EINVAL: printf("area improper\n"); break; case EIO: printf("i/o error\n"); break; case EINTR: printf("aborted from console\n"); break; default: printf("succeeded\n"); break; } } /* * Clear registers on exec */ void setregs(p, entry, stack) struct proc *p; u_long entry; u_long stack; { int *regs = p->p_md.md_regs; bzero(regs, sizeof(struct trapframe)); regs[tEIP] = entry; regs[tESP] = stack; regs[tEFLAGS] = PSL_USER | (regs[tEFLAGS] & PSL_T); regs[tSS] = _udatasel; regs[tDS] = _udatasel; regs[tES] = _udatasel; regs[tCS] = _ucodesel; p->p_addr->u_pcb.pcb_flags = 0; /* no fp at all */ load_cr0(rcr0() | CR0_TS); /* start emulating */ #if NNPX > 0 npxinit(__INITIAL_NPXCW__); #endif /* NNPX > 0 */ } static int sysctl_machdep_adjkerntz SYSCTL_HANDLER_ARGS { int error; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) resettodr(); return (error); } SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set, 0, ""); SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, CTLFLAG_RD, &bootinfo, bootinfo, ""); /* * Initialize 386 and configure to run kernel */ /* * Initialize segments & interrupt table */ int currentldt; int _default_ldt; union descriptor gdt[NGDT]; /* global descriptor table */ struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */ union descriptor ldt[NLDT]; /* local descriptor table */ static struct i386tss dblfault_tss; static char dblfault_stack[PAGE_SIZE]; extern struct user *proc0paddr; /* software prototypes -- in more palatable form */ struct soft_segment_descriptor gdt_segs[] = { /* GNULL_SEL 0 Null Descriptor */ { 0x0, /* segment base address */ 0x0, /* length */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GCODE_SEL 1 Code Descriptor for kernel */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GDATA_SEL 2 Data Descriptor for kernel */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMRWA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GLDT_SEL 3 LDT Descriptor */ { (int) ldt, /* segment base address */ sizeof(ldt)-1, /* length - all address space */ SDT_SYSLDT, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GTGATE_SEL 4 Null Descriptor - Placeholder */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GPANIC_SEL 5 Panic Tss Descriptor */ { (int) &dblfault_tss, /* segment base address */ sizeof(struct i386tss)-1,/* length - all address space */ SDT_SYS386TSS, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GPROC0_SEL 6 Proc 0 Tss Descriptor */ { (int) kstack, /* segment base address */ sizeof(struct i386tss)-1,/* length - all address space */ SDT_SYS386TSS, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GUSERLDT_SEL 7 User LDT Descriptor per process */ { (int) ldt, /* segment base address */ (512 * sizeof(union descriptor)-1), /* length */ SDT_SYSLDT, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* unused - default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* GAPMCODE32_SEL 8 APM BIOS 32-bit interface (32bit Code) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GAPMCODE16_SEL 9 APM BIOS 32-bit interface (16bit Code) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMERA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* GAPMDATA_SEL 10 APM BIOS 32-bit interface (Data) */ { 0, /* segment base address (overwritten by APM) */ 0xfffff, /* length */ SDT_MEMRWA, /* segment type */ 0, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, }; static struct soft_segment_descriptor ldt_segs[] = { /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Null Descriptor - overwritten by call gate */ { 0x0, /* segment base address */ 0x0, /* length - all address space */ 0, /* segment type */ 0, /* segment descriptor priority level */ 0, /* segment descriptor present */ 0, 0, 0, /* default 32 vs 16 bit size */ 0 /* limit granularity (byte/page units)*/ }, /* Code Descriptor for user */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMERA, /* segment type */ SEL_UPL, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, /* Data Descriptor for user */ { 0x0, /* segment base address */ 0xfffff, /* length - all address space */ SDT_MEMRWA, /* segment type */ SEL_UPL, /* segment descriptor priority level */ 1, /* segment descriptor present */ 0, 0, 1, /* default 32 vs 16 bit size */ 1 /* limit granularity (byte/page units)*/ }, }; void setidt(idx, func, typ, dpl, selec) int idx; inthand_t *func; int typ; int dpl; int selec; { struct gate_descriptor *ip = idt + idx; ip->gd_looffset = (int)func; ip->gd_selector = selec; ip->gd_stkcpy = 0; ip->gd_xx = 0; ip->gd_type = typ; ip->gd_dpl = dpl; ip->gd_p = 1; ip->gd_hioffset = ((int)func)>>16 ; } #define IDTVEC(name) __CONCAT(X,name) extern inthand_t IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), - IDTVEC(syscall); - -#if defined(COMPAT_LINUX) || defined(LINUX) -extern inthand_t - IDTVEC(linux_syscall); -#endif + IDTVEC(syscall), IDTVEC(int0x80_syscall); void sdtossd(sd, ssd) struct segment_descriptor *sd; struct soft_segment_descriptor *ssd; { ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; ssd->ssd_type = sd->sd_type; ssd->ssd_dpl = sd->sd_dpl; ssd->ssd_p = sd->sd_p; ssd->ssd_def32 = sd->sd_def32; ssd->ssd_gran = sd->sd_gran; } void init386(first) int first; { int x; unsigned biosbasemem, biosextmem; struct gate_descriptor *gdp; int gsel_tss; /* table descriptors - used to load tables by microp */ struct region_descriptor r_gdt, r_idt; int pagesinbase, pagesinext; int target_page, pa_indx; proc0.p_addr = proc0paddr; /* * Initialize the console before we print anything out. */ cninit(); /* * make gdt memory segments, the code segment goes up to end of the * page with etext in it, the data segment goes to the end of * the address space */ /* * XXX text protection is temporarily (?) disabled. The limit was * i386_btop(round_page(etext)) - 1. */ gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1; gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1; for (x = 0; x < NGDT; x++) ssdtosd(&gdt_segs[x], &gdt[x].sd); /* make ldt memory segments */ /* * The data segment limit must not cover the user area because we * don't want the user area to be writable in copyout() etc. (page * level protection is lost in kernel mode on 386's). Also, we * don't want the user area to be writable directly (page level * protection of the user area is not available on 486's with * CR0_WP set, because there is no user-read/kernel-write mode). * * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it * should be spelled ...MAX_USER... */ #define VM_END_USER_RW_ADDRESS VM_MAXUSER_ADDRESS /* * The code segment limit has to cover the user area until we move * the signal trampoline out of the user area. This is safe because * the code segment cannot be written to directly. */ #define VM_END_USER_R_ADDRESS (VM_END_USER_RW_ADDRESS + UPAGES * NBPG) ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1; ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1; /* Note. eventually want private ldts per process */ for (x = 0; x < NLDT; x++) ssdtosd(&ldt_segs[x], &ldt[x].sd); /* exceptions */ for (x = 0; x < NIDT; x++) setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL)); setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); -#if defined(COMPAT_LINUX) || defined(LINUX) - setidt(0x80, &IDTVEC(linux_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); -#endif + setidt(0x80, &IDTVEC(int0x80_syscall), + SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); #include "isa.h" #if NISA >0 isa_defaultirq(); #endif rand_initialize(); r_gdt.rd_limit = sizeof(gdt) - 1; r_gdt.rd_base = (int) gdt; lgdt(&r_gdt); r_idt.rd_limit = sizeof(idt) - 1; r_idt.rd_base = (int) idt; lidt(&r_idt); _default_ldt = GSEL(GLDT_SEL, SEL_KPL); lldt(_default_ldt); currentldt = _default_ldt; #ifdef DDB kdb_init(); if (boothowto & RB_KDB) Debugger("Boot flags requested debugger"); #endif /* Use BIOS values stored in RTC CMOS RAM, since probing * breaks certain 386 AT relics. */ biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); /* * Print a warning if the official BIOS interface disagrees * with the hackish interface used above. Eventually only * the official interface should be used. */ if (bootinfo.bi_memsizes_valid) { if (bootinfo.bi_basemem != biosbasemem) printf("BIOS basemem (%ldK) != RTC basemem (%dK)\n", bootinfo.bi_basemem, biosbasemem); if (bootinfo.bi_extmem != biosextmem) printf("BIOS extmem (%ldK) != RTC extmem (%dK)\n", bootinfo.bi_extmem, biosextmem); } /* * If BIOS tells us that it has more than 640k in the basemem, * don't believe it - set it to 640k. */ if (biosbasemem > 640) biosbasemem = 640; /* * Some 386 machines might give us a bogus number for extended * mem. If this happens, stop now. */ #ifndef LARGEMEM if (biosextmem > 65536) { panic("extended memory beyond limit of 64MB"); /* NOTREACHED */ } #endif pagesinbase = biosbasemem * 1024 / NBPG; pagesinext = biosextmem * 1024 / NBPG; /* * Special hack for chipsets that still remap the 384k hole when * there's 16MB of memory - this really confuses people that * are trying to use bus mastering ISA controllers with the * "16MB limit"; they only have 16MB, but the remapping puts * them beyond the limit. */ /* * If extended memory is between 15-16MB (16-17MB phys address range), * chop it to 15MB. */ if ((pagesinext > 3840) && (pagesinext < 4096)) pagesinext = 3840; /* * Maxmem isn't the "maximum memory", it's one larger than the * highest page of of the physical address space. It */ Maxmem = pagesinext + 0x100000/PAGE_SIZE; #ifdef MAXMEM Maxmem = MAXMEM/4; #endif /* call pmap initialization to make new kernel address space */ pmap_bootstrap (first, 0); /* * Size up each available chunk of physical memory. */ /* * We currently don't bother testing base memory. * XXX ...but we probably should. */ pa_indx = 0; badpages = 0; if (pagesinbase > 1) { phys_avail[pa_indx++] = PAGE_SIZE; /* skip first page of memory */ phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */ physmem = pagesinbase - 1; } else { /* point at first chunk end */ pa_indx++; } for (target_page = avail_start; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) { int tmp, page_bad = FALSE; /* * map page into kernel: valid, read/write, non-cacheable */ *(int *)CMAP1 = PG_V | PG_KW | PG_N | target_page; pmap_update(); tmp = *(int *)CADDR1; /* * Test for alternating 1's and 0's */ *(volatile int *)CADDR1 = 0xaaaaaaaa; if (*(volatile int *)CADDR1 != 0xaaaaaaaa) { page_bad = TRUE; } /* * Test for alternating 0's and 1's */ *(volatile int *)CADDR1 = 0x55555555; if (*(volatile int *)CADDR1 != 0x55555555) { page_bad = TRUE; } /* * Test for all 1's */ *(volatile int *)CADDR1 = 0xffffffff; if (*(volatile int *)CADDR1 != 0xffffffff) { page_bad = TRUE; } /* * Test for all 0's */ *(volatile int *)CADDR1 = 0x0; if (*(volatile int *)CADDR1 != 0x0) { /* * test of page failed */ page_bad = TRUE; } /* * Restore original value. */ *(int *)CADDR1 = tmp; /* * Adjust array of valid/good pages. */ if (page_bad == FALSE) { /* * If this good page is a continuation of the * previous set of good pages, then just increase * the end pointer. Otherwise start a new chunk. * Note that "end" points one higher than end, * making the range >= start and < end. */ if (phys_avail[pa_indx] == target_page) { phys_avail[pa_indx] += PAGE_SIZE; } else { pa_indx++; if (pa_indx == PHYS_AVAIL_ARRAY_END) { printf("Too many holes in the physical address space, giving up\n"); pa_indx--; break; } phys_avail[pa_indx++] = target_page; /* start */ phys_avail[pa_indx] = target_page + PAGE_SIZE; /* end */ } physmem++; } else { badpages++; page_bad = FALSE; } } *(int *)CMAP1 = 0; pmap_update(); /* * XXX * The last chunk must contain at least one page plus the message * buffer to avoid complicating other code (message buffer address * calculation, etc.). */ while (phys_avail[pa_indx - 1] + PAGE_SIZE + round_page(sizeof(struct msgbuf)) >= phys_avail[pa_indx]) { physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); phys_avail[pa_indx--] = 0; phys_avail[pa_indx--] = 0; } Maxmem = atop(phys_avail[pa_indx]); /* Trim off space for the message buffer. */ phys_avail[pa_indx] -= round_page(sizeof(struct msgbuf)); avail_end = phys_avail[pa_indx]; /* now running on new page tables, configured,and u/iom is accessible */ /* make a initial tss so microp can get interrupt stack on syscall! */ proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*NBPG; proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 = dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)]; dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 = dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL); dblfault_tss.tss_cr3 = IdlePTD; dblfault_tss.tss_eip = (int) dblfault_handler; dblfault_tss.tss_eflags = PSL_KERNEL; dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_fs = dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL); dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); ((struct i386tss *)gdt_segs[GPROC0_SEL].ssd_base)->tss_ioopt = (sizeof(struct i386tss))<<16; ltr(gsel_tss); /* make a call gate to reenter kernel with */ gdp = &ldt[LSYS5CALLS_SEL].gd; x = (int) &IDTVEC(syscall); gdp->gd_looffset = x++; gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); gdp->gd_stkcpy = 1; gdp->gd_type = SDT_SYS386CGT; gdp->gd_dpl = SEL_UPL; gdp->gd_p = 1; gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; /* transfer to user mode */ _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); _udatasel = LSEL(LUDATA_SEL, SEL_UPL); /* setup proc 0's pcb */ - bcopy(&sigcode, proc0.p_addr->u_pcb.pcb_sigc, szsigcode); proc0.p_addr->u_pcb.pcb_flags = 0; proc0.p_addr->u_pcb.pcb_ptd = IdlePTD; } /* * The registers are in the frame; the frame is in the user area of * the process in question; when the process is active, the registers * are in "the kernel stack"; when it's not, they're still there, but * things get flipped around. So, since p->p_md.md_regs is the whole address * of the register set, take its offset from the kernel stack, and * index into the user block. Don't you just *love* virtual memory? * (I'm starting to think seymour is right...) */ #define TF_REGP(p) ((struct trapframe *) \ ((char *)(p)->p_addr \ + ((char *)(p)->p_md.md_regs - kstack))) int ptrace_set_pc(p, addr) struct proc *p; unsigned int addr; { TF_REGP(p)->tf_eip = addr; return (0); } int ptrace_single_step(p) struct proc *p; { TF_REGP(p)->tf_eflags |= PSL_T; return (0); } int ptrace_write_u(p, off, data) struct proc *p; vm_offset_t off; int data; { struct trapframe frame_copy; vm_offset_t min; struct trapframe *tp; /* * Privileged kernel state is scattered all over the user area. * Only allow write access to parts of regs and to fpregs. */ min = (char *)p->p_md.md_regs - kstack; if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) { tp = TF_REGP(p); frame_copy = *tp; *(int *)((char *)&frame_copy + (off - min)) = data; if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) || !CS_SECURE(frame_copy.tf_cs)) return (EINVAL); *(int*)((char *)p->p_addr + off) = data; return (0); } min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu); if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) { *(int*)((char *)p->p_addr + off) = data; return (0); } return (EFAULT); } int fill_regs(p, regs) struct proc *p; struct reg *regs; { struct trapframe *tp; tp = TF_REGP(p); regs->r_es = tp->tf_es; regs->r_ds = tp->tf_ds; regs->r_edi = tp->tf_edi; regs->r_esi = tp->tf_esi; regs->r_ebp = tp->tf_ebp; regs->r_ebx = tp->tf_ebx; regs->r_edx = tp->tf_edx; regs->r_ecx = tp->tf_ecx; regs->r_eax = tp->tf_eax; regs->r_eip = tp->tf_eip; regs->r_cs = tp->tf_cs; regs->r_eflags = tp->tf_eflags; regs->r_esp = tp->tf_esp; regs->r_ss = tp->tf_ss; return (0); } int set_regs(p, regs) struct proc *p; struct reg *regs; { struct trapframe *tp; tp = TF_REGP(p); if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) || !CS_SECURE(regs->r_cs)) return (EINVAL); tp->tf_es = regs->r_es; tp->tf_ds = regs->r_ds; tp->tf_edi = regs->r_edi; tp->tf_esi = regs->r_esi; tp->tf_ebp = regs->r_ebp; tp->tf_ebx = regs->r_ebx; tp->tf_edx = regs->r_edx; tp->tf_ecx = regs->r_ecx; tp->tf_eax = regs->r_eax; tp->tf_eip = regs->r_eip; tp->tf_cs = regs->r_cs; tp->tf_eflags = regs->r_eflags; tp->tf_esp = regs->r_esp; tp->tf_ss = regs->r_ss; return (0); } #ifndef DDB void Debugger(const char *msg) { printf("Debugger(\"%s\") called.\n", msg); } #endif /* no DDB */ #include #define b_cylin b_resid /* * Determine the size of the transfer, and make sure it is * within the boundaries of the partition. Adjust transfer * if needed, and signal errors or early completion. */ int bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel) { struct partition *p = lp->d_partitions + dkpart(bp->b_dev); int labelsect = lp->d_partitions[0].p_offset; int maxsz = p->p_size, sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; /* overwriting disk label ? */ /* XXX should also protect bootstrap in first 8K */ if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && #if LABELSECTOR != 0 bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && #endif (bp->b_flags & B_READ) == 0 && wlabel == 0) { bp->b_error = EROFS; goto bad; } #if defined(DOSBBSECTOR) && defined(notyet) /* overwriting master boot record? */ if (bp->b_blkno + p->p_offset <= DOSBBSECTOR && (bp->b_flags & B_READ) == 0 && wlabel == 0) { bp->b_error = EROFS; goto bad; } #endif /* beyond partition? */ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { /* if exactly at end of disk, return an EOF */ if (bp->b_blkno == maxsz) { bp->b_resid = bp->b_bcount; return(0); } /* or truncate if part of it fits */ sz = maxsz - bp->b_blkno; if (sz <= 0) { bp->b_error = EINVAL; goto bad; } bp->b_bcount = sz << DEV_BSHIFT; } /* calculate cylinder for disksort to order transfers with */ bp->b_pblkno = bp->b_blkno + p->p_offset; bp->b_cylin = bp->b_pblkno / lp->d_secpercyl; return(1); bad: bp->b_flags |= B_ERROR; return(-1); } int disk_externalize(int drive, struct sysctl_req *req) { return SYSCTL_OUT(req, &drive, sizeof drive); } diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index e270a58dbf16..8ecc51166c61 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -1,1063 +1,972 @@ /*- * Copyright (C) 1994, David Greenman * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the University of Utah, and William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.71 1996/01/19 03:57:42 dyson Exp $ + * $Id: trap.c,v 1.72 1996/02/25 03:02:46 dyson Exp $ */ /* * 386 Trap and System call handling */ #include "opt_ktrace.h" #include "opt_ddb.h" #include #include #include #include #include #include #include #include #include #ifdef KTRACE #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef POWERFAIL_NMI # include # include #endif #include "isa.h" #include "npx.h" int (*pmath_emulate) __P((struct trapframe *)); extern void trap __P((struct trapframe frame)); extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); -extern void linux_syscall __P((struct trapframe frame)); static int trap_pfault __P((struct trapframe *, int)); static void trap_fatal __P((struct trapframe *)); void dblfault_handler __P((void)); extern inthand_t IDTVEC(syscall); #define MAX_TRAP_MSG 27 static char *trap_msg[] = { "", /* 0 unused */ "privileged instruction fault", /* 1 T_PRIVINFLT */ "", /* 2 unused */ "breakpoint instruction fault", /* 3 T_BPTFLT */ "", /* 4 unused */ "", /* 5 unused */ "arithmetic trap", /* 6 T_ARITHTRAP */ "system forced exception", /* 7 T_ASTFLT */ "", /* 8 unused */ "general protection fault", /* 9 T_PROTFLT */ "trace trap", /* 10 T_TRCTRAP */ "", /* 11 unused */ "page fault", /* 12 T_PAGEFLT */ "", /* 13 unused */ "alignment fault", /* 14 T_ALIGNFLT */ "", /* 15 unused */ "", /* 16 unused */ "", /* 17 unused */ "integer divide fault", /* 18 T_DIVIDE */ "non-maskable interrupt trap", /* 19 T_NMI */ "overflow trap", /* 20 T_OFLOW */ "FPU bounds check fault", /* 21 T_BOUND */ "FPU device not available", /* 22 T_DNA */ "double fault", /* 23 T_DOUBLEFLT */ "FPU operand fetch fault", /* 24 T_FPOPFLT */ "invalid TSS fault", /* 25 T_TSSFLT */ "segment not present fault", /* 26 T_SEGNPFLT */ "stack fault", /* 27 T_STKFLT */ }; static void userret __P((struct proc *p, struct trapframe *frame, u_quad_t oticks)); static inline void userret(p, frame, oticks) struct proc *p; struct trapframe *frame; u_quad_t oticks; { int sig, s; while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; if (want_resched) { /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we setrunqueue ourselves but before we * mi_switch()'ed, we might not be on the queue indicated by * our priority. */ s = splclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); splx(s); while ((sig = CURSIG(p)) != 0) postsig(sig); } /* * Charge system time if profiling. */ if (p->p_flag & P_PROFIL) { u_quad_t ticks = p->p_sticks - oticks; if (ticks) { #ifdef PROFTIMER extern int profscale; addupc(frame->tf_eip, &p->p_stats->p_prof, ticks * profscale); #else addupc(frame->tf_eip, &p->p_stats->p_prof, ticks); #endif } } curpriority = p->p_priority; } /* * Exception, fault, and trap interface to the FreeBSD kernel. * This common code is called from assembly language IDT gate entry * routines that prepare a suitable stack frame, and restore this * frame after the exception has been processed. */ void trap(frame) struct trapframe frame; { struct proc *p = curproc; u_quad_t sticks = 0; int i = 0, ucode = 0, type, code; #ifdef DEBUG u_long eva; #endif type = frame.tf_trapno; code = frame.tf_err; if (ISPL(frame.tf_cs) == SEL_UPL) { /* user trap */ sticks = p->p_sticks; p->p_md.md_regs = (int *)&frame; switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ ucode = type; i = SIGILL; break; case T_BPTFLT: /* bpt instruction fault */ case T_TRCTRAP: /* trace trap */ frame.tf_eflags &= ~PSL_T; i = SIGTRAP; break; case T_ARITHTRAP: /* arithmetic trap */ ucode = code; i = SIGFPE; break; case T_ASTFLT: /* Allow process switch */ astoff(); cnt.v_soft++; if (p->p_flag & P_OWEUPC) { addupc(frame.tf_eip, &p->p_stats->p_prof, 1); p->p_flag &= ~P_OWEUPC; } goto out; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ case T_STKFLT: /* stack fault */ case T_TSSFLT: /* invalid TSS fault */ case T_DOUBLEFLT: /* double fault */ default: ucode = code + BUS_SEGM_FAULT ; i = SIGBUS; break; case T_PAGEFLT: /* page fault */ i = trap_pfault(&frame, TRUE); if (i == -1) return; if (i == 0) goto out; ucode = T_PAGEFLT; break; case T_DIVIDE: /* integer divide fault */ ucode = FPE_INTDIV_TRAP; i = SIGFPE; break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI goto handle_powerfail; #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; panic("NMI indicates hardware failure"); #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ case T_OFLOW: /* integer overflow fault */ ucode = FPE_INTOVF_TRAP; i = SIGFPE; break; case T_BOUND: /* bounds check fault */ ucode = FPE_SUBRNG_TRAP; i = SIGFPE; break; case T_DNA: #if NNPX > 0 /* if a transparent fault (due to context switch "late") */ if (npxdna()) return; #endif /* NNPX > 0 */ if (!pmath_emulate) { i = SIGFPE; ucode = FPE_FPU_NP_TRAP; break; } i = (*pmath_emulate)(&frame); if (i == 0) { if (!(frame.tf_eflags & PSL_T)) return; frame.tf_eflags &= ~PSL_T; i = SIGTRAP; } /* else ucode = emulator_only_knows() XXX */ break; case T_FPOPFLT: /* FPU operand fetch fault */ ucode = T_FPOPFLT; i = SIGILL; break; } } else { /* kernel trap */ switch (type) { case T_PAGEFLT: /* page fault */ (void) trap_pfault(&frame, FALSE); return; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ /* * Invalid segment selectors and out of bounds * %eip's and %esp's can be set up in user mode. * This causes a fault in kernel mode when the * kernel tries to return to user mode. We want * to get this fault so that we can fix the * problem here and not have to check all the * selectors and pointers when the user changes * them. */ #define MAYBE_DORETI_FAULT(where, whereto) \ do { \ if (frame.tf_eip == (int)where) { \ frame.tf_eip = (int)whereto; \ return; \ } \ } while (0) if (intr_nesting_level == 0) { MAYBE_DORETI_FAULT(doreti_iret, doreti_iret_fault); MAYBE_DORETI_FAULT(doreti_popl_ds, doreti_popl_ds_fault); MAYBE_DORETI_FAULT(doreti_popl_es, doreti_popl_es_fault); } if (curpcb && curpcb->pcb_onfault) { frame.tf_eip = (int)curpcb->pcb_onfault; return; } break; case T_TSSFLT: /* * PSL_NT can be set in user mode and isn't cleared * automatically when the kernel is entered. This * causes a TSS fault when the kernel attempts to * `iret' because the TSS link is uninitialized. We * want to get this fault so that we can fix the * problem here and not every time the kernel is * entered. */ if (frame.tf_eflags & PSL_NT) { frame.tf_eflags &= ~PSL_NT; return; } break; case T_TRCTRAP: /* trace trap */ if (frame.tf_eip == (int)IDTVEC(syscall)) { /* * We've just entered system mode via the * syscall lcall. Continue single stepping * silently until the syscall handler has * saved the flags. */ return; } if (frame.tf_eip == (int)IDTVEC(syscall) + 1) { /* * The syscall handler has now saved the * flags. Stop single stepping it. */ frame.tf_eflags &= ~PSL_T; return; } /* * Fall through. */ case T_BPTFLT: /* * If DDB is enabled, let it handle the debugger trap. * Otherwise, debugger traps "can't happen". */ #ifdef DDB if (kdb_trap (type, 0, &frame)) return; #endif break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI #ifndef TIMER_FREQ # define TIMER_FREQ 1193182 #endif handle_powerfail: { static unsigned lastalert = 0; if(time.tv_sec - lastalert > 10) { log(LOG_WARNING, "NMI: power fail\n"); sysbeep(TIMER_FREQ/880, hz); lastalert = time.tv_sec; } return; } #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; /* FALL THROUGH */ #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ } trap_fatal(&frame); return; } trapsignal(p, i, ucode); #ifdef DEBUG eva = rcr2(); if (type <= MAX_TRAP_MSG) { uprintf("fatal process exception: %s", trap_msg[type]); if ((type == T_PAGEFLT) || (type == T_PROTFLT)) uprintf(", fault VA = 0x%x", eva); uprintf("\n"); } #endif out: userret(p, &frame, sticks); } #ifdef notyet /* * This version doesn't allow a page fault to user space while * in the kernel. The rest of the kernel needs to be made "safe" * before this can be used. I think the only things remaining * to be made safe are the iBCS2 code and the process tracing/ * debugging code. */ static int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va < VM_MIN_KERNEL_ADDRESS) { vm_offset_t v; vm_page_t mpte; if (p == NULL || (!usermode && va < VM_MAXUSER_ADDRESS && (curpcb == NULL || curpcb->pcb_onfault == NULL))) { trap_fatal(frame); return (-1); } /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(kernel_map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } #endif int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va >= KERNBASE) { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; map = kernel_map; } else { /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ if (p != NULL) vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; } if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; if (map != kernel_map) { vm_offset_t v; vm_page_t mpte; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } static void trap_fatal(frame) struct trapframe *frame; { int code, type, eva; struct soft_segment_descriptor softseg; code = frame->tf_err; type = frame->tf_trapno; eva = rcr2(); sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); if (type <= MAX_TRAP_MSG) printf("\n\nFatal trap %d: %s while in %s mode\n", type, trap_msg[type], ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); if (type == T_PAGEFLT) { printf("fault virtual address = 0x%x\n", eva); printf("fault code = %s %s, %s\n", code & PGEX_U ? "user" : "supervisor", code & PGEX_W ? "write" : "read", code & PGEX_P ? "protection violation" : "page not present"); } printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); printf(" = DPL %d, pres %d, def32 %d, gran %d\n", softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran); printf("processor eflags = "); if (frame->tf_eflags & PSL_T) printf("trace/trap, "); if (frame->tf_eflags & PSL_I) printf("interrupt enabled, "); if (frame->tf_eflags & PSL_NT) printf("nested task, "); if (frame->tf_eflags & PSL_RF) printf("resume, "); if (frame->tf_eflags & PSL_VM) printf("vm86, "); printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); printf("current process = "); if (curproc) { printf("%lu (%s)\n", (u_long)curproc->p_pid, curproc->p_comm ? curproc->p_comm : ""); } else { printf("Idle\n"); } printf("interrupt mask = "); if ((cpl & net_imask) == net_imask) printf("net "); if ((cpl & tty_imask) == tty_imask) printf("tty "); if ((cpl & bio_imask) == bio_imask) printf("bio "); if (cpl == 0) printf("none"); printf("\n"); #ifdef KDB if (kdb_trap(&psl)) return; #endif #ifdef DDB if (kdb_trap (type, 0, frame)) return; #endif if (type <= MAX_TRAP_MSG) panic(trap_msg[type]); else panic("unknown/reserved trap"); } /* * Double fault handler. Called when a fault occurs while writing * a frame for a trap/exception onto the stack. This usually occurs * when the stack overflows (such is the case with infinite recursion, * for example). * * XXX Note that the current PTD gets replaced by IdlePTD when the * task switch occurs. This means that the stack that was active at * the time of the double fault is not available at unless * the machine was idle when the double fault occurred. The downside * of this is that "trace " in ddb won't work. */ void dblfault_handler() { struct pcb *pcb = curpcb; if (pcb != NULL) { printf("\nFatal double fault:\n"); printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip); printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp); printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp); } panic("double fault"); } /* * Compensate for 386 brain damage (missing URKR). * This is a little simpler than the pagefault handler in trap() because * it the page tables have already been faulted in and high addresses * are thrown out early for other reasons. */ int trapwrite(addr) unsigned addr; { struct proc *p; vm_offset_t va, v; struct vmspace *vm; int rv; va = trunc_page((vm_offset_t)addr); /* * XXX - MAX is END. Changed > to >= for temp. fix. */ if (va >= VM_MAXUSER_ADDRESS) return (1); p = curproc; vm = p->p_vmspace; ++p->p_lock; if ((caddr_t)va >= vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { --p->p_lock; return (1); } } v = trunc_page(vtopte(va)); /* * wire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE); } /* * fault the data page */ rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); /* * unwire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE); } --p->p_lock; if (rv != KERN_SUCCESS) return 1; return (0); } /* * System call request from POSIX system call gate interface to kernel. * Like trap(), argument is call by reference. */ void syscall(frame) struct trapframe frame; { caddr_t params; int i; struct sysent *callp; struct proc *p = curproc; u_quad_t sticks; int error; int args[8], rval[2]; u_int code; sticks = p->p_sticks; if (ISPL(frame.tf_cs) != SEL_UPL) panic("syscall"); p->p_md.md_regs = (int *)&frame; params = (caddr_t)frame.tf_esp + sizeof(int); code = frame.tf_eax; - /* - * Need to check if this is a 32 bit or 64 bit syscall. - */ - if (code == SYS_syscall) { - /* - * Code is first argument, followed by actual args. - */ - code = fuword(params); - params += sizeof(int); - } else if (code == SYS___syscall) { + if (p->p_sysent->sv_prepsyscall) { + (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms); + } else { /* - * Like syscall, but code is a quad, so as to maintain - * quad alignment for the rest of the arguments. + * Need to check if this is a 32 bit or 64 bit syscall. */ - code = fuword(params); - params += sizeof(quad_t); + if (code == SYS_syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = fuword(params); + params += sizeof(int); + } else if (code == SYS___syscall) { + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + code = fuword(params); + params += sizeof(quad_t); + } } if (p->p_sysent->sv_mask) code &= p->p_sysent->sv_mask; if (code >= p->p_sysent->sv_size) callp = &p->p_sysent->sv_table[0]; else callp = &p->p_sysent->sv_table[code]; - if ((i = callp->sy_narg * sizeof(int)) && + if (params && (i = callp->sy_narg * sizeof(int)) && (error = copyin(params, (caddr_t)args, (u_int)i))) { #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif goto bad; } #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif rval[0] = 0; rval[1] = frame.tf_edx; error = (*callp->sy_call)(p, args, rval); switch (error) { case 0: /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; frame.tf_eax = rval[0]; frame.tf_edx = rval[1]; frame.tf_eflags &= ~PSL_C; break; case ERESTART: /* - * Reconstruct pc, assuming lcall $X,y is 7 bytes. + * Reconstruct pc, assuming lcall $X,y is 7 bytes, + * int 0x80 is 2 bytes. We saved this in tf_err. */ - frame.tf_eip -= 7; + frame.tf_eip -= frame.tf_err; break; case EJUSTRETURN: break; default: bad: if (p->p_sysent->sv_errsize) if (error >= p->p_sysent->sv_errsize) error = -1; /* XXX */ else error = p->p_sysent->sv_errtbl[error]; frame.tf_eax = error; frame.tf_eflags |= PSL_C; break; } if (frame.tf_eflags & PSL_T) { /* Traced syscall. */ frame.tf_eflags &= ~PSL_T; trapsignal(p, SIGTRAP, 0); } userret(p, &frame, sticks); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } - -#if defined(COMPAT_LINUX) || defined(LINUX) -void -linux_syscall(frame) - struct trapframe frame; -{ - struct proc *p = curproc; - struct sysent *callp; - u_quad_t sticks; - int error; - int rval[2]; - u_int code; - struct linux_syscall_args { - int arg1; - int arg2; - int arg3; - int arg4; - int arg5; - } args; - - args.arg1 = frame.tf_ebx; - args.arg2 = frame.tf_ecx; - args.arg3 = frame.tf_edx; - args.arg4 = frame.tf_esi; - args.arg5 = frame.tf_edi; - - sticks = p->p_sticks; - if (ISPL(frame.tf_cs) != SEL_UPL) - panic("linux syscall"); - - p->p_md.md_regs = (int *)&frame; - code = frame.tf_eax; - - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; - - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, callp->sy_narg, (int *)&args); -#endif - - rval[0] = 0; - - error = (*callp->sy_call)(p, &args, rval); - - switch (error) { - - case 0: - /* - * Reinitialize proc pointer `p' as it may be different - * if this is a child returning from fork syscall. - */ - p = curproc; - frame.tf_eax = rval[0]; - frame.tf_eflags &= ~PSL_C; - break; - - case ERESTART: - /* Reconstruct pc, subtract size of int 0x80 */ - frame.tf_eip -= 2; - break; - - case EJUSTRETURN: - break; - - default: - if (p->p_sysent->sv_errsize) - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; - frame.tf_eax = -error; - frame.tf_eflags |= PSL_C; - break; - } - - if (frame.tf_eflags & PSL_T) { - /* Traced syscall. */ - frame.tf_eflags &= ~PSL_T; - trapsignal(p, SIGTRAP, 0); - } - - userret(p, &frame, sticks); - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, error, rval[0]); -#endif -} -#endif /* COMPAT_LINUX || LINUX */ diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c index 160409ec3287..489047321f5a 100644 --- a/sys/i386/ibcs2/ibcs2_sysvec.c +++ b/sys/i386/ibcs2/ibcs2_sysvec.c @@ -1,50 +1,56 @@ /* * Copyright (c) 1995 Steven Wallace * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Steven Wallace. * 4. 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. * - * $Id$ + * $Id: ibcs2_sysvec.c,v 1.1 1995/10/10 07:59:11 swallace Exp $ */ #include #include #include extern int bsd_to_ibcs2_sig[]; extern int bsd_to_ibcs2_errno[]; extern struct sysent ibcs2_sysent[IBCS2_SYS_MAXSYSCALL]; +extern int szsigcode; +extern char sigcode[]; struct sysentvec ibcs2_svr3_sysvec = { sizeof (ibcs2_sysent) / sizeof (ibcs2_sysent[0]), ibcs2_sysent, 0xFF, NSIG, bsd_to_ibcs2_sig, ELAST, bsd_to_ibcs2_errno, - 0 + 0, /* fixup */ + 0, /* sendsig, ignore */ + sigcode, /* use generic trampoline */ + &szsigcode, /* use generic trampoline size */ + 0 /* prepsyscall */ }; diff --git a/sys/i386/ibcs2/ibcs2_util.h b/sys/i386/ibcs2/ibcs2_util.h index 67f859b3c9b4..af972b650eed 100644 --- a/sys/i386/ibcs2/ibcs2_util.h +++ b/sys/i386/ibcs2/ibcs2_util.h @@ -1,91 +1,93 @@ /* * 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.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 */ /* * This file is pretty much the same as Christos' svr4_util.h * (for now). */ #ifndef _IBCS2_UTIL_H_ #define _IBCS2_UTIL_H_ #include #include #include #include #include #include +#include +#include #ifndef SCARG #define SCARG(p, x) (p)->x #endif static __inline caddr_t stackgap_init(void); static __inline void *stackgap_alloc(caddr_t *, size_t); static __inline caddr_t stackgap_init() { -#define szsigcode ((caddr_t)(esigcode - sigcode)) - return (caddr_t)(ALIGN(((caddr_t)PS_STRINGS) - SPARE_USRSPACE)); +#define szsigcode (*(curproc->p_sysent->sv_szsigcode), sizeof(char *)) + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); } static __inline void * stackgap_alloc(sgp, sz) caddr_t *sgp; size_t sz; { void *p = (void *) *sgp; *sgp += ALIGN(sz); return p; } #ifdef DEBUG_IBCS2 #define DPRINTF(a) printf a; #else #define DPRINTF(a) #endif extern const char ibcs2_emul_path[]; int ibcs2_emul_find __P((struct proc *, caddr_t *, const char *, char *, char **, int)); #define CHECKALTEXIST(p, sgp, path) \ ibcs2_emul_find(p, sgp, ibcs2_emul_path, path, &(path), 0) #define CHECKALTCREAT(p, sgp, path) \ ibcs2_emul_find(p, sgp, ibcs2_emul_path, path, &(path), 1) #endif /* !_IBCS2_UTIL_H_ */ diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index 19e282248150..5e280304abdc 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -1,66 +1,66 @@ /*- * Copyright (c) 1995 Bruce D. Evans. * 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. Neither the name of the author nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: md_var.h,v 1.6 1996/01/27 02:33:25 bde Exp $ + * $Id: md_var.h,v 1.7 1996/02/04 21:20:52 davidg Exp $ */ #ifndef _MACHINE_MD_VAR_H_ #define _MACHINE_MD_VAR_H_ /* * Miscellaneous machine-dependent declarations. */ extern int Maxmem; extern u_long cpu_feature; extern u_long cpu_high; extern u_long cpu_id; extern char cpu_vendor[]; extern char etext[]; extern char kstack[]; extern void (*netisrs[32]) __P((void)); extern int nfs_diskless_valid; -extern int sigcode; +extern char sigcode[]; extern int szsigcode; struct proc; struct reg; void cpu_reset __P((void)); void doreti_iret __P((void)) __asm(__STRING(doreti_iret)); void doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault)); void doreti_popl_ds __P((void)) __asm(__STRING(doreti_popl_ds)); void doreti_popl_ds_fault __P((void)) __asm(__STRING(doreti_popl_ds_fault)); void doreti_popl_es __P((void)) __asm(__STRING(doreti_popl_es)); void doreti_popl_es_fault __P((void)) __asm(__STRING(doreti_popl_es_fault)); int fill_regs __P((struct proc *p, struct reg *regs)); void userconfig __P((void)); void vm_bounce_init __P((void)); int vm_page_zero_idle __P((void)); #endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index f8ea0dc06f25..a3f2005e7f45 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -1,86 +1,85 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)pcb.h 5.10 (Berkeley) 5/12/91 - * $Id: pcb.h,v 1.9 1995/08/17 11:30:03 davidg Exp $ + * $Id: pcb.h,v 1.10 1996/01/23 02:39:24 davidg Exp $ */ #ifndef _I386_PCB_H_ #define _I386_PCB_H_ /* * Intel 386 process control block */ #include #include struct pcb { struct i386tss pcb_tss; #define pcb_ksp pcb_tss.tss_esp0 #define pcb_ptd pcb_tss.tss_cr3 #define pcb_cr3 pcb_ptd #define pcb_pc pcb_tss.tss_eip #define pcb_psl pcb_tss.tss_eflags #define pcb_usp pcb_tss.tss_esp #define pcb_fp pcb_tss.tss_ebp #ifdef notyet u_char pcb_iomap[NPORT/sizeof(u_char)]; /* i/o port bitmap */ #endif caddr_t pcb_ldt; /* per process (user) LDT */ int pcb_ldt_len; /* number of LDT entries */ struct save87 pcb_savefpu; /* floating point state for 287/387 */ /* * Software pcb (extension) */ u_char pcb_flags; #define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */ u_char pcb_inl; /* intr_nesting_level at context switch */ caddr_t pcb_onfault; /* copyin/out fault recovery */ - long pcb_sigc[8]; /* XXX signal code trampoline */ }; /* * The pcb is augmented with machine-dependent additional data for * core dumps. For the i386: ??? */ struct md_coredump { }; #ifdef KERNEL extern struct pcb *curpcb; /* our current running pcb */ int savectx __P((struct pcb*)); #endif #endif /* _I386_PCB_H_ */ diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 4319de2f7399..9d6906d659cd 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -1,221 +1,232 @@ /*- * Copyright (c) 1994-1995 Søren Schmidt * All rights reserved. * * Based heavily on /sys/kern/imgact_aout.c which is: * Copyright (c) 1993, David Greenman * * 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: 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include +#include extern int exec_linux_imgact __P((struct image_params *iparams)); int exec_linux_imgact(imgp) struct image_params *imgp; { struct exec *a_out = (struct exec *) imgp->image_header; struct vmspace *vmspace = imgp->proc->p_vmspace; unsigned long vmaddr, virtual_offset, file_offset; unsigned long buffer, bss_size; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) return -1; /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: virtual_offset = 0; file_offset = 1024; break; case 0314: virtual_offset = 4096; file_offset = 0; break; default: 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. */ if (a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || a_out->a_text % NBPG || a_out->a_data % NBPG) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || a_out->a_data+bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ exec_new_vmspace(imgp); /* * Check if file_offset page aligned,. * Currently we cannot handle misalinged file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PGOFSET) { #ifdef DEBUG printf("imgact: Non page aligned binary %d\n", file_offset); #endif /* * Map text+data+bss read/write/execute */ vmaddr = virtual_offset; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data + bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return error; error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, MAP_FILE, (caddr_t) imgp->vp, trunc_page(file_offset)); if (error) return error; error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, a_out->a_text + a_out->a_data); vm_map_remove(kernel_map, buffer, round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) return error; /* * remove write enable on the 'text' part */ error = vm_map_protect(&vmspace->vm_map, vmaddr, a_out->a_text, VM_PROT_EXECUTE|VM_PROT_READ, TRUE); if (error) return error; } else { #ifdef DEBUG printf("imgact: Page aligned binary %d\n", file_offset); #endif /* * Map text+data read/execute */ vmaddr = virtual_offset; error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t)imgp->vp, file_offset); 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 */ error = vm_map_protect(&vmspace->vm_map, vmaddr + a_out->a_text, vmaddr + a_out->a_text + a_out->a_data, VM_PROT_ALL, FALSE); if (error) return (error); /* * Allocate anon demand-zeroed area for uninitialized data */ if (bss_size != 0) { vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, 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; } /* Fill in process VM information */ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t)virtual_offset; vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &linux_sysvec; return (0); } /* * Tell kern_execve.c about it, with a little help from the linker. * Since `const' objects end up in the text segment, TEXT_SET is the * correct directive to use. */ const struct execsw linux_execsw = { exec_linux_imgact, "linux" }; TEXT_SET(execsw_set, linux_execsw); diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index c0fbc0a20fe2..f6bab97e92bb 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -1,429 +1,481 @@ /*- * 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 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. * - * $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_ #define _I386_LINUX_LINUX_H_ typedef unsigned short linux_uid_t; typedef unsigned short linux_gid_t; typedef unsigned short linux_dev_t; typedef unsigned long linux_ino_t; typedef unsigned short linux_mode_t; typedef unsigned short linux_nlink_t; typedef long linux_time_t; typedef long linux_clock_t; typedef char * linux_caddr_t; typedef long linux_off_t; typedef struct { long val[2]; } linux_fsid_t; typedef int linux_pid_t; typedef unsigned long linux_sigset_t; typedef void (*linux_handler_t)(int); typedef struct { void (*sa_handler)(int); linux_sigset_t sa_mask; unsigned long sa_flags; void (*sa_restorer)(void); } 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 /* signal numbers */ #define LINUX_SIGHUP 1 #define LINUX_SIGINT 2 #define LINUX_SIGQUIT 3 #define LINUX_SIGILL 4 #define LINUX_SIGTRAP 5 #define LINUX_SIGABRT 6 #define LINUX_SIGIOT 6 #define LINUX_SIGUNUSED 7 #define LINUX_SIGFPE 8 #define LINUX_SIGKILL 9 #define LINUX_SIGUSR1 10 #define LINUX_SIGSEGV 11 #define LINUX_SIGUSR2 12 #define LINUX_SIGPIPE 13 #define LINUX_SIGALRM 14 #define LINUX_SIGTERM 15 #define LINUX_SIGSTKFLT 16 #define LINUX_SIGCHLD 17 #define LINUX_SIGCONT 18 #define LINUX_SIGSTOP 19 #define LINUX_SIGTSTP 20 #define LINUX_SIGTTIN 21 #define LINUX_SIGTTOU 22 #define LINUX_SIGIO 23 #define LINUX_SIGPOLL LINUX_SIGIO #define LINUX_SIGURG LINUX_SIGIO #define LINUX_SIGXCPU 24 #define LINUX_SIGXFSZ 25 #define LINUX_SIGVTALRM 26 #define LINUX_SIGPROF 27 #define LINUX_SIGWINCH 28 #define LINUX_SIGLOST 29 #define LINUX_SIGPWR 30 #define LINUX_SIGBUS LINUX_SIGUNUSED #define LINUX_NSIG 32 /* sigaction flags */ #define LINUX_SA_NOCLDSTOP 0x00000001 #define LINUX_SA_ONSTACK 0x08000000 #define LINUX_SA_RESTART 0x10000000 #define LINUX_SA_INTERRUPT 0x20000000 #define LINUX_SA_NOMASK 0x40000000 #define LINUX_SA_ONESHOT 0x80000000 /* sigprocmask actions */ #define LINUX_SIG_BLOCK 0 #define LINUX_SIG_UNBLOCK 1 #define LINUX_SIG_SETMASK 2 /* termio commands */ #define LINUX_TCGETS 0x5401 #define LINUX_TCSETS 0x5402 #define LINUX_TCSETSW 0x5403 #define LINUX_TCSETSF 0x5404 #define LINUX_TCGETA 0x5405 #define LINUX_TCSETA 0x5406 #define LINUX_TCSETAW 0x5407 #define LINUX_TCSETAF 0x5408 #define LINUX_TCSBRK 0x5409 #define LINUX_TCXONC 0x540A #define LINUX_TCFLSH 0x540B #define LINUX_TIOCEXCL 0x540C #define LINUX_TIOCNXCL 0x540D #define LINUX_TIOCSCTTY 0x540E #define LINUX_TIOCGPGRP 0x540F #define LINUX_TIOCSPGRP 0x5410 #define LINUX_TIOCOUTQ 0x5411 #define LINUX_TIOCSTI 0x5412 #define LINUX_TIOCGWINSZ 0x5413 #define LINUX_TIOCSWINSZ 0x5414 #define LINUX_TIOCMGET 0x5415 #define LINUX_TIOCMBIS 0x5416 #define LINUX_TIOCMBIC 0x5417 #define LINUX_TIOCMSET 0x5418 #define LINUX_TIOCGSOFTCAR 0x5419 #define LINUX_TIOCSSOFTCAR 0x541A #define LINUX_FIONREAD 0x541B #define LINUX_TIOCINQ FIONREAD #define LINUX_TIOCLINUX 0x541C #define LINUX_TIOCCONS 0x541D #define LINUX_TIOCGSERIAL 0x541E #define LINUX_TIOCSSERIAL 0x541F #define LINUX_TIOCPKT 0x5420 #define LINUX_FIONBIO 0x5421 #define LINUX_TIOCNOTTY 0x5422 #define LINUX_TIOCSETD 0x5423 #define LINUX_TIOCGETD 0x5424 #define LINUX_TCSBRKP 0x5425 #define LINUX_TIOCTTYGSTRUCT 0x5426 #define LINUX_FIONCLEX 0x5450 #define LINUX_FIOCLEX 0x5451 #define LINUX_FIOASYNC 0x5452 #define LINUX_TIOCSERCONFIG 0x5453 #define LINUX_TIOCSERGWILD 0x5454 #define LINUX_TIOCSERSWILD 0x5455 #define LINUX_TIOCGLCKTRMIOS 0x5456 #define LINUX_TIOCSLCKTRMIOS 0x5457 /* line disciplines */ #define LINUX_N_TTY 0 #define LINUX_N_SLIP 1 #define LINUX_N_MOUSE 2 #define LINUX_N_PPP 3 /* Linux termio c_cc values */ #define LINUX_VINTR 0 #define LINUX_VQUIT 1 #define LINUX_VERASE 2 #define LINUX_VKILL 3 #define LINUX_VEOF 4 #define LINUX_VTIME 5 #define LINUX_VMIN 6 #define LINUX_VSWTC 7 #define LINUX_NCC 8 /* Linux termios c_cc values */ #define LINUX_VSTART 8 #define LINUX_VSTOP 9 #define LINUX_VSUSP 10 #define LINUX_VEOL 11 #define LINUX_VREPRINT 12 #define LINUX_VDISCARD 13 #define LINUX_VWERASE 14 #define LINUX_VLNEXT 15 #define LINUX_VEOL2 16 #define LINUX_NCCS 17 /* Linux c_iflag masks */ #define LINUX_IGNBRK 0x0000001 #define LINUX_BRKINT 0x0000002 #define LINUX_IGNPAR 0x0000004 #define LINUX_PARMRK 0x0000008 #define LINUX_INPCK 0x0000010 #define LINUX_ISTRIP 0x0000020 #define LINUX_INLCR 0x0000040 #define LINUX_IGNCR 0x0000080 #define LINUX_ICRNL 0x0000100 #define LINUX_IUCLC 0x0000200 #define LINUX_IXON 0x0000400 #define LINUX_IXANY 0x0000800 #define LINUX_IXOFF 0x0001000 #define LINUX_IMAXBEL 0x0002000 /* Linux c_oflag masks */ #define LINUX_OPOST 0x0000001 #define LINUX_OLCUC 0x0000002 #define LINUX_ONLCR 0x0000004 #define LINUX_OCRNL 0x0000008 #define LINUX_ONOCR 0x0000010 #define LINUX_ONLRET 0x0000020 #define LINUX_OFILL 0x0000040 #define LINUX_OFDEL 0x0000080 #define LINUX_NLDLY 0x0000100 #define LINUX_NL0 0x0000000 #define LINUX_NL1 0x0000100 #define LINUX_CRDLY 0x0000600 #define LINUX_CR0 0x0000000 #define LINUX_CR1 0x0000200 #define LINUX_CR2 0x0000400 #define LINUX_CR3 0x0000600 #define LINUX_TABDLY 0x0001800 #define LINUX_TAB0 0x0000000 #define LINUX_TAB1 0x0000800 #define LINUX_TAB2 0x0001000 #define LINUX_TAB3 0x0001800 #define LINUX_XTABS 0x0001800 #define LINUX_BSDLY 0x0002000 #define LINUX_BS0 0x0000000 #define LINUX_BS1 0x0002000 #define LINUX_VTDLY 0x0004000 #define LINUX_VT0 0x0000000 #define LINUX_VT1 0x0004000 #define LINUX_FFDLY 0x0008000 #define LINUX_FF0 0x0000000 #define LINUX_FF1 0x0008000 #define LINUX_CBAUD 0x0000100f #define LINUX_B0 0x00000000 #define LINUX_B50 0x00000001 #define LINUX_B75 0x00000002 #define LINUX_B110 0x00000003 #define LINUX_B134 0x00000004 #define LINUX_B150 0x00000005 #define LINUX_B200 0x00000006 #define LINUX_B300 0x00000007 #define LINUX_B600 0x00000008 #define LINUX_B1200 0x00000009 #define LINUX_B1800 0x0000000a #define LINUX_B2400 0x0000000b #define LINUX_B4800 0x0000000c #define LINUX_B9600 0x0000000d #define LINUX_B19200 0x0000000e #define LINUX_B38400 0x0000000f #define LINUX_EXTA LINUX_B19200 #define LINUX_EXTB LINUX_B38400 #define LINUX_CBAUDEX 0x00001000 #define LINUX_B57600 0x00001001 #define LINUX_B115200 0x00001002 #define LINUX_CSIZE 0x00000030 #define LINUX_CS5 0x00000000 #define LINUX_CS6 0x00000010 #define LINUX_CS7 0x00000020 #define LINUX_CS8 0x00000030 #define LINUX_CSTOPB 0x00000040 #define LINUX_CREAD 0x00000080 #define LINUX_PARENB 0x00000100 #define LINUX_PARODD 0x00000200 #define LINUX_HUPCL 0x00000400 #define LINUX_CLOCAL 0x00000800 #define LINUX_CRTSCTS 0x80000000 /* Linux c_lflag masks */ #define LINUX_ISIG 0x00000001 #define LINUX_ICANON 0x00000002 #define LINUX_XCASE 0x00000004 #define LINUX_ECHO 0x00000008 #define LINUX_ECHOE 0x00000010 #define LINUX_ECHOK 0x00000020 #define LINUX_ECHONL 0x00000040 #define LINUX_NOFLSH 0x00000080 #define LINUX_TOSTOP 0x00000100 #define LINUX_ECHOCTL 0x00000200 #define LINUX_ECHOPRT 0x00000400 #define LINUX_ECHOKE 0x00000800 #define LINUX_FLUSHO 0x00001000 #define LINUX_PENDIN 0x00002000 #define LINUX_IEXTEN 0x00008000 /* open/fcntl flags */ #define LINUX_O_RDONLY 00 #define LINUX_O_WRONLY 01 #define LINUX_O_RDWR 02 #define LINUX_O_CREAT 0100 #define LINUX_O_EXCL 0200 #define LINUX_O_NOCTTY 0400 #define LINUX_O_TRUNC 01000 #define LINUX_O_APPEND 02000 #define LINUX_O_NONBLOCK 04000 #define LINUX_O_NDELAY LINUX_O_NONBLOCK #define LINUX_O_SYNC 010000 #define LINUX_FASYNC 020000 /* fcntl flags */ #define LINUX_F_DUPFD 0 #define LINUX_F_GETFD 1 #define LINUX_F_SETFD 2 #define LINUX_F_GETFL 3 #define LINUX_F_SETFL 4 #define LINUX_F_GETLK 5 #define LINUX_F_SETLK 6 #define LINUX_F_SETLKW 7 #define LINUX_F_SETOWN 8 #define LINUX_F_GETOWN 9 #define LINUX_F_RDLCK 0 #define LINUX_F_WRLCK 1 #define LINUX_F_UNLCK 2 /* mmap options */ #define LINUX_MAP_SHARED 0x0001 #define LINUX_MAP_PRIVATE 0x0002 #define LINUX_MAP_FIXED 0x0010 #define LINUX_MAP_ANON 0x0020 /* SystemV ipc defines */ #define LINUX_SEMOP 1 #define LINUX_SEMGET 2 #define LINUX_SEMCTL 3 #define LINUX_MSGSND 11 #define LINUX_MSGRCV 12 #define LINUX_MSGGET 13 #define LINUX_MSGCTL 14 #define LINUX_SHMAT 21 #define LINUX_SHMDT 22 #define LINUX_SHMGET 23 #define LINUX_SHMCTL 24 #define LINUX_IPC_RMID 0 #define LINUX_IPC_SET 1 #define LINUX_IPC_STAT 2 #define LINUX_IPC_INFO 3 #define LINUX_SHM_LOCK 11 #define LINUX_SHM_UNLOCK 12 #define LINUX_SHM_STAT 13 #define LINUX_SHM_INFO 14 #define LINUX_SHM_RDONLY 0x1000 #define LINUX_SHM_RND 0x2000 #define LINUX_SHM_REMAP 0x4000 /* Socket defines */ #define LINUX_SOCKET 1 #define LINUX_BIND 2 #define LINUX_CONNECT 3 #define LINUX_LISTEN 4 #define LINUX_ACCEPT 5 #define LINUX_GETSOCKNAME 6 #define LINUX_GETPEERNAME 7 #define LINUX_SOCKETPAIR 8 #define LINUX_SEND 9 #define LINUX_RECV 10 #define LINUX_SENDTO 11 #define LINUX_RECVFROM 12 #define LINUX_SHUTDOWN 13 #define LINUX_SETSOCKOPT 14 #define LINUX_GETSOCKOPT 15 #define LINUX_AF_UNSPEC 0 #define LINUX_AF_UNIX 1 #define LINUX_AF_INET 2 #define LINUX_AF_AX25 3 #define LINUX_AF_IPX 4 #define LINUX_AF_APPLETALK 5 #define LINUX_SOL_SOCKET 1 #define LINUX_SOL_IP 0 #define LINUX_SOL_IPX 256 #define LINUX_SOL_AX25 257 #define LINUX_SOL_TCP 6 #define LINUX_SOL_UDP 17 #define LINUX_SO_DEBUG 1 #define LINUX_SO_REUSEADDR 2 #define LINUX_SO_TYPE 3 #define LINUX_SO_ERROR 4 #define LINUX_SO_DONTROUTE 5 #define LINUX_SO_BROADCAST 6 #define LINUX_SO_SNDBUF 7 #define LINUX_SO_RCVBUF 8 #define LINUX_SO_KEEPALIVE 9 #define LINUX_SO_OOBINLINE 10 #define LINUX_SO_NO_CHECK 11 #define LINUX_SO_PRIORITY 12 #define LINUX_SO_LINGER 13 #define LINUX_IP_TOS 1 #define LINUX_IP_TTL 2 /* Sound system defines */ #define LINUX_SNDCTL_DSP_RESET 0x5000 #define LINUX_SNDCTL_DSP_SYNC 0x5001 #define LINUX_SNDCTL_DSP_SPEED 0x5002 #define LINUX_SNDCTL_DSP_STEREO 0x5003 #define LINUX_SNDCTL_DSP_GETBLKSIZE 0x5004 #define LINUX_SNDCTL_DSP_SETBLKSIZE 0x5004 #define LINUX_SNDCTL_DSP_SETFMT 0x5005 #define LINUX_SOUND_PCM_WRITE_CHANNELS 0x5006 #define LINUX_SOUND_PCM_WRITE_FILTER 0x5007 #define LINUX_SNDCTL_DSP_POST 0x5008 #define LINUX_SNDCTL_DSP_SUBDIVIDE 0x5009 #define LINUX_SNDCTL_DSP_SETFRAGMENT 0x500A #define LINUX_SNDCTL_DSP_GETFMTS 0x500B #define LINUX_SNDCTL_DSP_GETOSPACE 0x500C #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 6c55613e6abc..2fcab4616a39 100644 --- a/sys/i386/linux/linux_dummy.c +++ b/sys/i386/linux/linux_dummy.c @@ -1,317 +1,298 @@ /*- * 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_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 #include #include #include #include -#include +#include +#include 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 0918f221fd3f..93932dfca75f 100644 --- a/sys/i386/linux/linux_file.c +++ b/sys/i386/linux/linux_file.c @@ -1,452 +1,763 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include #include #include -#include - -struct linux_creat_args { - char *path; - int mode; -}; +#include +#include int linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) { struct open_args /* { char *path; 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", p->p_pid, args->path, args->mode); #endif bsd_open_args.path = args->path; bsd_open_args.mode = args->mode; bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 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) { struct open_args /* { char *path; int flags; 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); #endif bsd_open_args.flags = 0; if (args->flags & LINUX_O_RDONLY) bsd_open_args.flags |= O_RDONLY; if (args->flags & LINUX_O_WRONLY) bsd_open_args.flags |= O_WRONLY; if (args->flags & LINUX_O_RDWR) bsd_open_args.flags |= O_RDWR; if (args->flags & LINUX_O_NDELAY) bsd_open_args.flags |= O_NONBLOCK; if (args->flags & LINUX_O_APPEND) bsd_open_args.flags |= O_APPEND; if (args->flags & LINUX_O_SYNC) bsd_open_args.flags |= O_FSYNC; if (args->flags & LINUX_O_NONBLOCK) bsd_open_args.flags |= O_NONBLOCK; if (args->flags & LINUX_FASYNC) bsd_open_args.flags |= O_ASYNC; if (args->flags & LINUX_O_CREAT) bsd_open_args.flags |= O_CREAT; if (args->flags & LINUX_O_TRUNC) bsd_open_args.flags |= O_TRUNC; if (args->flags & LINUX_O_EXCL) bsd_open_args.flags |= O_EXCL; if (args->flags & LINUX_O_NOCTTY) bsd_open_args.flags |= O_NOCTTY; bsd_open_args.path = args->path; bsd_open_args.mode = args->mode; error = open(p, &bsd_open_args, retval); if (!error && !(bsd_open_args.flags & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { struct filedesc *fdp = p->p_fd; struct file *fp = fdp->fd_ofiles[*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; } struct linux_flock { short l_type; short l_whence; linux_off_t l_start; linux_off_t l_len; linux_pid_t l_pid; }; static void linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) { switch (linux_flock->l_type) { case LINUX_F_RDLCK: bsd_flock->l_type = F_RDLCK; break; case LINUX_F_WRLCK: bsd_flock->l_type = F_WRLCK; break; case LINUX_F_UNLCK: bsd_flock->l_type = F_UNLCK; break; } bsd_flock->l_whence = linux_flock->l_whence; bsd_flock->l_start = (off_t)linux_flock->l_start; bsd_flock->l_len = (off_t)linux_flock->l_len; bsd_flock->l_pid = (pid_t)linux_flock->l_pid; } static void bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) { switch (bsd_flock->l_type) { case F_RDLCK: linux_flock->l_type = LINUX_F_RDLCK; break; case F_WRLCK: linux_flock->l_type = LINUX_F_WRLCK; break; case F_UNLCK: linux_flock->l_type = LINUX_F_UNLCK; break; } linux_flock->l_whence = bsd_flock->l_whence; linux_flock->l_start = (linux_off_t)bsd_flock->l_start; linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 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) { int error, result; struct fcntl_args /* { int fd; int cmd; 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", p->p_pid, args->fd, args->cmd); #endif fcntl_args.fd = args->fd; fcntl_args.arg = 0; switch (args->cmd) { case LINUX_F_DUPFD: fcntl_args.cmd = F_DUPFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETFD: fcntl_args.cmd = F_GETFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_SETFD: fcntl_args.cmd = F_SETFD; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETFL: fcntl_args.cmd = F_GETFL; error = fcntl(p, &fcntl_args, &result); *retval = 0; if (result & O_RDONLY) *retval |= LINUX_O_RDONLY; if (result & O_WRONLY) *retval |= LINUX_O_WRONLY; if (result & O_RDWR) *retval |= LINUX_O_RDWR; if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK; if (result & O_APPEND) *retval |= LINUX_O_APPEND; if (result & O_FSYNC) *retval |= LINUX_O_SYNC; return error; case LINUX_F_SETFL: if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; fcntl_args.cmd = F_SETFL; return fcntl(p, &fcntl_args, retval); case LINUX_F_GETLK: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_GETLK; fcntl_args.arg = (int)bsd_flock; if (error = fcntl(p, &fcntl_args, retval)) return error; bsd_to_linux_flock(bsd_flock, &linux_flock); return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, sizeof(struct linux_flock)); case LINUX_F_SETLK: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_SETLK; fcntl_args.arg = (int)bsd_flock; return fcntl(p, &fcntl_args, retval); case LINUX_F_SETLKW: if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, sizeof(struct linux_flock)))) return error; linux_to_bsd_flock(&linux_flock, bsd_flock); fcntl_args.cmd = F_SETLKW; fcntl_args.arg = (int)bsd_flock; 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) { struct lseek_args /* { int fd; int pad; off_t offset; int whence; } */ tmp_args; int error; #ifdef DEBUG printf("Linux-emul(%d): lseek(%d, %d, %d)\n", p->p_pid, args->fdes, args->off, args->whence); #endif tmp_args.fd = args->fdes; tmp_args.offset = (off_t)args->off; tmp_args.whence = args->whence; error = lseek(p, &tmp_args, 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; unsigned short dreclen; char dname[LINUX_NAME_MAX + 1]; }; #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 */ int len, reclen; /* BSD-format */ caddr_t outp; /* Linux-format */ int resid, linuxreclen=0; /* Linux-format */ struct file *fp; struct uio auio; struct iovec aiov; struct vattr va; off_t off; struct linux_dirent linux_dirent; 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); vp = (struct vnode *) fp->f_data; if (vp->v_type != VDIR) return (EINVAL); if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { return error; } nbytes = args->count; if (nbytes == 1) { nbytes = sizeof (struct linux_dirent); justone = 1; } else justone = 0; off = fp->f_offset; blockoff = off % DIRBLKSIZ; buflen = max(DIRBLKSIZ, nbytes + blockoff); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); VOP_LOCK(vp); again: aiov.iov_base = buf; aiov.iov_len = buflen; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_resid = buflen; auio.uio_offset = off - (off_t)blockoff; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (int *) NULL, (u_int **) NULL); if (error) { goto out; -} + } inp = buf; inp += blockoff; outp = (caddr_t) args->dent; resid = nbytes; if ((len = buflen - auio.uio_resid - blockoff) == 0) { goto eof; - } + } while (len > 0) { bdp = (struct dirent *) inp; reclen = bdp->d_reclen; if (reclen & 3) { printf("linux_readdir: reclen=%d\n", reclen); error = EFAULT; goto out; } if (bdp->d_fileno == 0) { inp += reclen; off += reclen; len -= reclen; continue; } linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); if (reclen > len || resid < linuxreclen) { outp++; break; } linux_dirent.dino = (long) bdp->d_fileno; linux_dirent.doff = (linux_off_t) linuxreclen; linux_dirent.dreclen = (u_short) bdp->d_namlen; strcpy(linux_dirent.dname, bdp->d_name); if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { goto out; - } + } inp += reclen; off += reclen; outp += linuxreclen; resid -= linuxreclen; len -= reclen; if (justone) break; } if (outp == (caddr_t) args->dent) goto again; fp->f_offset = off; if (justone) nbytes = resid + linuxreclen; eof: *retval = nbytes - resid; out: VOP_UNLOCK(vp); 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 000000000000..c52294880775 --- /dev/null +++ b/sys/i386/linux/linux_genassym.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +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 03bc0315e942..968092862bd9 100644 --- a/sys/i386/linux/linux_ioctl.c +++ b/sys/i386/linux/linux_ioctl.c @@ -1,559 +1,588 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include #include #include #include -#include +#include struct linux_termios { unsigned long c_iflag; unsigned long c_oflag; unsigned long c_cflag; unsigned long c_lflag; unsigned char c_line; unsigned char c_cc[LINUX_NCCS]; }; struct linux_winsize { unsigned short ws_row, ws_col; unsigned short ws_xpixel, ws_ypixel; }; static struct speedtab sptab[] = { { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 }, { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 }, { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 }, { 2400, 11 }, { 4800, 12 }, { 9600, 13 }, { 19200, 14 }, { 38400, 15 }, { 57600, 4097 }, { 115200, 4098 }, {-1, -1 } }; static int linux_to_bsd_speed(int code, struct speedtab *table) { for ( ; table->sp_code != -1; table++) if (table->sp_code == code) return (table->sp_speed); return -1; } static int bsd_to_linux_speed(int speed, struct speedtab *table) { for ( ; table->sp_speed != -1; table++) if (table->sp_speed == speed) return (table->sp_code); return -1; } static void bsd_to_linux_termios(struct termios *bsd_termios, struct linux_termios *linux_termios) { int i, speed; #ifdef DEBUG printf("LINUX: BSD termios structure (input):\n"); printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", bsd_termios->c_iflag, bsd_termios->c_oflag, bsd_termios->c_cflag, bsd_termios->c_lflag, bsd_termios->c_ispeed, bsd_termios->c_ospeed); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif linux_termios->c_iflag = 0; if (bsd_termios->c_iflag & IGNBRK) linux_termios->c_iflag |= LINUX_IGNBRK; if (bsd_termios->c_iflag & BRKINT) linux_termios->c_iflag |= LINUX_BRKINT; if (bsd_termios->c_iflag & IGNPAR) linux_termios->c_iflag |= LINUX_IGNPAR; if (bsd_termios->c_iflag & PARMRK) linux_termios->c_iflag |= LINUX_PARMRK; if (bsd_termios->c_iflag & INPCK) linux_termios->c_iflag |= LINUX_INPCK; if (bsd_termios->c_iflag & ISTRIP) linux_termios->c_iflag |= LINUX_ISTRIP; if (bsd_termios->c_iflag & INLCR) linux_termios->c_iflag |= LINUX_INLCR; if (bsd_termios->c_iflag & IGNCR) linux_termios->c_iflag |= LINUX_IGNCR; if (bsd_termios->c_iflag & ICRNL) linux_termios->c_iflag |= LINUX_ICRNL; if (bsd_termios->c_iflag & IXON) linux_termios->c_iflag |= LINUX_IXANY; if (bsd_termios->c_iflag & IXON) linux_termios->c_iflag |= LINUX_IXON; if (bsd_termios->c_iflag & IXOFF) linux_termios->c_iflag |= LINUX_IXOFF; if (bsd_termios->c_iflag & IMAXBEL) linux_termios->c_iflag |= LINUX_IMAXBEL; linux_termios->c_oflag = 0; if (bsd_termios->c_oflag & OPOST) linux_termios->c_oflag |= LINUX_OPOST; if (bsd_termios->c_oflag & ONLCR) linux_termios->c_oflag |= LINUX_ONLCR; if (bsd_termios->c_oflag & OXTABS) linux_termios->c_oflag |= LINUX_XTABS; linux_termios->c_cflag = bsd_to_linux_speed(bsd_termios->c_ispeed, sptab); linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4; if (bsd_termios->c_cflag & CSTOPB) linux_termios->c_cflag |= LINUX_CSTOPB; if (bsd_termios->c_cflag & CREAD) linux_termios->c_cflag |= LINUX_CREAD; if (bsd_termios->c_cflag & PARENB) linux_termios->c_cflag |= LINUX_PARENB; if (bsd_termios->c_cflag & PARODD) linux_termios->c_cflag |= LINUX_PARODD; if (bsd_termios->c_cflag & HUPCL) linux_termios->c_cflag |= LINUX_HUPCL; if (bsd_termios->c_cflag & CLOCAL) linux_termios->c_cflag |= LINUX_CLOCAL; if (bsd_termios->c_cflag & CRTSCTS) linux_termios->c_cflag |= LINUX_CRTSCTS; linux_termios->c_lflag = 0; if (bsd_termios->c_lflag & ISIG) linux_termios->c_lflag |= LINUX_ISIG; if (bsd_termios->c_lflag & ICANON) linux_termios->c_lflag |= LINUX_ICANON; if (bsd_termios->c_lflag & ECHO) linux_termios->c_lflag |= LINUX_ECHO; if (bsd_termios->c_lflag & ECHOE) linux_termios->c_lflag |= LINUX_ECHOE; if (bsd_termios->c_lflag & ECHOK) linux_termios->c_lflag |= LINUX_ECHOK; if (bsd_termios->c_lflag & ECHONL) linux_termios->c_lflag |= LINUX_ECHONL; if (bsd_termios->c_lflag & NOFLSH) linux_termios->c_lflag |= LINUX_NOFLSH; if (bsd_termios->c_lflag & TOSTOP) linux_termios->c_lflag |= LINUX_TOSTOP; if (bsd_termios->c_lflag & ECHOCTL) linux_termios->c_lflag |= LINUX_ECHOCTL; if (bsd_termios->c_lflag & ECHOPRT) linux_termios->c_lflag |= LINUX_ECHOPRT; if (bsd_termios->c_lflag & ECHOKE) linux_termios->c_lflag |= LINUX_ECHOKE; if (bsd_termios->c_lflag & FLUSHO) linux_termios->c_lflag |= LINUX_FLUSHO; if (bsd_termios->c_lflag & PENDIN) linux_termios->c_lflag |= LINUX_PENDIN; if (bsd_termios->c_lflag & IEXTEN) linux_termios->c_lflag |= LINUX_IEXTEN; for (i=0; ic_cc[i] = _POSIX_VDISABLE; linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR]; linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT]; linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE]; linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL]; linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF]; linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL]; linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN]; linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME]; linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2]; linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE; linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP]; linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART]; linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP]; linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT]; linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD]; linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE]; linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT]; linux_termios->c_line = 0; #ifdef DEBUG printf("LINUX: LINUX termios structure (output):\n"); printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, linux_termios->c_lflag, linux_termios->c_line); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif } static void linux_to_bsd_termios(struct linux_termios *linux_termios, struct termios *bsd_termios) { int i, speed; #ifdef DEBUG printf("LINUX: LINUX termios structure (input):\n"); printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", linux_termios->c_iflag, linux_termios->c_oflag, linux_termios->c_cflag, linux_termios->c_lflag, linux_termios->c_line); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif bsd_termios->c_iflag = 0; if (linux_termios->c_iflag & LINUX_IGNBRK) bsd_termios->c_iflag |= IGNBRK; if (linux_termios->c_iflag & LINUX_BRKINT) bsd_termios->c_iflag |= BRKINT; if (linux_termios->c_iflag & LINUX_IGNPAR) bsd_termios->c_iflag |= IGNPAR; if (linux_termios->c_iflag & LINUX_PARMRK) bsd_termios->c_iflag |= PARMRK; if (linux_termios->c_iflag & LINUX_INPCK) bsd_termios->c_iflag |= INPCK; if (linux_termios->c_iflag & LINUX_ISTRIP) bsd_termios->c_iflag |= ISTRIP; if (linux_termios->c_iflag & LINUX_INLCR) bsd_termios->c_iflag |= INLCR; if (linux_termios->c_iflag & LINUX_IGNCR) bsd_termios->c_iflag |= IGNCR; if (linux_termios->c_iflag & LINUX_ICRNL) bsd_termios->c_iflag |= ICRNL; if (linux_termios->c_iflag & LINUX_IXON) bsd_termios->c_iflag |= IXANY; if (linux_termios->c_iflag & LINUX_IXON) bsd_termios->c_iflag |= IXON; if (linux_termios->c_iflag & LINUX_IXOFF) bsd_termios->c_iflag |= IXOFF; if (linux_termios->c_iflag & LINUX_IMAXBEL) bsd_termios->c_iflag |= IMAXBEL; bsd_termios->c_oflag = 0; if (linux_termios->c_oflag & LINUX_OPOST) bsd_termios->c_oflag |= OPOST; if (linux_termios->c_oflag & LINUX_ONLCR) bsd_termios->c_oflag |= ONLCR; if (linux_termios->c_oflag & LINUX_XTABS) bsd_termios->c_oflag |= OXTABS; bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4; if (linux_termios->c_cflag & LINUX_CSTOPB) bsd_termios->c_cflag |= CSTOPB; if (linux_termios->c_cflag & LINUX_PARENB) bsd_termios->c_cflag |= PARENB; if (linux_termios->c_cflag & LINUX_PARODD) bsd_termios->c_cflag |= PARODD; if (linux_termios->c_cflag & LINUX_HUPCL) bsd_termios->c_cflag |= HUPCL; if (linux_termios->c_cflag & LINUX_CLOCAL) bsd_termios->c_cflag |= CLOCAL; if (linux_termios->c_cflag & LINUX_CRTSCTS) bsd_termios->c_cflag |= CRTSCTS; bsd_termios->c_lflag = 0; if (linux_termios->c_lflag & LINUX_ISIG) bsd_termios->c_lflag |= ISIG; if (linux_termios->c_lflag & LINUX_ICANON) bsd_termios->c_lflag |= ICANON; if (linux_termios->c_lflag & LINUX_ECHO) bsd_termios->c_lflag |= ECHO; if (linux_termios->c_lflag & LINUX_ECHOE) bsd_termios->c_lflag |= ECHOE; if (linux_termios->c_lflag & LINUX_ECHOK) bsd_termios->c_lflag |= ECHOK; if (linux_termios->c_lflag & LINUX_ECHONL) bsd_termios->c_lflag |= ECHONL; if (linux_termios->c_lflag & LINUX_NOFLSH) bsd_termios->c_lflag |= NOFLSH; if (linux_termios->c_lflag & LINUX_TOSTOP) bsd_termios->c_lflag |= TOSTOP; if (linux_termios->c_lflag & LINUX_ECHOCTL) bsd_termios->c_lflag |= ECHOCTL; if (linux_termios->c_lflag & LINUX_ECHOPRT) bsd_termios->c_lflag |= ECHOPRT; if (linux_termios->c_lflag & LINUX_ECHOKE) bsd_termios->c_lflag |= ECHOKE; if (linux_termios->c_lflag & LINUX_FLUSHO) bsd_termios->c_lflag |= FLUSHO; if (linux_termios->c_lflag & LINUX_PENDIN) bsd_termios->c_lflag |= PENDIN; if (linux_termios->c_lflag & IEXTEN) bsd_termios->c_lflag |= IEXTEN; for (i=0; ic_cc[i] = _POSIX_VDISABLE; bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR]; bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT]; bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE]; bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL]; bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF]; bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL]; bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN]; bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME]; bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2]; bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP]; bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART]; bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP]; bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT]; bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD]; bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE]; bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT]; bsd_termios->c_ispeed = bsd_termios->c_ospeed = linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab); #ifdef DEBUG printf("LINUX: BSD termios structure (output):\n"); printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", bsd_termios->c_iflag, bsd_termios->c_oflag, bsd_termios->c_cflag, bsd_termios->c_lflag, bsd_termios->c_ispeed, bsd_termios->c_ospeed); printf("c_cc "); for (i=0; ic_cc[i]); printf("\n"); #endif } - -struct linux_ioctl_args { - int fd; - int cmd; - int arg; -}; - int linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval) { struct termios bsd_termios; struct winsize bsd_winsize; struct linux_termios linux_termios; struct linux_winsize linux_winsize; struct filedesc *fdp = p->p_fd; struct file *fp; int (*func)(struct file *fp, int com, caddr_t data, struct proc *p); int bsd_line, linux_line; int error; #ifdef DEBUG printf("Linux-emul(%d): ioctl(%d, %04x, *)\n", p->p_pid, args->fd, args->cmd); #endif if ((unsigned)args->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[args->fd]) == 0) return EBADF; if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) { return EBADF; } func = fp->f_ops->fo_ioctl; switch (args->cmd & 0xffff) { case LINUX_TCGETS: if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0) return error; bsd_to_linux_termios(&bsd_termios, &linux_termios); return copyout((caddr_t)&linux_termios, (caddr_t)args->arg, sizeof(linux_termios)); case LINUX_TCSETS: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p); case LINUX_TCSETSW: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p); case LINUX_TCSETSF: linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios); return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p); case LINUX_TIOCGPGRP: args->cmd = TIOCGPGRP; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCSPGRP: args->cmd = TIOCSPGRP; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCGWINSZ: args->cmd = TIOCGWINSZ; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCSWINSZ: args->cmd = TIOCSWINSZ; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONREAD: args->cmd = FIONREAD; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONBIO: args->cmd = FIONBIO; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIOASYNC: args->cmd = FIOASYNC; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIONCLEX: args->cmd = FIONCLEX; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_FIOCLEX: args->cmd = FIOCLEX; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCEXCL: args->cmd = TIOCEXCL; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCNXCL: args->cmd = TIOCNXCL; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCCONS: args->cmd = TIOCCONS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_TIOCNOTTY: 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: bsd_line = TTYDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); case LINUX_N_SLIP: bsd_line = SLIPDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); case LINUX_N_PPP: bsd_line = PPPDISC; return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p); default: return EINVAL; } case LINUX_TIOCGETD: bsd_line = TTYDISC; if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p)) return error; switch (bsd_line) { case TTYDISC: linux_line = LINUX_N_TTY; break; case SLIPDISC: linux_line = LINUX_N_SLIP; break; case PPPDISC: linux_line = LINUX_N_PPP; break; default: return EINVAL; } return copyout(&linux_line, (caddr_t)args->arg, sizeof(int)); case LINUX_SNDCTL_DSP_RESET: args->cmd = SNDCTL_DSP_RESET; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SYNC: args->cmd = SNDCTL_DSP_SYNC; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SPEED: args->cmd = SNDCTL_DSP_SPEED; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_STEREO: args->cmd = SNDCTL_DSP_STEREO; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ args->cmd = SNDCTL_DSP_GETBLKSIZE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SETFMT: args->cmd = SNDCTL_DSP_SETFMT; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SOUND_PCM_WRITE_CHANNELS: args->cmd = SOUND_PCM_WRITE_CHANNELS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SOUND_PCM_WRITE_FILTER: args->cmd = SOUND_PCM_WRITE_FILTER; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_POST: args->cmd = SNDCTL_DSP_POST; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SUBDIVIDE: args->cmd = SNDCTL_DSP_SUBDIVIDE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_SETFRAGMENT: args->cmd = SNDCTL_DSP_SETFRAGMENT; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETFMTS: args->cmd = SNDCTL_DSP_GETFMTS; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETOSPACE: args->cmd = SNDCTL_DSP_GETOSPACE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_GETISPACE: args->cmd = SNDCTL_DSP_GETISPACE; return ioctl(p, (struct ioctl_args *)args, retval); case LINUX_SNDCTL_DSP_NONBLOCK: args->cmd = SNDCTL_DSP_NONBLOCK; return ioctl(p, (struct ioctl_args *)args, retval); } uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n", args->fd, (args->cmd&0xffff00)>>8, (args->cmd&0xffff00)>>8, args->cmd&0xff); return EINVAL; } diff --git a/sys/i386/linux/linux_ipc.c b/sys/i386/linux/linux_ipc.c index 2e5b924bc38c..854766b99cc8 100644 --- a/sys/i386/linux/linux_ipc.c +++ b/sys/i386/linux/linux_ipc.c @@ -1,347 +1,353 @@ /*- * 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_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 $ */ #include #include #include #include #include #include -#include +#include +#include + +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; unsigned short uid; unsigned short gid; unsigned short cuid; unsigned short cgid; unsigned short mode; unsigned short seq; }; static void linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) { bpp->key = lpp->key; bpp->uid = lpp->uid; bpp->gid = lpp->gid; bpp->cuid = lpp->cuid; bpp->cgid = lpp->cgid; bpp->mode = lpp->mode; bpp->seq = lpp->seq; } static void bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) { lpp->key = bpp->key; lpp->uid = bpp->uid; lpp->gid = bpp->gid; lpp->cuid = bpp->cuid; lpp->cgid = bpp->cgid; lpp->mode = bpp->mode; lpp->seq = bpp->seq; } struct linux_shmid_ds { struct linux_ipc_perm shm_perm; int shm_segsz; linux_time_t shm_atime; linux_time_t shm_dtime; linux_time_t shm_ctime; ushort shm_cpid; ushort shm_lpid; short shm_nattch; ushort private1; void *private2; void *private3; }; static void linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); bsp->shm_segsz = lsp->shm_segsz; bsp->shm_lpid = lsp->shm_lpid; bsp->shm_cpid = lsp->shm_cpid; bsp->shm_nattch = lsp->shm_nattch; bsp->shm_atime = lsp->shm_atime; bsp->shm_dtime = lsp->shm_dtime; bsp->shm_ctime = lsp->shm_ctime; bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ } static void bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); lsp->shm_segsz = bsp->shm_segsz; lsp->shm_lpid = bsp->shm_lpid; lsp->shm_cpid = bsp->shm_cpid; lsp->shm_nattch = bsp->shm_nattch; lsp->shm_atime = bsp->shm_atime; lsp->shm_dtime = bsp->shm_dtime; lsp->shm_ctime = bsp->shm_ctime; 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 /* { int msqid; void *msgp; size_t msgsz; int msgflg; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.msgp = args->ptr; bsd_args.msgsz = args->arg2; bsd_args.msgflg = args->arg3; return msgsnd(p, &bsd_args, retval); } -int +static int linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgrcv_args /* { int msqid; void *msgp; size_t msgsz; long msgtyp; int msgflg; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.msgp = args->ptr; bsd_args.msgsz = args->arg2; bsd_args.msgtyp = 0; bsd_args.msgflg = args->arg3; return msgrcv(p, &bsd_args, retval); } -int +static int linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgget_args /* { key_t key; int msgflg; } */ bsd_args; bsd_args.key = args->arg1; bsd_args.msgflg = args->arg2; return msgget(p, &bsd_args, retval); } -int +static int linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) { struct msgctl_args /* { int msqid; int cmd; struct msqid_ds *buf; } */ bsd_args; bsd_args.msqid = args->arg1; bsd_args.cmd = args->arg2; bsd_args.buf = (struct msqid_ds *)args->ptr; return msgctl(p, &bsd_args, retval); } -int +static int linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmat_args /* { int shmid; void *shmaddr; int shmflg; } */ bsd_args; int error; bsd_args.shmid = args->arg1; bsd_args.shmaddr = args->ptr; bsd_args.shmflg = args->arg2; if ((error = shmat(p, &bsd_args, retval))) return error; if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) return error; retval[0] = 0; return 0; } -int +static int linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmdt_args /* { void *shmaddr; } */ bsd_args; bsd_args.shmaddr = args->ptr; return shmdt(p, &bsd_args, retval); } -int +static int linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) { struct shmget_args /* { key_t key; int size; int shmflg; } */ bsd_args; bsd_args.key = args->arg1; bsd_args.size = args->arg2; bsd_args.shmflg = args->arg3; 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; struct linux_shmid_ds linux_shmid; struct shmctl_args /* { int shmid; int cmd; 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, sizeof(struct shmid_ds)))) return error; bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); case LINUX_IPC_SET: if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 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; bsd_args.shmid = args->arg1; bsd_args.cmd = IPC_SET; return shmctl(p, &bsd_args, retval); case LINUX_IPC_RMID: bsd_args.shmid = args->arg1; bsd_args.cmd = IPC_RMID; if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 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; return shmctl(p, &bsd_args, retval); case LINUX_IPC_INFO: case LINUX_SHM_STAT: case LINUX_SHM_INFO: case LINUX_SHM_LOCK: case LINUX_SHM_UNLOCK: default: uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); return EINVAL; } } int linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) { switch (args->what) { case LINUX_SEMOP: return linux_semop(p, args, retval); case LINUX_SEMGET: return linux_semget(p, args, retval); case LINUX_SEMCTL: return linux_semctl(p, args, retval); case LINUX_MSGSND: return linux_msgsnd(p, args, retval); case LINUX_MSGRCV: return linux_msgrcv(p, args, retval); case LINUX_MSGGET: return linux_msgget(p, args, retval); case LINUX_MSGCTL: return linux_msgctl(p, args, retval); case LINUX_SHMAT: return linux_shmat(p, args, retval); case LINUX_SHMDT: return linux_shmdt(p, args, retval); case LINUX_SHMGET: return linux_shmget(p, args, retval); case LINUX_SHMCTL: return linux_shmctl(p, args, retval); default: uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); return ENOSYS; } } diff --git a/sys/i386/linux/linux_locore.s b/sys/i386/linux/linux_locore.s new file mode 100644 index 000000000000..1440218e847d --- /dev/null +++ b/sys/i386/linux/linux_locore.s @@ -0,0 +1,26 @@ +#include "linux_assym.h" /* system definitions */ +#include /* miscellaneous asm macros */ + +#include /* 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 bc6e8d824b29..069ca28cf739 100644 --- a/sys/i386/linux/linux_misc.c +++ b/sys/i386/linux/linux_misc.c @@ -1,781 +1,914 @@ /*- * 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 + * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include -#include - -struct linux_alarm_args { - unsigned int secs; -}; +#include +#include int linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval) { struct itimerval it, old_it; struct timeval tv; int s; #ifdef DEBUG printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs); #endif it.it_value.tv_sec = (long)args->secs; it.it_value.tv_usec = 0; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; s = splclock(); old_it = p->p_realtimer; tv = time; if (timerisset(&old_it.it_value)) if (timercmp(&old_it.it_value, &tv, <)) timerclear(&old_it.it_value); else timevalsub(&old_it.it_value, &tv); splx(s); if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) return EINVAL; s = splclock(); untimeout(realitexpire, (caddr_t)p); tv = time; if (timerisset(&it.it_value)) { timevaladd(&it.it_value, &tv); timeout(realitexpire, (caddr_t)p, hzto(&it.it_value)); } p->p_realtimer = it; splx(s); if (old_it.it_value.tv_usec) old_it.it_value.tv_sec++; *retval = old_it.it_value.tv_sec; return 0; } -struct linux_brk_args { - linux_caddr_t dsend; -}; - int linux_brk(struct proc *p, struct linux_brk_args *args, int *retval) { #if 0 struct vmspace *vm = p->p_vmspace; vm_offset_t new, old; int error; if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) return EINVAL; if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) > p->p_rlimit[RLIMIT_DATA].rlim_cur) return ENOMEM; old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); new = round_page((vm_offset_t)args->dsend); *retval = old; if ((new-old) > 0) { if (swap_pager_full) 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)); } return 0; #else struct vmspace *vm = p->p_vmspace; vm_offset_t new, old; struct obreak_args /* { char * nsize; } */ tmp; #ifdef DEBUG printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend); #endif old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); new = (vm_offset_t)args->dsend; tmp.nsize = (char *) new; if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval)) retval[0] = (int)new; else retval[0] = (int)old; return 0; #endif } -struct linux_uselib_args { - char *library; -}; - int linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval) { struct nameidata ni; struct vnode *vp; struct exec *a_out; struct vattr attr; 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 a_out = NULL; 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; vp = ni.ni_vp; if (vp == NULL) { error = ENOEXEC; /* ?? */ goto cleanup; } /* * From here on down, we have a locked vnode that must be unlocked. */ locked++; /* * Writable? */ if (vp->v_writecount) { error = ETXTBSY; goto cleanup; } /* * Executable? */ if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) goto cleanup; if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { error = ENOEXEC; goto cleanup; } /* * Sensible size? */ if (attr.va_size == 0) { error = ENOEXEC; goto cleanup; } /* * Can we access it? */ if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) goto cleanup; if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) goto cleanup; /* * Lock no longer needed */ VOP_UNLOCK(vp); locked = 0; /* * Pull in executable header into kernel_map */ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); if (error) goto cleanup; /* * Is it a Linux binary ? */ if (((a_out->a_magic >> 16) & 0xff) != 0x64) { error = ENOEXEC; goto cleanup; } /* While we are here, we should REALLY do some more checks */ /* * Set file/virtual offset based on a.out variant. */ switch ((int)(a_out->a_magic & 0xffff)) { case 0413: /* ZMAGIC */ file_offset = 1024; break; case 0314: /* QMAGIC */ file_offset = 0; break; default: error = ENOEXEC; goto cleanup; } bss_size = round_page(a_out->a_bss); /* * Check various fields in header for validity/bounds. */ if (a_out->a_text % NBPG || a_out->a_data % NBPG) { error = ENOEXEC; goto cleanup; } /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > attr.va_size) { error = EFAULT; goto cleanup; } /* * text/data/bss must not exceed limits * XXX: this is not complete. it should check current usage PLUS * the resources needed by this library. */ if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || a_out->a_data+bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { error = ENOMEM; goto cleanup; } /* * prevent more writers */ vp->v_flag |= VTEXT; /* * Check if file_offset page aligned,. * Currently we cannot handle misalinged file offsets, * and so we read in the entire image (what a waste). */ if (file_offset & PGOFSET) { #ifdef DEBUG printf("uselib: Non page aligned binary %d\n", file_offset); #endif /* * Map text+data read/write/execute */ /* a_entry is the load address and is page aligned */ vmaddr = trunc_page(a_out->a_entry); /* get anon user mapping, read+write+execute */ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) goto cleanup; /* map file into kernel_map */ error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, MAP_FILE, (caddr_t)vp, trunc_page(file_offset)); if (error) 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 */ vm_map_remove(kernel_map, buffer, round_page(a_out->a_text + a_out->a_data + file_offset)); if (error) goto cleanup; } else { #ifdef DEBUG printf("uselib: Page aligned binary %d\n", file_offset); #endif /* * for QMAGIC, a_entry is 20 bytes beyond the load address * to skip the executable header */ vmaddr = trunc_page(a_out->a_entry); /* * Map it all into the process's space as a single copy-on-write * "data" segment. */ error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset); if (error) goto cleanup; } #ifdef DEBUG printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]); #endif if (bss_size != 0) { /* * Calculate BSS start address */ vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; /* * 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) goto cleanup; } cleanup: /* * Unlock vnode if needed */ if (locked) VOP_UNLOCK(vp); /* * Release the kernel mapping. */ if (a_out) vm_map_remove(kernel_map, (vm_offset_t)a_out, PAGE_SIZE); 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) { struct proc *curproc; #ifdef DEBUG printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid); #endif if (args->pid != p->p_pid) { if (!(curproc = pfind(args->pid))) return ESRCH; } else curproc = p; *retval = curproc->p_pgid; return 0; } 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; int prot; int flags; int fd; long pad; 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; if (linux_args.flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (linux_args.flags & LINUX_MAP_PRIVATE) bsd_args.flags |= MAP_PRIVATE; if (linux_args.flags & LINUX_MAP_FIXED) bsd_args.flags |= MAP_FIXED; if (linux_args.flags & LINUX_MAP_ANON) bsd_args.flags |= MAP_ANON; bsd_args.addr = linux_args.addr; bsd_args.len = linux_args.len; bsd_args.prot = linux_args.prot; bsd_args.fd = linux_args.fd; bsd_args.pos = linux_args.pos; bsd_args.pad = 0; 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) { int error; #ifdef DEBUG printf("Linux-emul(%d): pipe(*)\n", p->p_pid); #endif if (error = pipe(p, 0, retval)) return error; if (error = copyout(retval, args->pipefds, 2*sizeof(int))) return error; *retval = 0; return 0; } -struct linux_time_args { - linux_time_t *tm; -}; - int linux_time(struct proc *p, struct linux_time_args *args, int *retval) { struct timeval tv; linux_time_t tm; int error; #ifdef DEBUG printf("Linux-emul(%d): time(*)\n", p->p_pid); #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); #endif tms.tms_utime = p->p_uticks; tms.tms_stime = p->p_sticks; tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz + ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000); tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz + ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000); 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]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; -struct linux_newuname_args { - char *buf; -}; - int linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval) { struct linux_newuname_t linux_newuname; #ifdef DEBUG printf("Linux-emul(%d): newuname(*)\n", p->p_pid); #endif bzero(&linux_newuname, sizeof(struct linux_newuname_args)); strncpy(linux_newuname.sysname, ostype, 64); strncpy(linux_newuname.nodename, hostname, 64); strncpy(linux_newuname.release, osrelease, 64); strncpy(linux_newuname.version, version, 64); strncpy(linux_newuname.machine, machine, 64); strncpy(linux_newuname.domainname, domainname, 64); return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf, 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) { struct utimes_args /* { char *path; 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) { struct wait_args /* { int pid; int *status; int options; struct rusage *rusage; } */ tmp; 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; tmp.options = args->options; tmp.rusage = NULL; 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 /* { int pid; int *status; int options; struct rusage *rusage; } */ tmp; 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; tmp.options = args->options; tmp.rusage = args->rusage; 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 000000000000..a227f2ca25d5 --- /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 +#include +#include + +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 fc5c2cd7c274..32648cb217a9 100644 --- a/sys/i386/linux/linux_signal.c +++ b/sys/i386/linux/linux_signal.c @@ -1,261 +1,311 @@ /*- * 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_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 #include #include #include #include #include #include #include -#include - -#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD)) +#include +#include 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; } sa.signum = linux_to_bsd_signal[args->sig]; sa.nsa = nsa; sa.osa = osa; if ((error = sigaction(p, &sa, retval))) return error; 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, int *retval) { int error, s; sigset_t mask; sigset_t omask; #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; } if (!(args->mask)) return 0; 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; break; } splx(s); return error; } 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) { linux_sigset_t linux_sig; #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) { struct kill_args /* { int pid; int signum; } */ tmp; #ifdef DEBUG printf("Linux-emul(%d): kill(%d, %d)\n", p->p_pid, args->pid, args->signum); #endif tmp.pid = args->pid; tmp.signum = linux_to_bsd_signal[args->signum]; return kill(p, &tmp, retval); } diff --git a/sys/i386/linux/linux_socket.c b/sys/i386/linux/linux_socket.c index da4668c674e1..63b33d50c9be 100644 --- a/sys/i386/linux/linux_socket.c +++ b/sys/i386/linux/linux_socket.c @@ -1,601 +1,596 @@ /*- * Copyright (c) 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_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. */ #define COMPAT_43 1 #include #include #include #include #include #include #include #include -#include +#include static int linux_to_bsd_domain(int domain) { switch (domain) { case LINUX_AF_UNSPEC: return AF_UNSPEC; case LINUX_AF_UNIX: return AF_LOCAL; case LINUX_AF_INET: return AF_INET; case LINUX_AF_AX25: return AF_CCITT; case LINUX_AF_IPX: return AF_IPX; case LINUX_AF_APPLETALK: return AF_APPLETALK; default: return -1; } } static int linux_to_bsd_sockopt_level(int level) { switch (level) { case LINUX_SOL_SOCKET: return SOL_SOCKET; default: return level; } } static int linux_to_bsd_ip_sockopt(int opt) { switch (opt) { case LINUX_IP_TOS: return IP_TOS; case LINUX_IP_TTL: return IP_TTL; default: return -1; } } static int linux_to_bsd_so_sockopt(int opt) { switch (opt) { case LINUX_SO_DEBUG: return SO_DEBUG; case LINUX_SO_REUSEADDR: return SO_REUSEADDR; case LINUX_SO_TYPE: return SO_TYPE; case LINUX_SO_ERROR: return SO_ERROR; case LINUX_SO_DONTROUTE: return SO_DONTROUTE; case LINUX_SO_BROADCAST: return SO_BROADCAST; case LINUX_SO_SNDBUF: return SO_SNDBUF; case LINUX_SO_RCVBUF: return SO_RCVBUF; case LINUX_SO_KEEPALIVE: return SO_KEEPALIVE; case LINUX_SO_OOBINLINE: return SO_OOBINLINE; case LINUX_SO_LINGER: return SO_LINGER; case LINUX_SO_PRIORITY: case LINUX_SO_NO_CHECK: default: return -1; } } struct linux_socket_args { int domain; int type; int protocol; }; static int linux_socket(struct proc *p, struct linux_socket_args *args, int *retval) { struct linux_socket_args linux_args; struct socket_args /* { int domain; int type; int protocol; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.protocol = linux_args.protocol; bsd_args.type = linux_args.type; bsd_args.domain = linux_to_bsd_domain(linux_args.domain); if (bsd_args.domain == -1) return EINVAL; return socket(p, &bsd_args, retval); } struct linux_bind_args { int s; struct sockaddr *name; int namelen; }; static int linux_bind(struct proc *p, struct linux_bind_args *args, int *retval) { struct linux_bind_args linux_args; struct bind_args /* { int s; caddr_t name; int namelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.name; bsd_args.namelen = linux_args.namelen; return bind(p, &bsd_args, retval); } struct linux_connect_args { int s; struct sockaddr * name; int namelen; }; static int linux_connect(struct proc *p, struct linux_connect_args *args, int *retval) { struct linux_connect_args linux_args; struct connect_args /* { int s; caddr_t name; int namelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.name; bsd_args.namelen = linux_args.namelen; return connect(p, &bsd_args, retval); } struct linux_listen_args { int s; int backlog; }; static int linux_listen(struct proc *p, struct linux_listen_args *args, int *retval) { struct linux_listen_args linux_args; struct listen_args /* { int s; int backlog; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.backlog = linux_args.backlog; return listen(p, &bsd_args, retval); } struct linux_accept_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_accept(struct proc *p, struct linux_accept_args *args, int *retval) { struct linux_accept_args linux_args; struct accept_args /* { int s; caddr_t name; int *anamelen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.name = (caddr_t)linux_args.addr; bsd_args.anamelen = linux_args.namelen; return oaccept(p, &bsd_args, retval); } struct linux_getsockname_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval) { struct linux_getsockname_args linux_args; struct getsockname_args /* { int fdes; caddr_t asa; int *alen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.fdes = linux_args.s; bsd_args.asa = (caddr_t) linux_args.addr; bsd_args.alen = linux_args.namelen; return ogetsockname(p, &bsd_args, retval); } struct linux_getpeername_args { int s; struct sockaddr *addr; int *namelen; }; static int linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval) { struct linux_getpeername_args linux_args; struct ogetpeername_args /* { int fdes; caddr_t asa; int *alen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.fdes = linux_args.s; bsd_args.asa = (caddr_t) linux_args.addr; bsd_args.alen = linux_args.namelen; return ogetpeername(p, &bsd_args, retval); } struct linux_socketpair_args { int domain; int type; int protocol; int *rsv; }; static int linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval) { struct linux_socketpair_args linux_args; struct socketpair_args /* { int domain; int type; int protocol; int *rsv; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.domain = linux_to_bsd_domain(linux_args.domain); if (bsd_args.domain == -1) return EINVAL; bsd_args.type = linux_args.type; bsd_args.protocol = linux_args.protocol; bsd_args.rsv = linux_args.rsv; return socketpair(p, &bsd_args, retval); } struct linux_send_args { int s; void *msg; int len; int flags; }; static int linux_send(struct proc *p, struct linux_send_args *args, int *retval) { struct linux_send_args linux_args; struct osend_args /* { int s; caddr_t buf; int len; int flags; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; return osend(p, &bsd_args, retval); } struct linux_recv_args { int s; void *msg; int len; int flags; }; static int linux_recv(struct proc *p, struct linux_recv_args *args, int *retval) { struct linux_recv_args linux_args; struct orecv_args /* { int s; caddr_t buf; int len; int flags; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; return orecv(p, &bsd_args, retval); } struct linux_sendto_args { int s; void *msg; int len; int flags; caddr_t to; int tolen; }; static int linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval) { struct linux_sendto_args linux_args; struct sendto_args /* { int s; caddr_t buf; size_t len; int flags; caddr_t to; int tolen; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.msg; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; bsd_args.to = linux_args.to; bsd_args.tolen = linux_args.tolen; return sendto(p, &bsd_args, retval); } struct linux_recvfrom_args { int s; void *buf; int len; int flags; caddr_t from; int *fromlen; }; static int linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval) { struct linux_recvfrom_args linux_args; struct recvfrom_args /* { int s; caddr_t buf; size_t len; int flags; caddr_t from; int *fromlenaddr; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.buf = linux_args.buf; bsd_args.len = linux_args.len; bsd_args.flags = linux_args.flags; bsd_args.from = linux_args.from; bsd_args.fromlenaddr = linux_args.fromlen; return orecvfrom(p, &bsd_args, retval); } struct linux_shutdown_args { int s; int how; }; static int linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval) { struct linux_shutdown_args linux_args; struct shutdown_args /* { int s; int how; } */ bsd_args; int error; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.how = linux_args.how; return shutdown(p, &bsd_args, retval); } struct linux_setsockopt_args { int s; int level; int optname; void *optval; int optlen; }; static int linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval) { struct linux_setsockopt_args linux_args; struct setsockopt_args /* { int s; int level; int name; caddr_t val; int valsize; } */ bsd_args; int error, name; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); switch (bsd_args.level) { case SOL_SOCKET: name = linux_to_bsd_so_sockopt(linux_args.optname); break; case IPPROTO_IP: name = linux_to_bsd_ip_sockopt(linux_args.optname); break; default: return EINVAL; } if (name == -1) return EINVAL; bsd_args.name = name; bsd_args.val = linux_args.optval; bsd_args.valsize = linux_args.optlen; return setsockopt(p, &bsd_args, retval); } struct linux_getsockopt_args { int s; int level; int optname; void *optval; int *optlen; }; static int linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval) { struct linux_getsockopt_args linux_args; struct getsockopt_args /* { int s; int level; int name; caddr_t val; int *avalsize; } */ bsd_args; int error, name; if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args)))) return error; bsd_args.s = linux_args.s; bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); switch (bsd_args.level) { case SOL_SOCKET: name = linux_to_bsd_so_sockopt(linux_args.optname); break; case IPPROTO_IP: name = linux_to_bsd_ip_sockopt(linux_args.optname); break; default: return EINVAL; } if (name == -1) return EINVAL; bsd_args.val = linux_args.optval; bsd_args.avalsize = linux_args.optlen; 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) { switch (args->what) { case LINUX_SOCKET: return linux_socket(p, args->args, retval); case LINUX_BIND: return linux_bind(p, args->args, retval); case LINUX_CONNECT: return linux_connect(p, args->args, retval); case LINUX_LISTEN: return linux_listen(p, args->args, retval); case LINUX_ACCEPT: return linux_accept(p, args->args, retval); case LINUX_GETSOCKNAME: return linux_getsockname(p, args->args, retval); case LINUX_GETPEERNAME: return linux_getpeername(p, args->args, retval); case LINUX_SOCKETPAIR: return linux_socketpair(p, args->args, retval); case LINUX_SEND: return linux_send(p, args->args, retval); case LINUX_RECV: return linux_recv(p, args->args, retval); case LINUX_SENDTO: return linux_sendto(p, args->args, retval); case LINUX_RECVFROM: return linux_recvfrom(p, args->args, retval); case LINUX_SHUTDOWN: return linux_shutdown(p, args->args, retval); case LINUX_SETSOCKOPT: return linux_setsockopt(p, args->args, retval); case LINUX_GETSOCKOPT: return linux_getsockopt(p, args->args, retval); default: uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); return ENOSYS; } } diff --git a/sys/i386/linux/linux_stats.c b/sys/i386/linux/linux_stats.c index 327343bd544f..8d562e0eff72 100644 --- a/sys/i386/linux/linux_stats.c +++ b/sys/i386/linux/linux_stats.c @@ -1,270 +1,297 @@ /*- * 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_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 #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include +#include struct linux_newstat { unsigned short stat_dev; unsigned short __pad1; unsigned long stat_ino; unsigned short stat_mode; unsigned short stat_nlink; unsigned short stat_uid; unsigned short stat_gid; unsigned short stat_rdev; unsigned short __pad2; unsigned long stat_size; unsigned long stat_blksize; unsigned long stat_blocks; unsigned long stat_atime; unsigned long __unused1; unsigned long stat_mtime; unsigned long __unused2; unsigned long stat_ctime; unsigned long __unused3; unsigned long __unused4; unsigned long __unused5; }; -struct linux_newstat_args { - char *path; - struct linux_newstat *buf; -}; static int newstat_copyout(struct stat *buf, void *ubuf) { struct linux_newstat tbuf; tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10); tbuf.stat_ino = buf->st_ino; tbuf.stat_mode = buf->st_mode; tbuf.stat_nlink = buf->st_nlink; tbuf.stat_uid = buf->st_uid; tbuf.stat_gid = buf->st_gid; tbuf.stat_rdev = buf->st_rdev; tbuf.stat_size = buf->st_size; tbuf.stat_atime = buf->st_atime; tbuf.stat_mtime = buf->st_mtime; tbuf.stat_ctime = buf->st_ctime; tbuf.stat_blksize = buf->st_blksize; tbuf.stat_blocks = buf->st_blocks; return copyout(&tbuf, ubuf, sizeof(tbuf)); } 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); #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; } +/* + * 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) return EBADF; switch (fp->f_type) { case DTYPE_VNODE: error = vn_stat((struct vnode *)fp->f_data, &buf, p); break; case DTYPE_SOCKET: error = soo_stat((struct socket *)fp->f_data, &buf); break; case DTYPE_PIPE: error = pipe_stat((struct pipe *)fp->f_data, &buf); break; default: panic("LINUX newfstat"); } if (!error) error = newstat_copyout(&buf, args->buf); return error; } -struct linux_statfs { +struct linux_statfs_buf { long ftype; long fbsize; long fblocks; long fbfree; long fbavail; long ffiles; long fffree; linux_fsid_t ffsid; long fnamelen; 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) { struct mount *mp; 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); #endif ndp = &nd; NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curproc); if (error = namei(ndp)) return error; mp = ndp->ni_vp->v_mount; bsd_statfs = &mp->mnt_stat; vrele(ndp->ni_vp); 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 printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd); #endif if (error = getvnode(p->p_fd, args->fd, &fp)) return error; mp = ((struct vnode *)fp->f_data)->v_mount; bsd_statfs = &mp->mnt_stat; 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 000000000000..6e0c5fdedd05 --- /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 0813e9b2a628..4e32271e8c71 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 #include #include -#include #include -#include - +#include #include -#include - -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 - 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 000000000000..92781027d986 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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 000000000000..1785fd315a10 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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/ibcs2/ibcs2_util.h b/sys/i386/linux/linux_util.h similarity index 82% copy from sys/i386/ibcs2/ibcs2_util.h copy to sys/i386/linux/linux_util.h index 67f859b3c9b4..46edfc52aae9 100644 --- a/sys/i386/ibcs2/ibcs2_util.h +++ b/sys/i386/linux/linux_util.h @@ -1,91 +1,92 @@ - /* * 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.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$ */ /* * This file is pretty much the same as Christos' svr4_util.h * (for now). */ -#ifndef _IBCS2_UTIL_H_ -#define _IBCS2_UTIL_H_ +#ifndef _LINUX_UTIL_H_ +#define _LINUX_UTIL_H_ #include #include #include #include #include +#include #include #ifndef SCARG #define SCARG(p, x) (p)->x #endif static __inline caddr_t stackgap_init(void); static __inline void *stackgap_alloc(caddr_t *, size_t); static __inline caddr_t stackgap_init() { -#define szsigcode ((caddr_t)(esigcode - sigcode)) - return (caddr_t)(ALIGN(((caddr_t)PS_STRINGS) - SPARE_USRSPACE)); +#define szsigcode (*(curproc->p_sysent->sv_szsigcode), sizeof(char *)) + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); } static __inline void * stackgap_alloc(sgp, sz) caddr_t *sgp; size_t sz; { void *p = (void *) *sgp; *sgp += ALIGN(sz); return p; } -#ifdef DEBUG_IBCS2 +#ifdef DEBUG_LINUX #define DPRINTF(a) printf a; #else #define DPRINTF(a) #endif -extern const char ibcs2_emul_path[]; +extern const char linux_emul_path[]; -int ibcs2_emul_find __P((struct proc *, caddr_t *, const char *, char *, +int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *, char **, int)); #define CHECKALTEXIST(p, sgp, path) \ - ibcs2_emul_find(p, sgp, ibcs2_emul_path, path, &(path), 0) + linux_emul_find(p, sgp, linux_emul_path, path, &(path), 0) #define CHECKALTCREAT(p, sgp, path) \ - ibcs2_emul_find(p, sgp, ibcs2_emul_path, path, &(path), 1) + linux_emul_find(p, sgp, linux_emul_path, path, &(path), 1) -#endif /* !_IBCS2_UTIL_H_ */ +#endif /* !_LINUX_UTIL_H_ */ diff --git a/sys/i386/linux/sysproto.h b/sys/i386/linux/sysproto.h deleted file mode 100644 index ea6ab5707aff..000000000000 --- 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_ */ diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 2bfc18828c23..d183a22aab50 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -1,211 +1,209 @@ /* * Copyright (c) 1993, David Greenman * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by David Greenman * 4. The name of the developer may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: imgact_aout.c,v 1.21 1995/12/15 02:57:40 peter Exp $ + * $Id: imgact_aout.c,v 1.22 1996/01/19 03:57:54 dyson Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int exec_aout_imgact __P((struct image_params *imgp)); static int exec_aout_imgact(imgp) struct image_params *imgp; { struct exec *a_out = (struct exec *) imgp->image_header; struct vmspace *vmspace = imgp->proc->p_vmspace; unsigned long vmaddr, virtual_offset; unsigned long file_offset; unsigned long bss_size; int error; -#if defined(COMPAT_LINUX) || defined(LINUX) /* * Linux and *BSD binaries look very much alike, * only the machine id is different: * 0x64 for Linux, 0x86 for *BSD, 0x00 for BSDI. */ if (((a_out->a_magic >> 16) & 0xff) != 0x86 && ((a_out->a_magic >> 16) & 0xff) != 0) return -1; -#endif /* COMPAT_LINUX || defined(LINUX) */ /* * Set file/virtual offset based on a.out variant. * We do two cases: host byte order and network byte order * (for NetBSD compatibility) */ switch ((int)(a_out->a_magic & 0xffff)) { case ZMAGIC: virtual_offset = 0; if (a_out->a_text) { file_offset = NBPG; } else { /* Bill's "screwball mode" */ file_offset = 0; } break; case QMAGIC: virtual_offset = NBPG; file_offset = 0; break; default: /* NetBSD compatibility */ switch ((int)(ntohl(a_out->a_magic) & 0xffff)) { case ZMAGIC: case QMAGIC: virtual_offset = NBPG; file_offset = 0; break; default: return (-1); } } bss_size = roundup(a_out->a_bss, NBPG); /* * Check various fields in header for validity/bounds. */ if (/* entry point must lay with text region */ a_out->a_entry < virtual_offset || a_out->a_entry >= virtual_offset + a_out->a_text || /* text and data size must each be page rounded */ a_out->a_text % NBPG || a_out->a_data % NBPG) return (-1); /* text + data can't exceed file size */ if (a_out->a_data + a_out->a_text > imgp->attr->va_size) return (EFAULT); /* * text/data/bss must not exceed limits */ if (/* text can't exceed maximum text size */ a_out->a_text > MAXTSIZ || /* data + bss can't exceed maximum data size */ a_out->a_data + bss_size > MAXDSIZ || /* data + bss can't exceed rlimit */ a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) return (ENOMEM); /* copy in arguments and/or environment from old process */ error = exec_extract_strings(imgp); if (error) return (error); /* * Destroy old process VM and create a new one (with a new stack) */ exec_new_vmspace(imgp); /* * Map text/data read/execute */ vmaddr = virtual_offset; error = vm_mmap(&vmspace->vm_map, /* map */ &vmaddr, /* address */ a_out->a_text + a_out->a_data, /* size */ VM_PROT_READ | VM_PROT_EXECUTE, /* protection */ VM_PROT_ALL, /* max protection */ MAP_PRIVATE | MAP_FIXED, /* flags */ (caddr_t)imgp->vp, /* vnode */ file_offset); /* offset */ if (error) return (error); /* * allow writing of data */ vm_map_protect(&vmspace->vm_map, vmaddr + a_out->a_text, vmaddr + a_out->a_text + a_out->a_data, VM_PROT_ALL, FALSE); if (bss_size != 0) { /* * Allocate demand-zeroed area for uninitialized data * "bss" = 'block started by symbol' - named after the IBM 7090 * instruction of the same name. */ vmaddr = virtual_offset + a_out->a_text + a_out->a_data; error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return (error); } /* Fill in process VM information */ vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT; vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT; vmspace->vm_taddr = (caddr_t) virtual_offset; vmspace->vm_daddr = (caddr_t) virtual_offset + a_out->a_text; /* Fill in image_params */ imgp->interpreted = 0; imgp->entry_addr = a_out->a_entry; imgp->proc->p_sysent = &aout_sysvec; /* Indicate that this file should not be modified */ imgp->vp->v_flag |= VTEXT; return (0); } /* * Tell kern_execve.c about it, with a little help from the linker. * Since `const' objects end up in the text segment, TEXT_SET is the * correct directive to use. */ static const struct execsw aout_execsw = { exec_aout_imgact, "a.out" }; TEXT_SET(execsw_set, aout_execsw); diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index ba630a758aba..77e5a30ff388 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -1,300 +1,289 @@ /* * System call switch table. * * DO NOT EDIT-- this file is automatically generated. * created from Id: syscalls.master,v 1.27 1996/03/02 16:51:25 peter Exp */ #include #include #include #include #include #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 /* The casts are bogus but will do for now. */ struct sysent sysent[] = { { 0, (sy_call_t *)nosys }, /* 0 = syscall */ { 1, (sy_call_t *)exit }, /* 1 = exit */ { 0, (sy_call_t *)fork }, /* 2 = fork */ { 3, (sy_call_t *)read }, /* 3 = read */ { 3, (sy_call_t *)write }, /* 4 = write */ { 3, (sy_call_t *)open }, /* 5 = open */ { 1, (sy_call_t *)close }, /* 6 = close */ { 4, (sy_call_t *)wait4 }, /* 7 = wait4 */ { compat(2,creat) }, /* 8 = old creat */ { 2, (sy_call_t *)link }, /* 9 = link */ { 1, (sy_call_t *)unlink }, /* 10 = unlink */ { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */ { 1, (sy_call_t *)chdir }, /* 12 = chdir */ { 1, (sy_call_t *)fchdir }, /* 13 = fchdir */ { 3, (sy_call_t *)mknod }, /* 14 = mknod */ { 2, (sy_call_t *)chmod }, /* 15 = chmod */ { 3, (sy_call_t *)chown }, /* 16 = chown */ { 1, (sy_call_t *)obreak }, /* 17 = break */ { 3, (sy_call_t *)getfsstat }, /* 18 = getfsstat */ { compat(3,lseek) }, /* 19 = old lseek */ { 0, (sy_call_t *)getpid }, /* 20 = getpid */ { 4, (sy_call_t *)mount }, /* 21 = mount */ { 2, (sy_call_t *)unmount }, /* 22 = unmount */ { 1, (sy_call_t *)setuid }, /* 23 = setuid */ { 0, (sy_call_t *)getuid }, /* 24 = getuid */ { 0, (sy_call_t *)geteuid }, /* 25 = geteuid */ { 4, (sy_call_t *)ptrace }, /* 26 = ptrace */ { 3, (sy_call_t *)recvmsg }, /* 27 = recvmsg */ { 3, (sy_call_t *)sendmsg }, /* 28 = sendmsg */ { 6, (sy_call_t *)recvfrom }, /* 29 = recvfrom */ { 3, (sy_call_t *)accept }, /* 30 = accept */ { 3, (sy_call_t *)getpeername }, /* 31 = getpeername */ { 3, (sy_call_t *)getsockname }, /* 32 = getsockname */ { 2, (sy_call_t *)access }, /* 33 = access */ { 2, (sy_call_t *)chflags }, /* 34 = chflags */ { 2, (sy_call_t *)fchflags }, /* 35 = fchflags */ { 0, (sy_call_t *)sync }, /* 36 = sync */ { 2, (sy_call_t *)kill }, /* 37 = kill */ { compat(2,stat) }, /* 38 = old stat */ { 0, (sy_call_t *)getppid }, /* 39 = getppid */ { compat(2,lstat) }, /* 40 = old lstat */ { 1, (sy_call_t *)dup }, /* 41 = dup */ { 0, (sy_call_t *)pipe }, /* 42 = pipe */ { 0, (sy_call_t *)getegid }, /* 43 = getegid */ { 4, (sy_call_t *)profil }, /* 44 = profil */ { 4, (sy_call_t *)ktrace }, /* 45 = ktrace */ { 3, (sy_call_t *)sigaction }, /* 46 = sigaction */ { 0, (sy_call_t *)getgid }, /* 47 = getgid */ { 2, (sy_call_t *)sigprocmask }, /* 48 = sigprocmask */ { 2, (sy_call_t *)getlogin }, /* 49 = getlogin */ { 1, (sy_call_t *)setlogin }, /* 50 = setlogin */ { 1, (sy_call_t *)acct }, /* 51 = acct */ { 0, (sy_call_t *)sigpending }, /* 52 = sigpending */ { 2, (sy_call_t *)sigaltstack }, /* 53 = sigaltstack */ { 3, (sy_call_t *)ioctl }, /* 54 = ioctl */ { 1, (sy_call_t *)reboot }, /* 55 = reboot */ { 1, (sy_call_t *)revoke }, /* 56 = revoke */ { 2, (sy_call_t *)symlink }, /* 57 = symlink */ { 3, (sy_call_t *)readlink }, /* 58 = readlink */ { 3, (sy_call_t *)execve }, /* 59 = execve */ { 1, (sy_call_t *)umask }, /* 60 = umask */ { 1, (sy_call_t *)chroot }, /* 61 = chroot */ { compat(2,fstat) }, /* 62 = old fstat */ { compat(4,getkerninfo) }, /* 63 = old getkerninfo */ { compat(0,getpagesize) }, /* 64 = old getpagesize */ { 3, (sy_call_t *)msync }, /* 65 = msync */ { 0, (sy_call_t *)vfork }, /* 66 = vfork */ { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */ { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */ { 1, (sy_call_t *)sbrk }, /* 69 = sbrk */ { 1, (sy_call_t *)sstk }, /* 70 = sstk */ { compat(6,mmap) }, /* 71 = old mmap */ { 1, (sy_call_t *)ovadvise }, /* 72 = vadvise */ { 2, (sy_call_t *)munmap }, /* 73 = munmap */ { 3, (sy_call_t *)mprotect }, /* 74 = mprotect */ { 3, (sy_call_t *)madvise }, /* 75 = madvise */ { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */ { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */ { 3, (sy_call_t *)mincore }, /* 78 = mincore */ { 2, (sy_call_t *)getgroups }, /* 79 = getgroups */ { 2, (sy_call_t *)setgroups }, /* 80 = setgroups */ { 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */ { 2, (sy_call_t *)setpgid }, /* 82 = setpgid */ { 3, (sy_call_t *)setitimer }, /* 83 = setitimer */ { compat(0,wait) }, /* 84 = old wait */ { 1, (sy_call_t *)swapon }, /* 85 = swapon */ { 2, (sy_call_t *)getitimer }, /* 86 = getitimer */ { compat(2,gethostname) }, /* 87 = old gethostname */ { compat(2,sethostname) }, /* 88 = old sethostname */ { 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */ { 2, (sy_call_t *)dup2 }, /* 90 = dup2 */ { 0, (sy_call_t *)nosys }, /* 91 = getdopt */ { 3, (sy_call_t *)fcntl }, /* 92 = fcntl */ { 5, (sy_call_t *)select }, /* 93 = select */ { 0, (sy_call_t *)nosys }, /* 94 = setdopt */ { 1, (sy_call_t *)fsync }, /* 95 = fsync */ { 3, (sy_call_t *)setpriority }, /* 96 = setpriority */ { 3, (sy_call_t *)socket }, /* 97 = socket */ { 3, (sy_call_t *)connect }, /* 98 = connect */ { compat(3,accept) }, /* 99 = old accept */ { 2, (sy_call_t *)getpriority }, /* 100 = getpriority */ { compat(4,send) }, /* 101 = old send */ { compat(4,recv) }, /* 102 = old recv */ { 1, (sy_call_t *)sigreturn }, /* 103 = sigreturn */ { 3, (sy_call_t *)bind }, /* 104 = bind */ { 5, (sy_call_t *)setsockopt }, /* 105 = setsockopt */ { 2, (sy_call_t *)listen }, /* 106 = listen */ { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */ { compat(3,sigvec) }, /* 108 = old sigvec */ { compat(1,sigblock) }, /* 109 = old sigblock */ { compat(1,sigsetmask) }, /* 110 = old sigsetmask */ { 1, (sy_call_t *)sigsuspend }, /* 111 = sigsuspend */ { compat(2,sigstack) }, /* 112 = old sigstack */ { compat(3,recvmsg) }, /* 113 = old recvmsg */ { compat(3,sendmsg) }, /* 114 = old sendmsg */ { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */ { 2, (sy_call_t *)gettimeofday }, /* 116 = gettimeofday */ { 2, (sy_call_t *)getrusage }, /* 117 = getrusage */ { 5, (sy_call_t *)getsockopt }, /* 118 = getsockopt */ { 0, (sy_call_t *)nosys }, /* 119 = resuba */ { 3, (sy_call_t *)readv }, /* 120 = readv */ { 3, (sy_call_t *)writev }, /* 121 = writev */ { 2, (sy_call_t *)settimeofday }, /* 122 = settimeofday */ { 3, (sy_call_t *)fchown }, /* 123 = fchown */ { 2, (sy_call_t *)fchmod }, /* 124 = fchmod */ { compat(6,recvfrom) }, /* 125 = old recvfrom */ { 2, (sy_call_t *)setreuid }, /* 126 = setreuid */ { 2, (sy_call_t *)setregid }, /* 127 = setregid */ { 2, (sy_call_t *)rename }, /* 128 = rename */ { compat(2,truncate) }, /* 129 = old truncate */ { compat(2,ftruncate) }, /* 130 = old ftruncate */ { 2, (sy_call_t *)flock }, /* 131 = flock */ { 2, (sy_call_t *)mkfifo }, /* 132 = mkfifo */ { 6, (sy_call_t *)sendto }, /* 133 = sendto */ { 2, (sy_call_t *)shutdown }, /* 134 = shutdown */ { 4, (sy_call_t *)socketpair }, /* 135 = socketpair */ { 2, (sy_call_t *)mkdir }, /* 136 = mkdir */ { 1, (sy_call_t *)rmdir }, /* 137 = rmdir */ { 2, (sy_call_t *)utimes }, /* 138 = utimes */ { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */ { 2, (sy_call_t *)adjtime }, /* 140 = adjtime */ { compat(3,getpeername) }, /* 141 = old getpeername */ { compat(0,gethostid) }, /* 142 = old gethostid */ { compat(1,sethostid) }, /* 143 = old sethostid */ { compat(2,getrlimit) }, /* 144 = old getrlimit */ { compat(2,setrlimit) }, /* 145 = old setrlimit */ { compat(2,killpg) }, /* 146 = old killpg */ { 0, (sy_call_t *)setsid }, /* 147 = setsid */ { 4, (sy_call_t *)quotactl }, /* 148 = quotactl */ { compat(0,quota) }, /* 149 = old quota */ { compat(3,getsockname) }, /* 150 = old getsockname */ { 0, (sy_call_t *)nosys }, /* 151 = sem_lock */ { 0, (sy_call_t *)nosys }, /* 152 = sem_wakeup */ { 0, (sy_call_t *)nosys }, /* 153 = asyncdaemon */ { 0, (sy_call_t *)nosys }, /* 154 = nosys */ #ifdef NFS { 2, (sy_call_t *)nfssvc }, /* 155 = nfssvc */ #else { 0, (sy_call_t *)nosys }, /* 155 = nosys */ #endif { compat(4,getdirentries) }, /* 156 = old getdirentries */ { 2, (sy_call_t *)statfs }, /* 157 = statfs */ { 2, (sy_call_t *)fstatfs }, /* 158 = fstatfs */ { 0, (sy_call_t *)nosys }, /* 159 = nosys */ { 0, (sy_call_t *)nosys }, /* 160 = nosys */ #if defined(NFS) && !defined (NFS_NOSERVER) { 2, (sy_call_t *)getfh }, /* 161 = getfh */ #else { 0, (sy_call_t *)nosys }, /* 161 = nosys */ #endif { 2, (sy_call_t *)getdomainname }, /* 162 = getdomainname */ { 2, (sy_call_t *)setdomainname }, /* 163 = setdomainname */ { 1, (sy_call_t *)uname }, /* 164 = uname */ { 2, (sy_call_t *)sysarch }, /* 165 = sysarch */ { 3, (sy_call_t *)rtprio }, /* 166 = rtprio */ { 0, (sy_call_t *)nosys }, /* 167 = nosys */ { 0, (sy_call_t *)nosys }, /* 168 = nosys */ { 5, (sy_call_t *)semsys }, /* 169 = semsys */ { 6, (sy_call_t *)msgsys }, /* 170 = msgsys */ { 4, (sy_call_t *)shmsys }, /* 171 = shmsys */ { 0, (sy_call_t *)nosys }, /* 172 = nosys */ { 0, (sy_call_t *)nosys }, /* 173 = nosys */ { 0, (sy_call_t *)nosys }, /* 174 = nosys */ { 0, (sy_call_t *)nosys }, /* 175 = nosys */ { 1, (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */ { 0, (sy_call_t *)nosys }, /* 177 = sfork */ { 0, (sy_call_t *)nosys }, /* 178 = getdescriptor */ { 0, (sy_call_t *)nosys }, /* 179 = setdescriptor */ { 0, (sy_call_t *)nosys }, /* 180 = nosys */ { 1, (sy_call_t *)setgid }, /* 181 = setgid */ { 1, (sy_call_t *)setegid }, /* 182 = setegid */ { 1, (sy_call_t *)seteuid }, /* 183 = seteuid */ #ifdef LFS { 3, (sy_call_t *)lfs_bmapv }, /* 184 = lfs_bmapv */ { 3, (sy_call_t *)lfs_markv }, /* 185 = lfs_markv */ { 2, (sy_call_t *)lfs_segclean }, /* 186 = lfs_segclean */ { 2, (sy_call_t *)lfs_segwait }, /* 187 = lfs_segwait */ #else { 0, (sy_call_t *)nosys }, /* 184 = nosys */ { 0, (sy_call_t *)nosys }, /* 185 = nosys */ { 0, (sy_call_t *)nosys }, /* 186 = nosys */ { 0, (sy_call_t *)nosys }, /* 187 = nosys */ #endif { 2, (sy_call_t *)stat }, /* 188 = stat */ { 2, (sy_call_t *)fstat }, /* 189 = fstat */ { 2, (sy_call_t *)lstat }, /* 190 = lstat */ { 2, (sy_call_t *)pathconf }, /* 191 = pathconf */ { 2, (sy_call_t *)fpathconf }, /* 192 = fpathconf */ { 0, (sy_call_t *)nosys }, /* 193 = nosys */ { 2, (sy_call_t *)getrlimit }, /* 194 = getrlimit */ { 2, (sy_call_t *)setrlimit }, /* 195 = setrlimit */ { 4, (sy_call_t *)getdirentries }, /* 196 = getdirentries */ { 8, (sy_call_t *)mmap }, /* 197 = mmap */ { 0, (sy_call_t *)nosys }, /* 198 = __syscall */ { 5, (sy_call_t *)lseek }, /* 199 = lseek */ { 4, (sy_call_t *)truncate }, /* 200 = truncate */ { 4, (sy_call_t *)ftruncate }, /* 201 = ftruncate */ { 6, (sy_call_t *)__sysctl }, /* 202 = __sysctl */ { 2, (sy_call_t *)mlock }, /* 203 = mlock */ { 2, (sy_call_t *)munlock }, /* 204 = munlock */ { 0, (sy_call_t *)nosys }, /* 205 = nosys */ { 0, (sy_call_t *)nosys }, /* 206 = nosys */ { 0, (sy_call_t *)nosys }, /* 207 = nosys */ { 0, (sy_call_t *)nosys }, /* 208 = nosys */ { 0, (sy_call_t *)nosys }, /* 209 = nosys */ { 0, (sy_call_t *)lkmnosys }, /* 210 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 211 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 212 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 213 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 214 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 215 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 216 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 217 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */ { 4, (sy_call_t *)__semctl }, /* 220 = __semctl */ { 3, (sy_call_t *)semget }, /* 221 = semget */ { 3, (sy_call_t *)semop }, /* 222 = semop */ { 1, (sy_call_t *)semconfig }, /* 223 = semconfig */ { 3, (sy_call_t *)msgctl }, /* 224 = msgctl */ { 2, (sy_call_t *)msgget }, /* 225 = msgget */ { 4, (sy_call_t *)msgsnd }, /* 226 = msgsnd */ { 5, (sy_call_t *)msgrcv }, /* 227 = msgrcv */ { 3, (sy_call_t *)shmat }, /* 228 = shmat */ { 3, (sy_call_t *)shmctl }, /* 229 = shmctl */ { 1, (sy_call_t *)shmdt }, /* 230 = shmdt */ { 3, (sy_call_t *)shmget }, /* 231 = shmget */ { 0, (sy_call_t *)nosys }, /* 232 = nosys */ { 0, (sy_call_t *)nosys }, /* 233 = nosys */ { 0, (sy_call_t *)nosys }, /* 234 = nosys */ { 0, (sy_call_t *)nosys }, /* 235 = nosys */ { 0, (sy_call_t *)nosys }, /* 236 = nosys */ { 0, (sy_call_t *)nosys }, /* 237 = nosys */ { 0, (sy_call_t *)nosys }, /* 238 = nosys */ { 0, (sy_call_t *)nosys }, /* 239 = nosys */ { 0, (sy_call_t *)nosys }, /* 240 = nosys */ { 0, (sy_call_t *)nosys }, /* 241 = nosys */ { 0, (sy_call_t *)nosys }, /* 242 = nosys */ { 0, (sy_call_t *)nosys }, /* 243 = nosys */ { 0, (sy_call_t *)nosys }, /* 244 = nosys */ { 0, (sy_call_t *)nosys }, /* 245 = nosys */ { 0, (sy_call_t *)nosys }, /* 246 = nosys */ { 0, (sy_call_t *)nosys }, /* 247 = nosys */ { 0, (sy_call_t *)nosys }, /* 248 = nosys */ { 0, (sy_call_t *)nosys }, /* 249 = nosys */ { 3, (sy_call_t *)minherit }, /* 250 = minherit */ { 1, (sy_call_t *)rfork }, /* 251 = rfork */ }; - -struct sysentvec aout_sysvec = { - sizeof (sysent) / sizeof (sysent[0]), - sysent, - 0, - 0, - 0, - 0, - 0, - 0 -}; diff --git a/sys/kern/init_sysvec.c b/sys/kern/init_sysvec.c new file mode 100644 index 000000000000..4ef3b16d79c0 --- /dev/null +++ b/sys/kern/init_sysvec.c @@ -0,0 +1,29 @@ +/* + * sysentvec for native FreeBSD a.out executable format. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sysentvec aout_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + sendsig, + sigcode, + &szsigcode, + 0, +}; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 9933183aff40..65fdaff03ad1 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,593 +1,603 @@ /* * Copyright (c) 1993, David Greenman * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by David Greenman * 4. The name of the developer 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: kern_exec.c,v 1.34 1996/01/20 21:36:30 bde Exp $ + * $Id: kern_exec.c,v 1.35 1996/02/24 14:32:52 peter Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int *exec_copyout_strings __P((struct image_params *)); static int exec_check_permissions(struct image_params *); /* * XXX trouble here if sizeof(caddr_t) != sizeof(int), other parts * of the sysctl code also assumes this, and sizeof(int) == sizeof(long). */ static caddr_t ps_strings = (caddr_t)PS_STRINGS; SYSCTL_INT(_kern, KERN_PS_STRINGS, ps_strings, 0, &ps_strings, 0, ""); static caddr_t usrstack = (caddr_t)USRSTACK; SYSCTL_INT(_kern, KERN_USRSTACK, usrstack, 0, &usrstack, 0, ""); /* * execsw_set is constructed for us by the linker. Each of the items * is a pointer to a `const struct execsw', hence the double pointer here. */ static const struct execsw **execsw = (const struct execsw **)&execsw_set.ls_items[0]; #ifndef _SYS_SYSPROTO_H_ struct execve_args { char *fname; char **argv; char **envv; }; #endif /* * execve() system call. */ int execve(p, uap, retval) struct proc *p; register struct execve_args *uap; int *retval; { struct nameidata nd, *ndp; int *stack_base; int error, len, i; struct image_params image_params, *imgp; struct vattr attr; imgp = &image_params; /* * Initialize part of the common data */ imgp->proc = p; imgp->uap = uap; imgp->attr = &attr; imgp->image_header = NULL; imgp->argc = imgp->envc = 0; imgp->entry_addr = 0; imgp->vmspace_destroyed = 0; imgp->interpreted = 0; imgp->interpreter_name[0] = '\0'; /* * Allocate temporary demand zeroed space for argument and * environment strings */ imgp->stringbase = (char *)kmem_alloc_pageable(exec_map, ARG_MAX); if (imgp->stringbase == NULL) { error = ENOMEM; goto exec_fail; } imgp->stringp = imgp->stringbase; imgp->stringspace = ARG_MAX; /* * Translate the file name. namei() returns a vnode pointer * in ni_vp amoung other things. */ ndp = &nd; NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_USERSPACE, uap->fname, p); interpret: error = namei(ndp); if (error) { kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); goto exec_fail; } imgp->vp = ndp->ni_vp; if (imgp->vp == NULL) { error = ENOEXEC; goto exec_fail_dealloc; } /* * Check file permissions (also 'opens' file) */ error = exec_check_permissions(imgp); /* * Lose the lock on the vnode. It's no longer needed, and must not * exist for the pagefault paging to work below. */ VOP_UNLOCK(imgp->vp); if (error) goto exec_fail_dealloc; /* * Map the image header (first page) of the file into * kernel address space */ error = vm_mmap(kernel_map, /* map */ (vm_offset_t *)&imgp->image_header, /* address */ PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ 0, /* flags */ (caddr_t)imgp->vp, /* vnode */ 0); /* offset */ if (error) { uprintf("mmap failed: %d\n",error); goto exec_fail_dealloc; } /* * Loop through list of image activators, calling each one. * If there is no match, the activator returns -1. If there * is a match, but there was an error during the activation, * the error is returned. Otherwise 0 means success. If the * image is interpreted, loop back up and try activating * the interpreter. */ for (i = 0; execsw[i]; ++i) { if (execsw[i]->ex_imgact) error = (*execsw[i]->ex_imgact)(imgp); else continue; if (error == -1) continue; if (error) goto exec_fail_dealloc; if (imgp->interpreted) { /* free old vnode and name buffer */ vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (1)"); /* set new name to that of the interpreter */ NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, p); goto interpret; } break; } /* If we made it through all the activators and none matched, exit. */ if (error == -1) { error = ENOEXEC; goto exec_fail_dealloc; } /* * Copy out strings (args and env) and initialize stack base */ stack_base = exec_copyout_strings(imgp); p->p_vmspace->vm_minsaddr = (char *)stack_base; /* * If custom stack fixup routine present for this process * let it do the stack setup. * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup) (*p->p_sysent->sv_fixup)(&stack_base, imgp); else suword(--stack_base, imgp->argc); /* close files on exec */ fdcloseexec(p); /* reset caught signals */ execsigs(p); /* name this process - nameiexec(p, ndp) */ len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN); bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len); p->p_comm[len] = 0; /* * mark as executable, wakeup any process that was vforked and tell * it that it now has it's own resources back */ p->p_flag |= P_EXEC; if (p->p_pptr && (p->p_flag & P_PPWAIT)) { p->p_flag &= ~P_PPWAIT; wakeup((caddr_t)p->p_pptr); } /* * Implement image setuid/setgid. Disallow if the process is * being traced. */ if ((attr.va_mode & (VSUID | VSGID)) && (p->p_flag & P_TRACED) == 0) { /* * Turn off syscall tracing for set-id programs, except for * root. */ if (p->p_tracep && suser(p->p_ucred, &p->p_acflag)) { p->p_traceflag = 0; vrele(p->p_tracep); p->p_tracep = NULL; } /* * Set the new credentials. */ p->p_ucred = crcopy(p->p_ucred); if (attr.va_mode & VSUID) p->p_ucred->cr_uid = attr.va_uid; if (attr.va_mode & VSGID) p->p_ucred->cr_groups[0] = attr.va_gid; p->p_flag |= P_SUGID; } else { p->p_flag &= ~P_SUGID; } /* * Implement correct POSIX saved-id behavior. */ p->p_cred->p_svuid = p->p_ucred->cr_uid; p->p_cred->p_svgid = p->p_ucred->cr_gid; /* * Store the vp for use in procfs */ if (p->p_textvp) /* release old reference */ vrele(p->p_textvp); VREF(ndp->ni_vp); p->p_textvp = ndp->ni_vp; /* * If tracing the process, trap to debugger so breakpoints * can be set before the program executes. */ if (p->p_flag & P_TRACED) psignal(p, SIGTRAP); /* clear "fork but no exec" flag, as we _are_ execing */ p->p_acflag &= ~AFORK; /* Set entry address */ setregs(p, imgp->entry_addr, (u_long)stack_base); /* * free various allocated resources */ kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (2)"); vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); return (0); exec_fail_dealloc: if (imgp->stringbase != NULL) kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); if (imgp->image_header && imgp->image_header != (char *)-1) if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (3)"); if (ndp->ni_vp) vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); exec_fail: if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ exit1(p, W_EXITCODE(0, SIGABRT)); /* NOT REACHED */ return(0); } else { return(error); } } /* * Destroy old address space, and allocate a new stack * The new stack is only SGROWSIZ large because it is grown * automatically in trap.c. */ int exec_new_vmspace(imgp) struct image_params *imgp; { int error; struct vmspace *vmspace = imgp->proc->p_vmspace; caddr_t stack_addr = (caddr_t) (USRSTACK - SGROWSIZ); imgp->vmspace_destroyed = 1; /* Blow away entire process VM */ if (vmspace->vm_shm) shmexit(imgp->proc); vm_map_remove(&vmspace->vm_map, 0, USRSTACK); /* Allocate a new stack */ error = vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *)&stack_addr, SGROWSIZ, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return(error); vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT; /* Initialize maximum stack address */ vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ; return(0); } /* * Copy out argument and environment strings from the old process * address space into the temporary string buffer. */ int exec_extract_strings(imgp) struct image_params *imgp; { char **argv, **envv; char *argp, *envp; int error, length; /* * extract arguments first */ argv = imgp->uap->argv; if (argv) { while ((argp = (caddr_t) fuword(argv++))) { if (argp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(argp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->argc++; } } /* * extract environment strings */ envv = imgp->uap->envv; if (envv) { while ((envp = (caddr_t) fuword(envv++))) { if (envp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(envp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->envc++; } } return (0); } /* * Copy strings out to the new process address space, constructing * new arg and env vector tables. Return a pointer to the base * so that it can be used as the initial stack pointer. */ int * exec_copyout_strings(imgp) struct image_params *imgp; { int argc, envc; char **vectp; char *stringp, *destp; int *stack_base; struct ps_strings *arginfo; + int szsigcode; /* * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. */ arginfo = PS_STRINGS; - destp = (caddr_t)arginfo - SPARE_USRSPACE - + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + /* * The '+ 2' is for the null pointers at the end of each of the * arg and env vector sets */ vectp = (char **) (destp - (imgp->argc + imgp->envc + 2) * sizeof(char *)); /* * vectp also becomes our initial stack base */ stack_base = (int *)vectp; stringp = imgp->stringbase; argc = imgp->argc; envc = imgp->envc; /* * Copy out strings - arguments and environment. */ copyout(stringp, destp, ARG_MAX - imgp->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. */ suword(&arginfo->ps_argvstr, (int)vectp); suword(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { suword(vectp++, (int)destp); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer seperates the argp's from the envp's */ suword(vectp++, NULL); suword(&arginfo->ps_envstr, (int)vectp); suword(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { suword(vectp++, (int)destp); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ suword(vectp, NULL); return (stack_base); } /* * Check permissions of file to execute. * Return 0 for success or error code on failure. */ static int exec_check_permissions(imgp) struct image_params *imgp; { struct proc *p = imgp->proc; struct vnode *vp = imgp->vp; struct vattr *attr = imgp->attr; int error; /* * Check number of open-for-writes on the file and deny execution * if there are any. */ if (vp->v_writecount) { return (ETXTBSY); } /* Get file attributes */ error = VOP_GETATTR(vp, attr, p->p_ucred, p); if (error) return (error); /* * 1) Check if file execution is disabled for the filesystem that this * file resides on. * 2) Insure that at least one execute bit is on - otherwise root * will always succeed, and we don't want to happen unless the * file really is executable. * 3) Insure that the file is a regular file. */ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr->va_mode & 0111) == 0) || (attr->va_type != VREG)) { return (EACCES); } /* * Zero length files can't be exec'd */ if (attr->va_size == 0) return (ENOEXEC); /* * Disable setuid/setgid if the filesystem prohibits it or if * the process is being traced. */ if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED)) attr->va_mode &= ~(VSUID | VSGID); /* * Check for execute permission to file based on current credentials. * Then call filesystem specific open routine (which does nothing * in the general case). */ error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) return (error); error = VOP_OPEN(vp, FREAD, p->p_ucred, p); if (error) return (error); return (0); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 0ccb77507ea6..fb0484e2b46e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,1270 +1,1272 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 - * $Id: kern_sig.c,v 1.17 1996/01/03 21:42:09 wollman Exp $ + * $Id: kern_sig.c,v 1.18 1996/01/31 12:44:13 davidg Exp $ */ #include "opt_ktrace.h" #define SIGPROP /* include signal properties table */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include #include #include /* for coredump */ static int coredump __P((struct proc *p)); static int killpg1 __P((struct proc *cp, int signum, int pgid, int all)); static void stop __P((struct proc *)); /* * Can process p, with pcred pc, send the signal signum to process q? */ #define CANSIGNAL(p, pc, q, signum) \ ((pc)->pc_ucred->cr_uid == 0 || \ (pc)->p_ruid == (q)->p_cred->p_ruid || \ (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ (pc)->p_ruid == (q)->p_ucred->cr_uid || \ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) #ifndef _SYS_SYSPROTO_H_ struct sigaction_args { int signum; struct sigaction *nsa; struct sigaction *osa; }; #endif /* ARGSUSED */ int sigaction(p, uap, retval) struct proc *p; register struct sigaction_args *uap; int *retval; { struct sigaction vec; register struct sigaction *sa; register struct sigacts *ps = p->p_sigacts; register int signum; int bit, error; signum = uap->signum; if (signum <= 0 || signum >= NSIG || signum == SIGKILL || signum == SIGSTOP) return (EINVAL); sa = &vec; if (uap->osa) { sa->sa_handler = ps->ps_sigact[signum]; sa->sa_mask = ps->ps_catchmask[signum]; bit = sigmask(signum); sa->sa_flags = 0; if ((ps->ps_sigonstack & bit) != 0) sa->sa_flags |= SA_ONSTACK; if ((ps->ps_sigintr & bit) == 0) sa->sa_flags |= SA_RESTART; if ((ps->ps_nodefer & bit) != 0) sa->sa_flags |= SA_NODEFER; if (p->p_flag & P_NOCLDSTOP) sa->sa_flags |= SA_NOCLDSTOP; if ((error = copyout((caddr_t)sa, (caddr_t)uap->osa, sizeof (vec)))) return (error); } if (uap->nsa) { if ((error = copyin((caddr_t)uap->nsa, (caddr_t)sa, sizeof (vec)))) return (error); setsigvec(p, signum, sa); } return (0); } void setsigvec(p, signum, sa) register struct proc *p; int signum; register struct sigaction *sa; { register struct sigacts *ps = p->p_sigacts; register int bit; bit = sigmask(signum); /* * Change setting atomically. */ (void) splhigh(); ps->ps_sigact[signum] = sa->sa_handler; ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask; if ((sa->sa_flags & SA_RESTART) == 0) ps->ps_sigintr |= bit; else ps->ps_sigintr &= ~bit; if (sa->sa_flags & SA_ONSTACK) ps->ps_sigonstack |= bit; else ps->ps_sigonstack &= ~bit; if (sa->sa_flags & SA_NODEFER) ps->ps_nodefer |= bit; else ps->ps_nodefer &= ~bit; #ifdef COMPAT_SUNOS if (sa->sa_flags & SA_USERTRAMP) ps->ps_usertramp |= bit; else ps->ps_usertramp &= ~bit; #endif if (signum == SIGCHLD) { if (sa->sa_flags & SA_NOCLDSTOP) p->p_flag |= P_NOCLDSTOP; else p->p_flag &= ~P_NOCLDSTOP; } /* * Set bit in p_sigignore for signals that are set to SIG_IGN, * and for signals set to SIG_DFL where the default is to ignore. * However, don't put SIGCONT in p_sigignore, * as we have to restart the process. */ if (sa->sa_handler == SIG_IGN || (sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) { p->p_siglist &= ~bit; /* never to be seen again */ if (signum != SIGCONT) p->p_sigignore |= bit; /* easier in psignal */ p->p_sigcatch &= ~bit; } else { p->p_sigignore &= ~bit; if (sa->sa_handler == SIG_DFL) p->p_sigcatch &= ~bit; else p->p_sigcatch |= bit; } (void) spl0(); } /* * Initialize signal state for process 0; * set to ignore signals that are ignored by default. */ void siginit(p) struct proc *p; { register int i; for (i = 0; i < NSIG; i++) if (sigprop[i] & SA_IGNORE && i != SIGCONT) p->p_sigignore |= sigmask(i); } /* * Reset signals for an exec of the specified process. */ void execsigs(p) register struct proc *p; { register struct sigacts *ps = p->p_sigacts; register int nc, mask; /* * Reset caught signals. Held signals remain held * through p_sigmask (unless they were caught, * and are now ignored by default). */ while (p->p_sigcatch) { nc = ffs((long)p->p_sigcatch); mask = sigmask(nc); p->p_sigcatch &= ~mask; if (sigprop[nc] & SA_IGNORE) { if (nc != SIGCONT) p->p_sigignore |= mask; p->p_siglist &= ~mask; } ps->ps_sigact[nc] = SIG_DFL; } /* * Reset stack state to the user stack. * Clear set of signals caught on the signal stack. */ - ps->ps_sigstk.ss_flags = SA_DISABLE; + ps->ps_sigstk.ss_flags = SS_DISABLE; ps->ps_sigstk.ss_size = 0; ps->ps_sigstk.ss_sp = 0; ps->ps_flags = 0; } /* * Manipulate signal mask. * Note that we receive new mask, not pointer, * and return old mask as return value; * the library stub does the rest. */ #ifndef _SYS_SYSPROTO_H_ struct sigprocmask_args { int how; sigset_t mask; }; #endif int sigprocmask(p, uap, retval) register struct proc *p; struct sigprocmask_args *uap; int *retval; { int error = 0; *retval = p->p_sigmask; (void) splhigh(); switch (uap->how) { case SIG_BLOCK: p->p_sigmask |= uap->mask &~ sigcantmask; break; case SIG_UNBLOCK: p->p_sigmask &= ~uap->mask; break; case SIG_SETMASK: p->p_sigmask = uap->mask &~ sigcantmask; break; default: error = EINVAL; break; } (void) spl0(); return (error); } #ifndef _SYS_SYSPROTO_H_ struct sigpending_args { int dummy; }; #endif /* ARGSUSED */ int sigpending(p, uap, retval) struct proc *p; struct sigpending_args *uap; int *retval; { *retval = p->p_siglist; return (0); } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) /* * Generalized interface signal handler, 4.3-compatible. */ #ifndef _SYS_SYSPROTO_H_ struct osigvec_args { int signum; struct sigvec *nsv; struct sigvec *osv; }; #endif /* ARGSUSED */ int osigvec(p, uap, retval) struct proc *p; register struct osigvec_args *uap; int *retval; { struct sigvec vec; register struct sigacts *ps = p->p_sigacts; register struct sigvec *sv; register int signum; int bit, error; signum = uap->signum; if (signum <= 0 || signum >= NSIG || signum == SIGKILL || signum == SIGSTOP) return (EINVAL); sv = &vec; if (uap->osv) { *(sig_t *)&sv->sv_handler = ps->ps_sigact[signum]; sv->sv_mask = ps->ps_catchmask[signum]; bit = sigmask(signum); sv->sv_flags = 0; if ((ps->ps_sigonstack & bit) != 0) sv->sv_flags |= SV_ONSTACK; if ((ps->ps_sigintr & bit) != 0) sv->sv_flags |= SV_INTERRUPT; #ifndef COMPAT_SUNOS if (p->p_flag & P_NOCLDSTOP) sv->sv_flags |= SA_NOCLDSTOP; #endif if ((error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)))) return (error); } if (uap->nsv) { if ((error = copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)))) return (error); #ifdef COMPAT_SUNOS - /* - * SunOS uses this bit (4, aka SA_DISABLE) as SV_RESETHAND, - * `reset to SIG_DFL on delivery'. We have no such option - * now or ever! - */ - if (sv->sv_flags & SA_DISABLE) - return (EINVAL); sv->sv_flags |= SA_USERTRAMP; #endif sv->sv_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */ setsigvec(p, signum, (struct sigaction *)sv); } return (0); } #ifndef _SYS_SYSPROTO_H_ struct osigblock_args { int mask; }; #endif int osigblock(p, uap, retval) register struct proc *p; struct osigblock_args *uap; int *retval; { (void) splhigh(); *retval = p->p_sigmask; p->p_sigmask |= uap->mask &~ sigcantmask; (void) spl0(); return (0); } #ifndef _SYS_SYSPROTO_H_ struct osigsetmask_args { int mask; }; #endif int osigsetmask(p, uap, retval) struct proc *p; struct osigsetmask_args *uap; int *retval; { (void) splhigh(); *retval = p->p_sigmask; p->p_sigmask = uap->mask &~ sigcantmask; (void) spl0(); return (0); } #endif /* COMPAT_43 || COMPAT_SUNOS */ /* * Suspend process until signal, providing mask to be set * in the meantime. Note nonstandard calling convention: * libc stub passes mask, not pointer, to save a copyin. */ #ifndef _SYS_SYSPROTO_H_ struct sigsuspend_args { sigset_t mask; }; #endif /* ARGSUSED */ int sigsuspend(p, uap, retval) register struct proc *p; struct sigsuspend_args *uap; int *retval; { register struct sigacts *ps = p->p_sigacts; /* * When returning from sigpause, we want * the old mask to be restored after the * signal handler has finished. Thus, we * save it here and mark the sigacts structure * to indicate this. */ ps->ps_oldmask = p->p_sigmask; ps->ps_flags |= SAS_OLDMASK; p->p_sigmask = uap->mask &~ sigcantmask; while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0) /* void */; /* always return EINTR rather than ERESTART... */ return (EINTR); } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) #ifndef _SYS_SYSPROTO_H_ struct osigstack_args { struct sigstack *nss; struct sigstack *oss; }; #endif /* ARGSUSED */ int osigstack(p, uap, retval) struct proc *p; register struct osigstack_args *uap; int *retval; { struct sigstack ss; struct sigacts *psp; int error = 0; psp = p->p_sigacts; ss.ss_sp = psp->ps_sigstk.ss_sp; - ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; + ss.ss_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss, sizeof (struct sigstack)))) return (error); if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss))) == 0) { psp->ps_sigstk.ss_sp = ss.ss_sp; psp->ps_sigstk.ss_size = 0; - psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK; + psp->ps_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK; psp->ps_flags |= SAS_ALTSTACK; } return (error); } #endif /* COMPAT_43 || COMPAT_SUNOS */ #ifndef _SYS_SYSPROTO_H_ struct sigaltstack_args { struct sigaltstack *nss; struct sigaltstack *oss; }; #endif /* ARGSUSED */ int sigaltstack(p, uap, retval) struct proc *p; register struct sigaltstack_args *uap; int *retval; { struct sigacts *psp; struct sigaltstack ss; int error; psp = p->p_sigacts; if ((psp->ps_flags & SAS_ALTSTACK) == 0) - psp->ps_sigstk.ss_flags |= SA_DISABLE; + psp->ps_sigstk.ss_flags |= SS_DISABLE; if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk, (caddr_t)uap->oss, sizeof (struct sigaltstack)))) return (error); if (uap->nss == 0) return (0); if ((error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)))) return (error); - if (ss.ss_flags & SA_DISABLE) { - if (psp->ps_sigstk.ss_flags & SA_ONSTACK) + if (ss.ss_flags & SS_DISABLE) { + if (psp->ps_sigstk.ss_flags & SS_ONSTACK) return (EINVAL); psp->ps_flags &= ~SAS_ALTSTACK; psp->ps_sigstk.ss_flags = ss.ss_flags; return (0); } if (ss.ss_size < MINSIGSTKSZ) return (ENOMEM); psp->ps_flags |= SAS_ALTSTACK; psp->ps_sigstk= ss; return (0); } /* * Common code for kill process group/broadcast kill. * cp is calling process. */ int killpg1(cp, signum, pgid, all) register struct proc *cp; int signum, pgid, all; { register struct proc *p; register struct pcred *pc = cp->p_cred; struct pgrp *pgrp; int nfound = 0; if (all) /* * broadcast */ for (p = (struct proc *)allproc; p != NULL; p = p->p_next) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp || !CANSIGNAL(cp, pc, p, signum)) continue; nfound++; if (signum) psignal(p, signum); } else { if (pgid == 0) /* * zero pgid means send to my process group. */ pgrp = cp->p_pgrp; else { pgrp = pgfind(pgid); if (pgrp == NULL) return (ESRCH); } for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p->p_stat == SZOMB || !CANSIGNAL(cp, pc, p, signum)) continue; nfound++; if (signum) psignal(p, signum); } } return (nfound ? 0 : ESRCH); } #ifndef _SYS_SYSPROTO_H_ struct kill_args { int pid; int signum; }; #endif /* ARGSUSED */ int kill(cp, uap, retval) register struct proc *cp; register struct kill_args *uap; int *retval; { register struct proc *p; register struct pcred *pc = cp->p_cred; if ((u_int)uap->signum >= NSIG) return (EINVAL); if (uap->pid > 0) { /* kill single process */ if ((p = pfind(uap->pid)) == NULL) return (ESRCH); if (!CANSIGNAL(cp, pc, p, uap->signum)) return (EPERM); if (uap->signum) psignal(p, uap->signum); return (0); } switch (uap->pid) { case -1: /* broadcast signal */ return (killpg1(cp, uap->signum, 0, 1)); case 0: /* signal own process group */ return (killpg1(cp, uap->signum, 0, 0)); default: /* negative explicit process group */ return (killpg1(cp, uap->signum, -uap->pid, 0)); } /* NOTREACHED */ } #if defined(COMPAT_43) || defined(COMPAT_SUNOS) #ifndef _SYS_SYSPROTO_H_ struct okillpg_args { int pgid; int signum; }; #endif /* ARGSUSED */ int okillpg(p, uap, retval) struct proc *p; register struct okillpg_args *uap; int *retval; { if ((u_int)uap->signum >= NSIG) return (EINVAL); return (killpg1(p, uap->signum, uap->pgid, 0)); } #endif /* COMPAT_43 || COMPAT_SUNOS */ /* * Send a signal to a process group. */ void gsignal(pgid, signum) int pgid, signum; { struct pgrp *pgrp; if (pgid && (pgrp = pgfind(pgid))) pgsignal(pgrp, signum, 0); } /* * Send a signal to a process group. If checktty is 1, * limit to members which have a controlling terminal. */ void pgsignal(pgrp, signum, checkctty) struct pgrp *pgrp; int signum, checkctty; { register struct proc *p; if (pgrp) for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) if (checkctty == 0 || p->p_flag & P_CONTROLT) psignal(p, signum); } /* * Send a signal caused by a trap to the current process. * If it will be caught immediately, deliver it with correct code. * Otherwise, post it normally. */ void trapsignal(p, signum, code) struct proc *p; register int signum; u_int code; { register struct sigacts *ps = p->p_sigacts; int mask; mask = sigmask(signum); if ((p->p_flag & P_TRACED) == 0 && (p->p_sigcatch & mask) != 0 && (p->p_sigmask & mask) == 0) { p->p_stats->p_ru.ru_nsignals++; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) ktrpsig(p->p_tracep, signum, ps->ps_sigact[signum], p->p_sigmask, code); #endif - sendsig(ps->ps_sigact[signum], signum, p->p_sigmask, code); + (*p->p_sysent->sv_sendsig)(ps->ps_sigact[signum], signum, + p->p_sigmask, code); p->p_sigmask |= ps->ps_catchmask[signum] | (mask & ~ps->ps_nodefer); } else { ps->ps_code = code; /* XXX for core dump/debugger */ psignal(p, signum); } } /* * Send the signal to the process. If the signal has an action, the action * is usually performed by the target process rather than the caller; we add * the signal to the set of pending signals for the process. * * Exceptions: * o When a stop signal is sent to a sleeping process that takes the * default action, the process is stopped without awakening it. * o SIGCONT restarts stopped processes (or puts them back to sleep) * regardless of the signal action (eg, blocked or ignored). * * Other ignored signals are discarded immediately. */ void psignal(p, signum) register struct proc *p; register int signum; { register int s, prop; register sig_t action; int mask; if ((u_int)signum >= NSIG || signum == 0) panic("psignal signal number"); mask = sigmask(signum); prop = sigprop[signum]; /* * If proc is traced, always give parent a chance. */ if (p->p_flag & P_TRACED) action = SIG_DFL; else { /* * If the signal is being ignored, * then we forget about it immediately. * (Note: we don't set SIGCONT in p_sigignore, * and if it is set to SIG_IGN, * action will be SIG_DFL here.) */ if (p->p_sigignore & mask) return; if (p->p_sigmask & mask) action = SIG_HOLD; else if (p->p_sigcatch & mask) action = SIG_CATCH; else action = SIG_DFL; } if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) && (p->p_flag & P_TRACED) == 0) p->p_nice = NZERO; if (prop & SA_CONT) p->p_siglist &= ~stopsigmask; if (prop & SA_STOP) { /* * If sending a tty stop signal to a member of an orphaned * process group, discard the signal here if the action * is default; don't stop the process below if sleeping, * and don't clear any pending SIGCONT. */ if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 && action == SIG_DFL) return; p->p_siglist &= ~contsigmask; } p->p_siglist |= mask; /* * Defer further processing for signals which are held, * except that stopped processes must be continued by SIGCONT. */ if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP)) return; s = splhigh(); switch (p->p_stat) { case SSLEEP: /* * If process is sleeping uninterruptibly * we can't interrupt the sleep... the signal will * be noticed when the process returns through * trap() or syscall(). */ if ((p->p_flag & P_SINTR) == 0) goto out; /* * Process is sleeping and traced... make it runnable * so it can discover the signal in issignal() and stop * for the parent. */ if (p->p_flag & P_TRACED) goto run; /* * If SIGCONT is default (or ignored) and process is * asleep, we are finished; the process should not * be awakened. */ if ((prop & SA_CONT) && action == SIG_DFL) { p->p_siglist &= ~mask; goto out; } /* * When a sleeping process receives a stop * signal, process immediately if possible. * All other (caught or default) signals * cause the process to run. */ if (prop & SA_STOP) { if (action != SIG_DFL) goto runfast; /* * If a child holding parent blocked, * stopping could cause deadlock. */ if (p->p_flag & P_PPWAIT) goto out; p->p_siglist &= ~mask; p->p_xstat = signum; if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); stop(p); goto out; } else goto runfast; /*NOTREACHED*/ case SSTOP: /* * If traced process is already stopped, * then no further action is necessary. */ if (p->p_flag & P_TRACED) goto out; /* * Kill signal always sets processes running. */ if (signum == SIGKILL) goto runfast; if (prop & SA_CONT) { /* * If SIGCONT is default (or ignored), we continue the * process but don't leave the signal in p_siglist, as * it has no further action. If SIGCONT is held, we * continue the process and leave the signal in * p_siglist. If the process catches SIGCONT, let it * handle the signal itself. If it isn't waiting on * an event, then it goes back to run state. * Otherwise, process goes back to sleep state. */ if (action == SIG_DFL) p->p_siglist &= ~mask; if (action == SIG_CATCH) goto runfast; if (p->p_wchan == 0) goto run; p->p_stat = SSLEEP; goto out; } if (prop & SA_STOP) { /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ p->p_siglist &= ~mask; /* take it away */ goto out; } /* * If process is sleeping interruptibly, then simulate a * wakeup so that when it is continued, it will be made * runnable and can look at the signal. But don't make * the process runnable, leave it stopped. */ if (p->p_wchan && p->p_flag & P_SINTR) unsleep(p); goto out; default: /* * SRUN, SIDL, SZOMB do nothing with the signal, * other than kicking ourselves if we are running. * It will either never be noticed, or noticed very soon. */ if (p == curproc) signotify(p); goto out; } /*NOTREACHED*/ runfast: /* * Raise priority to at least PUSER. */ if (p->p_priority > PUSER) p->p_priority = PUSER; run: setrunnable(p); out: splx(s); } /* * If the current process has received a signal (should be caught or cause * termination, should interrupt current syscall), return the signal number. * Stop signals with default action are processed immediately, then cleared; * they aren't returned. This is checked after each entry to the system for * a syscall or trap (though this can usually be done without calling issignal * by checking the pending signal masks in the CURSIG macro.) The normal call * sequence is * * while (signum = CURSIG(curproc)) * postsig(signum); */ int issignal(p) register struct proc *p; { register int signum, mask, prop; for (;;) { mask = p->p_siglist & ~p->p_sigmask; if (p->p_flag & P_PPWAIT) mask &= ~stopsigmask; if (mask == 0) /* no signal to send */ return (0); signum = ffs((long)mask); mask = sigmask(signum); prop = sigprop[signum]; /* * We should see pending but ignored signals * only if P_TRACED was on when they were posted. */ if (mask & p->p_sigignore && (p->p_flag & P_TRACED) == 0) { p->p_siglist &= ~mask; continue; } if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) { /* * If traced, always stop, and stay * stopped until released by the parent. */ p->p_xstat = signum; psignal(p->p_pptr, SIGCHLD); do { stop(p); mi_switch(); } while (!trace_req(p) && p->p_flag & P_TRACED); /* * If the traced bit got turned off, go back up * to the top to rescan signals. This ensures * that p_sig* and ps_sigact are consistent. */ if ((p->p_flag & P_TRACED) == 0) continue; /* * If parent wants us to take the signal, * then it will leave it in p->p_xstat; * otherwise we just look for signals again. */ p->p_siglist &= ~mask; /* clear the old signal */ signum = p->p_xstat; if (signum == 0) continue; /* * Put the new signal into p_siglist. If the * signal is being masked, look for other signals. */ mask = sigmask(signum); p->p_siglist |= mask; if (p->p_sigmask & mask) continue; } /* * Decide whether the signal should be returned. * Return the signal's number, or fall through * to clear it from the pending mask. */ switch ((int)p->p_sigacts->ps_sigact[signum]) { case (int)SIG_DFL: /* * Don't take default actions on system processes. */ if (p->p_pid <= 1) { #ifdef DIAGNOSTIC /* * Are you sure you want to ignore SIGSEGV * in init? XXX */ printf("Process (pid %lu) got signal %d\n", (u_long)p->p_pid, signum); #endif break; /* == ignore */ } /* * If there is a pending stop signal to process * with default action, stop here, * then clear the signal. However, * if process is member of an orphaned * process group, ignore tty stop signals. */ if (prop & SA_STOP) { if (p->p_flag & P_TRACED || (p->p_pgrp->pg_jobc == 0 && prop & SA_TTYSTOP)) break; /* == ignore */ p->p_xstat = signum; stop(p); if ((p->p_pptr->p_flag & P_NOCLDSTOP) == 0) psignal(p->p_pptr, SIGCHLD); mi_switch(); break; } else if (prop & SA_IGNORE) { /* * Except for SIGCONT, shouldn't get here. * Default action is to ignore; drop it. */ break; /* == ignore */ } else return (signum); /*NOTREACHED*/ case (int)SIG_IGN: /* * Masking above should prevent us ever trying * to take action on an ignored signal other * than SIGCONT, unless process is traced. */ if ((prop & SA_CONT) == 0 && (p->p_flag & P_TRACED) == 0) printf("issignal\n"); break; /* == ignore */ default: /* * This signal has an action, let * postsig() process it. */ return (signum); } p->p_siglist &= ~mask; /* take the signal! */ } /* NOTREACHED */ } /* * Put the argument process into the stopped state and notify the parent * via wakeup. Signals are handled elsewhere. The process must not be * on the run queue. */ void stop(p) register struct proc *p; { p->p_stat = SSTOP; p->p_flag &= ~P_WAITED; wakeup((caddr_t)p->p_pptr); } /* * Take the action for the specified signal * from the current set of pending signals. */ void postsig(signum) register int signum; { register struct proc *p = curproc; register struct sigacts *ps = p->p_sigacts; register sig_t action; int code, mask, returnmask; #ifdef DIAGNOSTIC if (signum == 0) panic("postsig"); #endif mask = sigmask(signum); p->p_siglist &= ~mask; action = ps->ps_sigact[signum]; #ifdef KTRACE if (KTRPOINT(p, KTR_PSIG)) ktrpsig(p->p_tracep, signum, action, ps->ps_flags & SAS_OLDMASK ? ps->ps_oldmask : p->p_sigmask, 0); #endif if (action == SIG_DFL) { /* * Default action, where the default is to kill * the process. (Other cases were ignored above.) */ sigexit(p, signum); /* NOTREACHED */ } else { /* * If we get here, the signal must be caught. */ #ifdef DIAGNOSTIC if (action == SIG_IGN || (p->p_sigmask & mask)) panic("postsig action"); #endif /* * Set the new mask value and also defer further * occurences of this signal. * * Special case: user has done a sigpause. Here the * current mask is not of interest, but rather the * mask from before the sigpause is what we want * restored after the signal processing is completed. */ (void) splhigh(); if (ps->ps_flags & SAS_OLDMASK) { returnmask = ps->ps_oldmask; ps->ps_flags &= ~SAS_OLDMASK; } else returnmask = p->p_sigmask; p->p_sigmask |= ps->ps_catchmask[signum] | (mask & ~ps->ps_nodefer); (void) spl0(); p->p_stats->p_ru.ru_nsignals++; if (ps->ps_sig != signum) { code = 0; } else { code = ps->ps_code; ps->ps_code = 0; } - sendsig(action, signum, returnmask, code); + (*p->p_sysent->sv_sendsig)(action, signum, returnmask, code); } } /* * Kill the current process for stated reason. */ void killproc(p, why) struct proc *p; char *why; { log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm, p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, why); psignal(p, SIGKILL); } /* * Force the current process to exit with the specified signal, dumping core * if appropriate. We bypass the normal tests for masked and caught signals, * allowing unrecoverable failures to terminate the process without changing * signal state. Mark the accounting record with the signal termination. * If dumping core, save the signal number for the debugger. Calls exit and * does not return. */ void sigexit(p, signum) register struct proc *p; int signum; { p->p_acflag |= AXSIG; if (sigprop[signum] & SA_CORE) { p->p_sigacts->ps_sig = signum; /* * Log signals which would cause core dumps * (Log as LOG_INFO to appease those who don't want * these messages.) * XXX : Todo, as well as euid, write out ruid too */ log(LOG_INFO, "pid %d (%s), uid %d: exited on signal %d\n", p->p_pid, p->p_comm, p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, signum); if (coredump(p) == 0) signum |= WCOREFLAG; } exit1(p, W_EXITCODE(0, signum)); /* NOTREACHED */ } /* * Dump core, into a file named "progname.core", unless the process was * setuid/setgid. */ static int coredump(p) register struct proc *p; { register struct vnode *vp; register struct pcred *pcred = p->p_cred; register struct ucred *cred = pcred->pc_ucred; register struct vmspace *vm = p->p_vmspace; struct nameidata nd; struct vattr vattr; int error, error1; char name[MAXCOMLEN+6]; /* progname.core */ + /* + * If we are setuid/setgid, or if we've changed uid's in the past, + * we may be holding privileged information. We must not core! + */ if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid) return (EFAULT); + if (p->p_flag & P_SUGID) + return (EFAULT); if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= p->p_rlimit[RLIMIT_CORE].rlim_cur) return (EFAULT); sprintf(name, "%s.core", p->p_comm); NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); if ((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR))) return (error); vp = nd.ni_vp; /* Don't dump to non-regular files or files with links. */ if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) { error = EFAULT; goto out; } VATTR_NULL(&vattr); vattr.va_size = 0; LEASE_CHECK(vp, p, cred, LEASE_WRITE); VOP_SETATTR(vp, &vattr, cred, p); p->p_acflag |= ACORE; bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); error = cpu_coredump(p, vp, cred); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); if (error == 0) error = vn_rdwr(UIO_WRITE, vp, (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), round_page(ctob(vm->vm_ssize)), (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); out: VOP_UNLOCK(vp); error1 = vn_close(vp, FWRITE, cred, p); if (error == 0) error = error1; return (error); } /* * Nonexistent system call-- signal process (may want to handle it). * Flag error in case process won't see signal immediately (blocked or ignored). */ #ifndef _SYS_SYSPROTO_H_ struct nosys_args { int dummy; }; #endif /* ARGSUSED */ int nosys(p, args, retval) struct proc *p; struct nosys_args *args; int *retval; { psignal(p, SIGSYS); return (EINVAL); } diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 976f04234aac..d871d3583a28 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -1,373 +1,361 @@ #! /bin/sh - # @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93 -# $Id: makesyscalls.sh,v 1.15 1995/10/07 06:24:07 swallace Exp $ +# $Id: makesyscalls.sh,v 1.16 1995/10/07 23:56:18 swallace Exp $ set -e # name of compat option: compat=COMPAT_43 # output files: sysnames="syscalls.c" sysproto="../sys/sysproto.h" sysproto_h=_SYS_SYSPROTO_H_ syshdr="../sys/syscall.h" syssw="init_sysent.c" syshide="../sys/syscall-hide.h" syscallprefix="SYS_" switchname="sysent" namesname="syscallnames" -sysvec="" # tmp files: sysdcl="sysent.dcl" syscompat="sysent.compat" syscompatdcl="sysent.compatdcl" sysent="sysent.switch" sysinc="sysinc.switch" sysarg="sysarg.switch" trap "rm $sysdcl $syscompat $syscompatdcl $sysent $sysinc $sysarg" 0 case $# in 0) echo "Usage: $0 input-file " 1>&2 exit 1 ;; esac if [ -f $2 ]; then . $2 fi sed -e ' s/\$//g :join /\\$/{a\ N s/\\\n// b join } 2,${ /^#/!s/\([{}()*,]\)/ \1 /g } ' < $1 | awk " BEGIN { sysdcl = \"$sysdcl\" sysproto = \"$sysproto\" sysproto_h = \"$sysproto_h\" syscompat = \"$syscompat\" syscompatdcl = \"$syscompatdcl\" sysent = \"$sysent\" sysinc = \"$sysinc\" sysarg = \"$sysarg\" sysnames = \"$sysnames\" syshdr = \"$syshdr\" compat = \"$compat\" syshide = \"$syshide\" syscallprefix = \"$syscallprefix\" switchname = \"$switchname\" namesname = \"$namesname\" - sysvec = \"$sysvec\" infile = \"$1\" "' printf "/*\n * System call switch table.\n *\n" > sysinc printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysinc printf "/*\n * System call prototypes.\n *\n" > sysarg printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarg printf "\n#ifdef %s\n\n", compat > syscompat printf "/*\n * System call names.\n *\n" > sysnames printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames printf "/*\n * System call numbers.\n *\n" > syshdr printf " * DO NOT EDIT-- this file is automatically generated.\n" > syshdr printf "/*\n * System call hiders.\n *\n" > syshide printf " * DO NOT EDIT-- this file is automatically generated.\n" > syshide } NR == 1 { gsub("[$]Id: ", "", $0) gsub(" [$]", "", $0) printf " * created from%s\n */\n\n", $0 > sysinc printf "\n#ifdef %s\n", compat > sysent printf "#define compat(n, name) n, (sy_call_t *)__CONCAT(o,name)\n" > sysent printf("#else\n") > sysent printf("#define compat(n, name) 0, (sy_call_t *)nosys\n") > sysent printf("#endif\n\n") > sysent printf("/* The casts are bogus but will do for now. */\n") > sysent printf "struct sysent %s[] = {\n",switchname > sysent printf " * created from%s\n */\n\n", $0 > sysarg printf("#ifndef %s\n", sysproto_h) > sysarg printf("#define\t%s\n\n", sysproto_h) > sysarg printf "#include \n", $0 > sysarg printf "#include \n", $0 > sysarg printf "#include \n\n", $0 > sysarg printf " * created from%s\n */\n\n", $0 > sysnames printf "char *%s[] = {\n", namesname > sysnames printf " * created from%s\n */\n\n", $0 > syshdr printf " * created from%s\n */\n\n", $0 > syshide next } NF == 0 || $1 ~ /^;/ { next } $1 ~ /^#[ ]*include/ { print > sysinc next } $1 ~ /^#[ ]*if/ { print > sysent print > sysdcl print > sysarg print > syscompat print > sysnames print > syshide savesyscall = syscall next } $1 ~ /^#[ ]*else/ { print > sysent print > sysdcl print > sysarg print > syscompat print > sysnames print > syshide syscall = savesyscall next } $1 ~ /^#/ { print > sysent print > sysdcl print > sysarg print > syscompat print > sysnames print > syshide next } syscall != $1 { printf "%s: line %d: syscall number out of sync at %d\n", \ infile, NR, syscall printf "line is:\n" print exit 1 } function parserr(was, wanted) { printf "%s: line %d: unexpected %s (expected %s)\n", \ infile, NR, was, wanted exit 1 } function parseline() { f=4 # toss number and type argc= 0; bigargc = 0; if ($NF != "}") { funcalias=$(NF-2) argalias=$(NF-1) rettype=$NF end=NF-3 } else { funcalias="" argalias="" rettype="int" end=NF } if ($2 == "NODEF") { funcname=$4 return } if ($f != "{") parserr($f, "{") f++ if ($end != "}") parserr($end, "}") end-- if ($end != ";") parserr($end, ";") end-- if ($end != ")") parserr($end, ")") end-- f++ #function return type funcname=$f if (funcalias == "") funcalias = funcname if (argalias == "") { argalias = funcname "_args" if ($2 == "COMPAT") argalias = "o" argalias } f++ if ($f != "(") parserr($f, ")") f++ if (f == end) { if ($f != "void") parserr($f, "argument definition") return } while (f <= end) { argc++ argtype[argc]="" oldf="" while (f < end && $(f+1) != ",") { if (argtype[argc] != "" && oldf != "*") argtype[argc] = argtype[argc]" "; argtype[argc] = argtype[argc]$f; oldf = $f; f++ } if (argtype[argc] == "") parserr($f, "argument definition") if (argtype[argc] == "off_t") bigargc++ argname[argc]=$f; f += 2; # skip name, and any comma } } { comment = $4 if (NF < 7) for (i = 5; i <= NF; i++) comment = comment " " $i } $2 == "STD" || $2 == "NODEF" || $2 == "NOARGS" || $2 == "NOPROTO" { parseline() if ((!nosys || funcname != "nosys") && \ (funcname != "lkmnosys")) { if (argc != 0 && $2 != "NOARGS" && $2 != "NOPROTO") { printf("struct\t%s {\n", argalias) > sysarg for (i = 1; i <= argc; i++) printf("\t%s %s;\n", argtype[i], argname[i]) > sysarg printf("};\n") > sysarg } else if($2 != "NOARGS" && $2 != "NOPROTO") printf("struct\t%s {\n\tint dummy;\n};\n", \ argalias) > sysarg } if ($2 != "NOPROTO" && (!nosys || funcname != "nosys") && \ (!lkmnosys || funcname != "lkmnosys")) { if (funcname == "exit") printf("__dead ") > sysdcl printf("%s\t%s __P((struct proc *, struct %s *, int []));\n", \ rettype, funcname, argalias) > sysdcl } if (funcname == "nosys") nosys = 1 if (funcname == "lkmnosys") lkmnosys = 1 printf("\t{ %d, (sy_call_t *)%s },\t\t", \ argc+bigargc, funcname) > sysent if(length(funcname) < 11) printf("\t") > sysent printf("/* %d = %s */\n", syscall, funcalias) > sysent printf("\t\"%s\",\t\t\t/* %d = %s */\n", \ funcalias, syscall, funcalias) > sysnames if ($2 != "NODEF") printf("#define\t%s%s\t%d\n", syscallprefix, \ funcalias, syscall) > syshdr if ($3 != "NOHIDE") printf("HIDE_%s(%s)\n", $3, funcname) > syshide syscall++ next } $2 == "COMPAT" || $2 == "CPT_NOA" { parseline() if (argc != 0 && $2 != "CPT_NOA") { printf("struct\t%s {\n", argalias) > syscompat for (i = 1; i <= argc; i++) printf("\t%s %s;\n", argtype[i], argname[i]) > syscompat printf("};\n") > syscompat } else if($2 != "CPT_NOA") printf("struct\t%s {\n\tint dummy;\n};\n", \ argalias) > sysarg printf("%s\to%s __P((struct proc *, struct %s *, int []));\n", \ rettype, funcname, argalias) > syscompatdcl printf("\t{ compat(%d,%s) },\t\t/* %d = old %s */\n", \ argc+bigargc, funcname, syscall, funcalias) > sysent printf("\t\"old.%s\",\t\t/* %d = old %s */\n", \ funcalias, syscall, funcalias) > sysnames printf("\t\t\t\t/* %d is old %s */\n", \ syscall, funcalias) > syshdr if ($3 != "NOHIDE") printf("HIDE_%s(%s)\n", $3, funcname) > syshide syscall++ next } $2 == "LIBCOMPAT" { parseline() printf("%s\to%s();\n", rettype, funcname) > syscompatdcl printf("\t{ compat(%d,%s) },\t\t/* %d = old %s */\n", \ argc+bigargc, funcname, syscall, funcalias) > sysent printf("\t\"old.%s\",\t\t/* %d = old %s */\n", \ funcalias, syscall, funcalias) > sysnames printf("#define\t%s%s\t%d\t/* compatibility; still used by libc */\n", \ syscallprefix, funcalias, syscall) > syshdr if ($3 != "NOHIDE") printf("HIDE_%s(%s)\n", $3, funcname) > syshide syscall++ next } $2 == "OBSOL" { printf("\t{ 0, (sy_call_t *)nosys },\t\t\t/* %d = obsolete %s */\n", \ syscall, comment) > sysent printf("\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n", \ $4, syscall, comment) > sysnames printf("\t\t\t\t/* %d is obsolete %s */\n", \ syscall, comment) > syshdr if ($3 != "NOHIDE") printf("HIDE_%s(%s)\n", $3, $4) > syshide syscall++ next } $2 == "UNIMPL" { printf("\t{ 0, (sy_call_t *)nosys },\t\t\t/* %d = %s */\n", \ syscall, comment) > sysent printf("\t\"#%d\",\t\t\t/* %d = %s */\n", \ syscall, syscall, comment) > sysnames if ($3 != "NOHIDE") printf("HIDE_%s(%s)\n", $3, $4) > syshide syscall++ next } { printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2 exit 1 } END { printf("\n#endif /* %s */\n", compat) > syscompatdcl printf("\n#endif /* !%s */\n", sysproto_h) > syscompatdcl - printf("};\n\n") > sysent - if(sysvec != "") - printf(sysvec) > sysent; - else { - printf ("struct sysentvec aout_sysvec = {\n") > sysent - printf ("\tsizeof (%s) / sizeof (%s[0]),\n", \ - switchname, switchname) > sysent - printf ("\t%s,\n", switchname) > sysent - printf ("\t0,\n\t0,\n\t0,\n\t0,\n\t0,\n\t0\n};\n") \ - > sysent - } + printf("};\n") > sysent printf("};\n") > sysnames printf("#define\t%sMAXSYSCALL\t%d\n", syscallprefix, syscall) \ > syshdr } ' cat $sysinc $sysent >$syssw cat $sysarg $sysdcl $syscompat $syscompatdcl > $sysproto diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c index e270a58dbf16..8ecc51166c61 100644 --- a/sys/kern/subr_trap.c +++ b/sys/kern/subr_trap.c @@ -1,1063 +1,972 @@ /*- * Copyright (C) 1994, David Greenman * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * the University of Utah, and William Jolitz. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.71 1996/01/19 03:57:42 dyson Exp $ + * $Id: trap.c,v 1.72 1996/02/25 03:02:46 dyson Exp $ */ /* * 386 Trap and System call handling */ #include "opt_ktrace.h" #include "opt_ddb.h" #include #include #include #include #include #include #include #include #include #ifdef KTRACE #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef POWERFAIL_NMI # include # include #endif #include "isa.h" #include "npx.h" int (*pmath_emulate) __P((struct trapframe *)); extern void trap __P((struct trapframe frame)); extern int trapwrite __P((unsigned addr)); extern void syscall __P((struct trapframe frame)); -extern void linux_syscall __P((struct trapframe frame)); static int trap_pfault __P((struct trapframe *, int)); static void trap_fatal __P((struct trapframe *)); void dblfault_handler __P((void)); extern inthand_t IDTVEC(syscall); #define MAX_TRAP_MSG 27 static char *trap_msg[] = { "", /* 0 unused */ "privileged instruction fault", /* 1 T_PRIVINFLT */ "", /* 2 unused */ "breakpoint instruction fault", /* 3 T_BPTFLT */ "", /* 4 unused */ "", /* 5 unused */ "arithmetic trap", /* 6 T_ARITHTRAP */ "system forced exception", /* 7 T_ASTFLT */ "", /* 8 unused */ "general protection fault", /* 9 T_PROTFLT */ "trace trap", /* 10 T_TRCTRAP */ "", /* 11 unused */ "page fault", /* 12 T_PAGEFLT */ "", /* 13 unused */ "alignment fault", /* 14 T_ALIGNFLT */ "", /* 15 unused */ "", /* 16 unused */ "", /* 17 unused */ "integer divide fault", /* 18 T_DIVIDE */ "non-maskable interrupt trap", /* 19 T_NMI */ "overflow trap", /* 20 T_OFLOW */ "FPU bounds check fault", /* 21 T_BOUND */ "FPU device not available", /* 22 T_DNA */ "double fault", /* 23 T_DOUBLEFLT */ "FPU operand fetch fault", /* 24 T_FPOPFLT */ "invalid TSS fault", /* 25 T_TSSFLT */ "segment not present fault", /* 26 T_SEGNPFLT */ "stack fault", /* 27 T_STKFLT */ }; static void userret __P((struct proc *p, struct trapframe *frame, u_quad_t oticks)); static inline void userret(p, frame, oticks) struct proc *p; struct trapframe *frame; u_quad_t oticks; { int sig, s; while ((sig = CURSIG(p)) != 0) postsig(sig); p->p_priority = p->p_usrpri; if (want_resched) { /* * Since we are curproc, clock will normally just change * our priority without moving us from one queue to another * (since the running process is not on a queue.) * If that happened after we setrunqueue ourselves but before we * mi_switch()'ed, we might not be on the queue indicated by * our priority. */ s = splclock(); setrunqueue(p); p->p_stats->p_ru.ru_nivcsw++; mi_switch(); splx(s); while ((sig = CURSIG(p)) != 0) postsig(sig); } /* * Charge system time if profiling. */ if (p->p_flag & P_PROFIL) { u_quad_t ticks = p->p_sticks - oticks; if (ticks) { #ifdef PROFTIMER extern int profscale; addupc(frame->tf_eip, &p->p_stats->p_prof, ticks * profscale); #else addupc(frame->tf_eip, &p->p_stats->p_prof, ticks); #endif } } curpriority = p->p_priority; } /* * Exception, fault, and trap interface to the FreeBSD kernel. * This common code is called from assembly language IDT gate entry * routines that prepare a suitable stack frame, and restore this * frame after the exception has been processed. */ void trap(frame) struct trapframe frame; { struct proc *p = curproc; u_quad_t sticks = 0; int i = 0, ucode = 0, type, code; #ifdef DEBUG u_long eva; #endif type = frame.tf_trapno; code = frame.tf_err; if (ISPL(frame.tf_cs) == SEL_UPL) { /* user trap */ sticks = p->p_sticks; p->p_md.md_regs = (int *)&frame; switch (type) { case T_PRIVINFLT: /* privileged instruction fault */ ucode = type; i = SIGILL; break; case T_BPTFLT: /* bpt instruction fault */ case T_TRCTRAP: /* trace trap */ frame.tf_eflags &= ~PSL_T; i = SIGTRAP; break; case T_ARITHTRAP: /* arithmetic trap */ ucode = code; i = SIGFPE; break; case T_ASTFLT: /* Allow process switch */ astoff(); cnt.v_soft++; if (p->p_flag & P_OWEUPC) { addupc(frame.tf_eip, &p->p_stats->p_prof, 1); p->p_flag &= ~P_OWEUPC; } goto out; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ case T_STKFLT: /* stack fault */ case T_TSSFLT: /* invalid TSS fault */ case T_DOUBLEFLT: /* double fault */ default: ucode = code + BUS_SEGM_FAULT ; i = SIGBUS; break; case T_PAGEFLT: /* page fault */ i = trap_pfault(&frame, TRUE); if (i == -1) return; if (i == 0) goto out; ucode = T_PAGEFLT; break; case T_DIVIDE: /* integer divide fault */ ucode = FPE_INTDIV_TRAP; i = SIGFPE; break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI goto handle_powerfail; #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; panic("NMI indicates hardware failure"); #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ case T_OFLOW: /* integer overflow fault */ ucode = FPE_INTOVF_TRAP; i = SIGFPE; break; case T_BOUND: /* bounds check fault */ ucode = FPE_SUBRNG_TRAP; i = SIGFPE; break; case T_DNA: #if NNPX > 0 /* if a transparent fault (due to context switch "late") */ if (npxdna()) return; #endif /* NNPX > 0 */ if (!pmath_emulate) { i = SIGFPE; ucode = FPE_FPU_NP_TRAP; break; } i = (*pmath_emulate)(&frame); if (i == 0) { if (!(frame.tf_eflags & PSL_T)) return; frame.tf_eflags &= ~PSL_T; i = SIGTRAP; } /* else ucode = emulator_only_knows() XXX */ break; case T_FPOPFLT: /* FPU operand fetch fault */ ucode = T_FPOPFLT; i = SIGILL; break; } } else { /* kernel trap */ switch (type) { case T_PAGEFLT: /* page fault */ (void) trap_pfault(&frame, FALSE); return; case T_PROTFLT: /* general protection fault */ case T_SEGNPFLT: /* segment not present fault */ /* * Invalid segment selectors and out of bounds * %eip's and %esp's can be set up in user mode. * This causes a fault in kernel mode when the * kernel tries to return to user mode. We want * to get this fault so that we can fix the * problem here and not have to check all the * selectors and pointers when the user changes * them. */ #define MAYBE_DORETI_FAULT(where, whereto) \ do { \ if (frame.tf_eip == (int)where) { \ frame.tf_eip = (int)whereto; \ return; \ } \ } while (0) if (intr_nesting_level == 0) { MAYBE_DORETI_FAULT(doreti_iret, doreti_iret_fault); MAYBE_DORETI_FAULT(doreti_popl_ds, doreti_popl_ds_fault); MAYBE_DORETI_FAULT(doreti_popl_es, doreti_popl_es_fault); } if (curpcb && curpcb->pcb_onfault) { frame.tf_eip = (int)curpcb->pcb_onfault; return; } break; case T_TSSFLT: /* * PSL_NT can be set in user mode and isn't cleared * automatically when the kernel is entered. This * causes a TSS fault when the kernel attempts to * `iret' because the TSS link is uninitialized. We * want to get this fault so that we can fix the * problem here and not every time the kernel is * entered. */ if (frame.tf_eflags & PSL_NT) { frame.tf_eflags &= ~PSL_NT; return; } break; case T_TRCTRAP: /* trace trap */ if (frame.tf_eip == (int)IDTVEC(syscall)) { /* * We've just entered system mode via the * syscall lcall. Continue single stepping * silently until the syscall handler has * saved the flags. */ return; } if (frame.tf_eip == (int)IDTVEC(syscall) + 1) { /* * The syscall handler has now saved the * flags. Stop single stepping it. */ frame.tf_eflags &= ~PSL_T; return; } /* * Fall through. */ case T_BPTFLT: /* * If DDB is enabled, let it handle the debugger trap. * Otherwise, debugger traps "can't happen". */ #ifdef DDB if (kdb_trap (type, 0, &frame)) return; #endif break; #if NISA > 0 case T_NMI: #ifdef POWERFAIL_NMI #ifndef TIMER_FREQ # define TIMER_FREQ 1193182 #endif handle_powerfail: { static unsigned lastalert = 0; if(time.tv_sec - lastalert > 10) { log(LOG_WARNING, "NMI: power fail\n"); sysbeep(TIMER_FREQ/880, hz); lastalert = time.tv_sec; } return; } #else /* !POWERFAIL_NMI */ #ifdef DDB /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); if (kdb_trap (type, 0, &frame)) return; #endif /* DDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi(code) == 0) return; /* FALL THROUGH */ #endif /* POWERFAIL_NMI */ #endif /* NISA > 0 */ } trap_fatal(&frame); return; } trapsignal(p, i, ucode); #ifdef DEBUG eva = rcr2(); if (type <= MAX_TRAP_MSG) { uprintf("fatal process exception: %s", trap_msg[type]); if ((type == T_PAGEFLT) || (type == T_PROTFLT)) uprintf(", fault VA = 0x%x", eva); uprintf("\n"); } #endif out: userret(p, &frame, sticks); } #ifdef notyet /* * This version doesn't allow a page fault to user space while * in the kernel. The rest of the kernel needs to be made "safe" * before this can be used. I think the only things remaining * to be made safe are the iBCS2 code and the process tracing/ * debugging code. */ static int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va < VM_MIN_KERNEL_ADDRESS) { vm_offset_t v; vm_page_t mpte; if (p == NULL || (!usermode && va < VM_MAXUSER_ADDRESS && (curpcb == NULL || curpcb->pcb_onfault == NULL))) { trap_fatal(frame); return (-1); } /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(kernel_map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } #endif int trap_pfault(frame, usermode) struct trapframe *frame; int usermode; { vm_offset_t va; struct vmspace *vm = NULL; vm_map_t map = 0; int rv = 0; vm_prot_t ftype; int eva; struct proc *p = curproc; eva = rcr2(); va = trunc_page((vm_offset_t)eva); if (va >= KERNBASE) { /* * Don't allow user-mode faults in kernel address space. */ if (usermode) goto nogo; map = kernel_map; } else { /* * This is a fault on non-kernel virtual memory. * vm is initialized above to NULL. If curproc is NULL * or curproc->p_vmspace is NULL the fault is fatal. */ if (p != NULL) vm = p->p_vmspace; if (vm == NULL) goto nogo; map = &vm->vm_map; } if (frame->tf_err & PGEX_W) ftype = VM_PROT_READ | VM_PROT_WRITE; else ftype = VM_PROT_READ; if (map != kernel_map) { vm_offset_t v; vm_page_t mpte; /* * Keep swapout from messing with us during this * critical time. */ ++p->p_lock; /* * Grow the stack if necessary */ if ((caddr_t)va > vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { rv = KERN_FAILURE; --p->p_lock; goto nogo; } } /* * Check if page table is mapped, if not, * fault it first */ v = (vm_offset_t) vtopte(va); /* Fault the pte only if needed: */ if (*((int *)vtopte(v)) == 0) (void) vm_fault(map, trunc_page(v), VM_PROT_WRITE, FALSE); mpte = pmap_use_pt( vm_map_pmap(map), va); /* Fault in the user page: */ rv = vm_fault(map, va, ftype, FALSE); pmap_unuse_pt( vm_map_pmap(map), va, mpte); --p->p_lock; } else { /* * Since we know that kernel virtual address addresses * always have pte pages mapped, we just have to fault * the page. */ rv = vm_fault(map, va, ftype, FALSE); } if (rv == KERN_SUCCESS) return (0); nogo: if (!usermode) { if (curpcb && curpcb->pcb_onfault) { frame->tf_eip = (int)curpcb->pcb_onfault; return (0); } trap_fatal(frame); return (-1); } /* kludge to pass faulting virtual address to sendsig */ frame->tf_err = eva; return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV); } static void trap_fatal(frame) struct trapframe *frame; { int code, type, eva; struct soft_segment_descriptor softseg; code = frame->tf_err; type = frame->tf_trapno; eva = rcr2(); sdtossd(&gdt[IDXSEL(frame->tf_cs & 0xffff)].sd, &softseg); if (type <= MAX_TRAP_MSG) printf("\n\nFatal trap %d: %s while in %s mode\n", type, trap_msg[type], ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); if (type == T_PAGEFLT) { printf("fault virtual address = 0x%x\n", eva); printf("fault code = %s %s, %s\n", code & PGEX_U ? "user" : "supervisor", code & PGEX_W ? "write" : "read", code & PGEX_P ? "protection violation" : "page not present"); } printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n", softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type); printf(" = DPL %d, pres %d, def32 %d, gran %d\n", softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran); printf("processor eflags = "); if (frame->tf_eflags & PSL_T) printf("trace/trap, "); if (frame->tf_eflags & PSL_I) printf("interrupt enabled, "); if (frame->tf_eflags & PSL_NT) printf("nested task, "); if (frame->tf_eflags & PSL_RF) printf("resume, "); if (frame->tf_eflags & PSL_VM) printf("vm86, "); printf("IOPL = %d\n", (frame->tf_eflags & PSL_IOPL) >> 12); printf("current process = "); if (curproc) { printf("%lu (%s)\n", (u_long)curproc->p_pid, curproc->p_comm ? curproc->p_comm : ""); } else { printf("Idle\n"); } printf("interrupt mask = "); if ((cpl & net_imask) == net_imask) printf("net "); if ((cpl & tty_imask) == tty_imask) printf("tty "); if ((cpl & bio_imask) == bio_imask) printf("bio "); if (cpl == 0) printf("none"); printf("\n"); #ifdef KDB if (kdb_trap(&psl)) return; #endif #ifdef DDB if (kdb_trap (type, 0, frame)) return; #endif if (type <= MAX_TRAP_MSG) panic(trap_msg[type]); else panic("unknown/reserved trap"); } /* * Double fault handler. Called when a fault occurs while writing * a frame for a trap/exception onto the stack. This usually occurs * when the stack overflows (such is the case with infinite recursion, * for example). * * XXX Note that the current PTD gets replaced by IdlePTD when the * task switch occurs. This means that the stack that was active at * the time of the double fault is not available at unless * the machine was idle when the double fault occurred. The downside * of this is that "trace " in ddb won't work. */ void dblfault_handler() { struct pcb *pcb = curpcb; if (pcb != NULL) { printf("\nFatal double fault:\n"); printf("eip = 0x%x\n", pcb->pcb_tss.tss_eip); printf("esp = 0x%x\n", pcb->pcb_tss.tss_esp); printf("ebp = 0x%x\n", pcb->pcb_tss.tss_ebp); } panic("double fault"); } /* * Compensate for 386 brain damage (missing URKR). * This is a little simpler than the pagefault handler in trap() because * it the page tables have already been faulted in and high addresses * are thrown out early for other reasons. */ int trapwrite(addr) unsigned addr; { struct proc *p; vm_offset_t va, v; struct vmspace *vm; int rv; va = trunc_page((vm_offset_t)addr); /* * XXX - MAX is END. Changed > to >= for temp. fix. */ if (va >= VM_MAXUSER_ADDRESS) return (1); p = curproc; vm = p->p_vmspace; ++p->p_lock; if ((caddr_t)va >= vm->vm_maxsaddr && (caddr_t)va < (caddr_t)USRSTACK) { if (!grow(p, va)) { --p->p_lock; return (1); } } v = trunc_page(vtopte(va)); /* * wire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), FALSE); } /* * fault the data page */ rv = vm_fault(&vm->vm_map, va, VM_PROT_READ|VM_PROT_WRITE, FALSE); /* * unwire the pte page */ if (va < USRSTACK) { vm_map_pageable(&vm->vm_map, v, round_page(v+1), TRUE); } --p->p_lock; if (rv != KERN_SUCCESS) return 1; return (0); } /* * System call request from POSIX system call gate interface to kernel. * Like trap(), argument is call by reference. */ void syscall(frame) struct trapframe frame; { caddr_t params; int i; struct sysent *callp; struct proc *p = curproc; u_quad_t sticks; int error; int args[8], rval[2]; u_int code; sticks = p->p_sticks; if (ISPL(frame.tf_cs) != SEL_UPL) panic("syscall"); p->p_md.md_regs = (int *)&frame; params = (caddr_t)frame.tf_esp + sizeof(int); code = frame.tf_eax; - /* - * Need to check if this is a 32 bit or 64 bit syscall. - */ - if (code == SYS_syscall) { - /* - * Code is first argument, followed by actual args. - */ - code = fuword(params); - params += sizeof(int); - } else if (code == SYS___syscall) { + if (p->p_sysent->sv_prepsyscall) { + (*p->p_sysent->sv_prepsyscall)(&frame, args, &code, ¶ms); + } else { /* - * Like syscall, but code is a quad, so as to maintain - * quad alignment for the rest of the arguments. + * Need to check if this is a 32 bit or 64 bit syscall. */ - code = fuword(params); - params += sizeof(quad_t); + if (code == SYS_syscall) { + /* + * Code is first argument, followed by actual args. + */ + code = fuword(params); + params += sizeof(int); + } else if (code == SYS___syscall) { + /* + * Like syscall, but code is a quad, so as to maintain + * quad alignment for the rest of the arguments. + */ + code = fuword(params); + params += sizeof(quad_t); + } } if (p->p_sysent->sv_mask) code &= p->p_sysent->sv_mask; if (code >= p->p_sysent->sv_size) callp = &p->p_sysent->sv_table[0]; else callp = &p->p_sysent->sv_table[code]; - if ((i = callp->sy_narg * sizeof(int)) && + if (params && (i = callp->sy_narg * sizeof(int)) && (error = copyin(params, (caddr_t)args, (u_int)i))) { #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif goto bad; } #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p->p_tracep, code, callp->sy_narg, args); #endif rval[0] = 0; rval[1] = frame.tf_edx; error = (*callp->sy_call)(p, args, rval); switch (error) { case 0: /* * Reinitialize proc pointer `p' as it may be different * if this is a child returning from fork syscall. */ p = curproc; frame.tf_eax = rval[0]; frame.tf_edx = rval[1]; frame.tf_eflags &= ~PSL_C; break; case ERESTART: /* - * Reconstruct pc, assuming lcall $X,y is 7 bytes. + * Reconstruct pc, assuming lcall $X,y is 7 bytes, + * int 0x80 is 2 bytes. We saved this in tf_err. */ - frame.tf_eip -= 7; + frame.tf_eip -= frame.tf_err; break; case EJUSTRETURN: break; default: bad: if (p->p_sysent->sv_errsize) if (error >= p->p_sysent->sv_errsize) error = -1; /* XXX */ else error = p->p_sysent->sv_errtbl[error]; frame.tf_eax = error; frame.tf_eflags |= PSL_C; break; } if (frame.tf_eflags & PSL_T) { /* Traced syscall. */ frame.tf_eflags &= ~PSL_T; trapsignal(p, SIGTRAP, 0); } userret(p, &frame, sticks); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) ktrsysret(p->p_tracep, code, error, rval[0]); #endif } - -#if defined(COMPAT_LINUX) || defined(LINUX) -void -linux_syscall(frame) - struct trapframe frame; -{ - struct proc *p = curproc; - struct sysent *callp; - u_quad_t sticks; - int error; - int rval[2]; - u_int code; - struct linux_syscall_args { - int arg1; - int arg2; - int arg3; - int arg4; - int arg5; - } args; - - args.arg1 = frame.tf_ebx; - args.arg2 = frame.tf_ecx; - args.arg3 = frame.tf_edx; - args.arg4 = frame.tf_esi; - args.arg5 = frame.tf_edi; - - sticks = p->p_sticks; - if (ISPL(frame.tf_cs) != SEL_UPL) - panic("linux syscall"); - - p->p_md.md_regs = (int *)&frame; - code = frame.tf_eax; - - if (p->p_sysent->sv_mask) - code &= p->p_sysent->sv_mask; - - if (code >= p->p_sysent->sv_size) - callp = &p->p_sysent->sv_table[0]; - else - callp = &p->p_sysent->sv_table[code]; - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p->p_tracep, code, callp->sy_narg, (int *)&args); -#endif - - rval[0] = 0; - - error = (*callp->sy_call)(p, &args, rval); - - switch (error) { - - case 0: - /* - * Reinitialize proc pointer `p' as it may be different - * if this is a child returning from fork syscall. - */ - p = curproc; - frame.tf_eax = rval[0]; - frame.tf_eflags &= ~PSL_C; - break; - - case ERESTART: - /* Reconstruct pc, subtract size of int 0x80 */ - frame.tf_eip -= 2; - break; - - case EJUSTRETURN: - break; - - default: - if (p->p_sysent->sv_errsize) - if (error >= p->p_sysent->sv_errsize) - error = -1; /* XXX */ - else - error = p->p_sysent->sv_errtbl[error]; - frame.tf_eax = -error; - frame.tf_eflags |= PSL_C; - break; - } - - if (frame.tf_eflags & PSL_T) { - /* Traced syscall. */ - frame.tf_eflags &= ~PSL_T; - trapsignal(p, SIGTRAP, 0); - } - - userret(p, &frame, sticks); - -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p->p_tracep, code, error, rval[0]); -#endif -} -#endif /* COMPAT_LINUX || LINUX */ diff --git a/sys/sys/_sigset.h b/sys/sys/_sigset.h index f718a371dc4b..23a255cd74a5 100644 --- a/sys/sys/_sigset.h +++ b/sys/sys/_sigset.h @@ -1,203 +1,206 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)signal.h 8.2 (Berkeley) 1/21/94 - * $Id: signal.h,v 1.5 1995/10/19 19:16:00 swallace Exp $ + * $Id: signal.h,v 1.6 1996/01/22 12:31:15 mpp Exp $ */ #ifndef _SYS_SIGNAL_H_ #define _SYS_SIGNAL_H_ #include #include /* sig_atomic_t; trap codes; sigcontext */ #if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) #define NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ #endif #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instruction (not reset when caught) */ #ifndef _POSIX_SOURCE #define SIGTRAP 5 /* trace trap (not reset when caught) */ #endif #define SIGABRT 6 /* abort() */ #ifndef _POSIX_SOURCE #define SIGIOT SIGABRT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #endif #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #ifndef _POSIX_SOURCE #define SIGBUS 10 /* bus error */ #endif #define SIGSEGV 11 /* segmentation violation */ #ifndef _POSIX_SOURCE #define SIGSYS 12 /* non-existent system call invoked */ #endif #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #ifndef _POSIX_SOURCE #define SIGURG 16 /* urgent condition on IO channel */ #endif #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ #ifndef _POSIX_SOURCE #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGINFO 29 /* information request */ #endif #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ /*- * Type of a signal handling function. * * Language spec sez signal handlers take exactly one arg, even though we * actually supply three. Ugh! * * We don't try to hide the difference by leaving out the args because * that would cause warnings about conformant programs. Nonconformant * programs can avoid the warnings by casting to (__sighandler_t *) or * sig_t before calling signal() or assigning to sa_handler or sv_handler. * * The kernel should reverse the cast before calling the function. It * has no way to do this, but on most machines 1-arg and 3-arg functions * have the same calling protocol so there is no problem in practice. * A bit in sa_flags could be used to specify the number of args. */ typedef void __sighandler_t __P((int)); #define SIG_DFL ((__sighandler_t *)0) #define SIG_IGN ((__sighandler_t *)1) #define SIG_ERR ((__sighandler_t *)-1) #ifndef _ANSI_SOURCE typedef unsigned int sigset_t; /* * Signal vector "template" used in sigaction call. */ struct sigaction { __sighandler_t *sa_handler; /* signal handler */ sigset_t sa_mask; /* signal mask to apply */ int sa_flags; /* see signal options below */ }; #ifndef _POSIX_SOURCE #define SA_ONSTACK 0x0001 /* take signal on signal stack */ #define SA_RESTART 0x0002 /* restart system call on signal return */ -#define SA_DISABLE 0x0004 /* disable taking signals on alternate stack */ +#define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ +#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ #ifdef COMPAT_SUNOS #define SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */ #endif -#endif +#endif /* _POSIX_SOURCE */ #define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ -#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ /* * Flags for sigprocmask: */ #define SIG_BLOCK 1 /* block specified signal set */ #define SIG_UNBLOCK 2 /* unblock specified signal set */ #define SIG_SETMASK 3 /* set specified signal set */ #ifndef _POSIX_SOURCE typedef __sighandler_t *sig_t; /* type of pointer to a signal function */ /* * Structure used in sigaltstack call. */ struct sigaltstack { char *ss_sp; /* signal stack base */ int ss_size; /* signal stack length */ - int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */ + int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ }; +#define SS_ONSTACK 0x0001 /* take signal on alternate stack */ +#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ #define MINSIGSTKSZ 8192 /* minimum allowable stack */ #define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ /* * 4.3 compatibility: * Signal vector "template" used in sigvec call. */ struct sigvec { __sighandler_t *sv_handler; /* signal handler */ int sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK SA_ONSTACK #define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ +#define SV_RESETHAND SA_RESETHAND #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) (1 << ((m)-1)) #define BADSIG SIG_ERR #endif /* !_POSIX_SOURCE */ #endif /* !_ANSI_SOURCE */ /* * For historical reasons; programs expect signal's return value to be * defined by . */ __BEGIN_DECLS __sighandler_t *signal __P((int, __sighandler_t *)); __END_DECLS #endif /* !_SYS_SIGNAL_H_ */ diff --git a/sys/sys/exec.h b/sys/sys/exec.h index 4ace86b02e14..f9338e7ebb9f 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -1,81 +1,81 @@ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)exec.h 8.3 (Berkeley) 1/21/94 - * $Id: exec.h,v 1.11 1995/11/13 07:44:03 bde Exp $ + * $Id: exec.h,v 1.12 1995/12/09 04:29:07 peter Exp $ */ #ifndef _SYS_EXEC_H_ #define _SYS_EXEC_H_ /* * The following structure is found at the top of the user stack of each * user process. The ps program uses it to locate argv and environment * strings. Programs that wish ps to display other information may modify * it; normally ps_argvstr points to the argv vector, and ps_nargvstr * is the same as the program's argc. The fields ps_envstr and ps_nenvstr * are the equivalent for the environment. */ struct ps_strings { char **ps_argvstr; /* first of 0 or more argument strings */ int ps_nargvstr; /* the number of argument strings */ char **ps_envstr; /* first of 0 or more environment strings */ int ps_nenvstr; /* the number of environment strings */ }; /* * Address of ps_strings structure (in user space). */ -#define SPARE_USRSPACE 256 #define PS_STRINGS ((struct ps_strings *) \ (USRSTACK - sizeof(struct ps_strings))) +#define SPARE_USRSPACE 256 struct image_params; struct execsw { int (*ex_imgact)(struct image_params *); const char *ex_name; }; #ifdef KERNEL extern const struct execsw **execsw; #endif #include #endif diff --git a/sys/sys/signal.h b/sys/sys/signal.h index f718a371dc4b..23a255cd74a5 100644 --- a/sys/sys/signal.h +++ b/sys/sys/signal.h @@ -1,203 +1,206 @@ /* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)signal.h 8.2 (Berkeley) 1/21/94 - * $Id: signal.h,v 1.5 1995/10/19 19:16:00 swallace Exp $ + * $Id: signal.h,v 1.6 1996/01/22 12:31:15 mpp Exp $ */ #ifndef _SYS_SIGNAL_H_ #define _SYS_SIGNAL_H_ #include #include /* sig_atomic_t; trap codes; sigcontext */ #if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) #define NSIG 32 /* counting 0; could be 33 (mask is 1-32) */ #endif #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instruction (not reset when caught) */ #ifndef _POSIX_SOURCE #define SIGTRAP 5 /* trace trap (not reset when caught) */ #endif #define SIGABRT 6 /* abort() */ #ifndef _POSIX_SOURCE #define SIGIOT SIGABRT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #endif #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #ifndef _POSIX_SOURCE #define SIGBUS 10 /* bus error */ #endif #define SIGSEGV 11 /* segmentation violation */ #ifndef _POSIX_SOURCE #define SIGSYS 12 /* non-existent system call invoked */ #endif #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #ifndef _POSIX_SOURCE #define SIGURG 16 /* urgent condition on IO channel */ #endif #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ #ifndef _POSIX_SOURCE #define SIGIO 23 /* input/output possible signal */ #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #define SIGWINCH 28 /* window size changes */ #define SIGINFO 29 /* information request */ #endif #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */ /*- * Type of a signal handling function. * * Language spec sez signal handlers take exactly one arg, even though we * actually supply three. Ugh! * * We don't try to hide the difference by leaving out the args because * that would cause warnings about conformant programs. Nonconformant * programs can avoid the warnings by casting to (__sighandler_t *) or * sig_t before calling signal() or assigning to sa_handler or sv_handler. * * The kernel should reverse the cast before calling the function. It * has no way to do this, but on most machines 1-arg and 3-arg functions * have the same calling protocol so there is no problem in practice. * A bit in sa_flags could be used to specify the number of args. */ typedef void __sighandler_t __P((int)); #define SIG_DFL ((__sighandler_t *)0) #define SIG_IGN ((__sighandler_t *)1) #define SIG_ERR ((__sighandler_t *)-1) #ifndef _ANSI_SOURCE typedef unsigned int sigset_t; /* * Signal vector "template" used in sigaction call. */ struct sigaction { __sighandler_t *sa_handler; /* signal handler */ sigset_t sa_mask; /* signal mask to apply */ int sa_flags; /* see signal options below */ }; #ifndef _POSIX_SOURCE #define SA_ONSTACK 0x0001 /* take signal on signal stack */ #define SA_RESTART 0x0002 /* restart system call on signal return */ -#define SA_DISABLE 0x0004 /* disable taking signals on alternate stack */ +#define SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */ +#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ #ifdef COMPAT_SUNOS #define SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */ #endif -#endif +#endif /* _POSIX_SOURCE */ #define SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */ -#define SA_NODEFER 0x0010 /* don't mask the signal we're delivering */ /* * Flags for sigprocmask: */ #define SIG_BLOCK 1 /* block specified signal set */ #define SIG_UNBLOCK 2 /* unblock specified signal set */ #define SIG_SETMASK 3 /* set specified signal set */ #ifndef _POSIX_SOURCE typedef __sighandler_t *sig_t; /* type of pointer to a signal function */ /* * Structure used in sigaltstack call. */ struct sigaltstack { char *ss_sp; /* signal stack base */ int ss_size; /* signal stack length */ - int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */ + int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */ }; +#define SS_ONSTACK 0x0001 /* take signal on alternate stack */ +#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */ #define MINSIGSTKSZ 8192 /* minimum allowable stack */ #define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */ /* * 4.3 compatibility: * Signal vector "template" used in sigvec call. */ struct sigvec { __sighandler_t *sv_handler; /* signal handler */ int sv_mask; /* signal mask to apply */ int sv_flags; /* see signal options below */ }; #define SV_ONSTACK SA_ONSTACK #define SV_INTERRUPT SA_RESTART /* same bit, opposite sense */ +#define SV_RESETHAND SA_RESETHAND #define sv_onstack sv_flags /* isn't compatibility wonderful! */ /* * Structure used in sigstack call. */ struct sigstack { char *ss_sp; /* signal stack pointer */ int ss_onstack; /* current status */ }; /* * Macro for converting signal number to a mask suitable for * sigblock(). */ #define sigmask(m) (1 << ((m)-1)) #define BADSIG SIG_ERR #endif /* !_POSIX_SOURCE */ #endif /* !_ANSI_SOURCE */ /* * For historical reasons; programs expect signal's return value to be * defined by . */ __BEGIN_DECLS __sighandler_t *signal __P((int, __sighandler_t *)); __END_DECLS #endif /* !_SYS_SIGNAL_H_ */ diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index 46c15f93d3b5..78bfa9fb1f02 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -1,172 +1,173 @@ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * * @(#)signalvar.h 8.3 (Berkeley) 1/4/94 - * $Id: signalvar.h,v 1.8 1995/12/14 08:32:34 phk Exp $ + * $Id: signalvar.h,v 1.9 1996/01/31 12:44:31 davidg Exp $ */ #ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */ #define _SYS_SIGNALVAR_H_ /* * Kernel signal definitions and data structures, * not exported to user programs. */ /* * Process signal actions and state, needed only within the process * (not necessarily resident). */ struct sigacts { sig_t ps_sigact[NSIG]; /* disposition of signals */ sigset_t ps_catchmask[NSIG]; /* signals to be blocked */ sigset_t ps_sigonstack; /* signals to take on sigstack */ sigset_t ps_sigintr; /* signals that interrupt syscalls */ sigset_t ps_oldmask; /* saved mask from before sigpause */ int ps_flags; /* signal flags, below */ struct sigaltstack ps_sigstk; /* sp & on stack state variable */ int ps_sig; /* for core dump/debugger XXX */ int ps_code; /* for core dump/debugger XXX */ int ps_addr; /* for core dump/debugger XXX */ sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX */ sigset_t ps_nodefer; /* signals not to defer */ + sigset_t ps_sigreset; /* signals that reset when caught */ }; /* signal flags */ #define SAS_OLDMASK 0x01 /* need to restore mask before pause */ #define SAS_ALTSTACK 0x02 /* have alternate signal stack */ /* additional signal action values, used only temporarily/internally */ #define SIG_CATCH ((__sighandler_t *)2) #define SIG_HOLD ((__sighandler_t *)3) /* * get signal action for process and signal; currently only for current process */ #define SIGACTION(p, sig) (p->p_sigacts->ps_sigact[(sig)]) /* * Determine signal that should be delivered to process p, the current * process, 0 if none. If there is a pending stop signal with default * action, the process stops in issig(). */ #define CURSIG(p) \ (((p)->p_siglist == 0 || \ (((p)->p_flag & P_TRACED) == 0 && \ ((p)->p_siglist & ~(p)->p_sigmask) == 0)) ? \ 0 : issignal(p)) /* * Clear a pending signal from a process. */ #define CLRSIG(p, sig) { (p)->p_siglist &= ~sigmask(sig); } /* * Signal properties and actions. * The array below categorizes the signals and their default actions * according to the following properties: */ #define SA_KILL 0x01 /* terminates process by default */ #define SA_CORE 0x02 /* ditto and coredumps */ #define SA_STOP 0x04 /* suspend process */ #define SA_TTYSTOP 0x08 /* ditto, from tty */ #define SA_IGNORE 0x10 /* ignore by default */ #define SA_CONT 0x20 /* continue if suspended */ #define SA_CANTMASK 0x40 /* non-maskable, catchable */ #ifdef SIGPROP static int sigprop[NSIG + 1] = { 0, /* unused */ SA_KILL, /* SIGHUP */ SA_KILL, /* SIGINT */ SA_KILL|SA_CORE, /* SIGQUIT */ SA_KILL|SA_CORE, /* SIGILL */ SA_KILL|SA_CORE, /* SIGTRAP */ SA_KILL|SA_CORE, /* SIGABRT */ SA_KILL|SA_CORE, /* SIGEMT */ SA_KILL|SA_CORE, /* SIGFPE */ SA_KILL, /* SIGKILL */ SA_KILL|SA_CORE, /* SIGBUS */ SA_KILL|SA_CORE, /* SIGSEGV */ SA_KILL|SA_CORE, /* SIGSYS */ SA_KILL, /* SIGPIPE */ SA_KILL, /* SIGALRM */ SA_KILL, /* SIGTERM */ SA_IGNORE, /* SIGURG */ SA_STOP, /* SIGSTOP */ SA_STOP|SA_TTYSTOP, /* SIGTSTP */ SA_IGNORE|SA_CONT, /* SIGCONT */ SA_IGNORE, /* SIGCHLD */ SA_STOP|SA_TTYSTOP, /* SIGTTIN */ SA_STOP|SA_TTYSTOP, /* SIGTTOU */ SA_IGNORE, /* SIGIO */ SA_KILL, /* SIGXCPU */ SA_KILL, /* SIGXFSZ */ SA_KILL, /* SIGVTALRM */ SA_KILL, /* SIGPROF */ SA_IGNORE, /* SIGWINCH */ SA_IGNORE, /* SIGINFO */ SA_KILL, /* SIGUSR1 */ SA_KILL, /* SIGUSR2 */ }; #define contsigmask (sigmask(SIGCONT)) #define stopsigmask (sigmask(SIGSTOP) | sigmask(SIGTSTP) | \ sigmask(SIGTTIN) | sigmask(SIGTTOU)) #endif /* SIGPROP */ #define sigcantmask (sigmask(SIGKILL) | sigmask(SIGSTOP)) #ifdef KERNEL /* * Machine-independent functions: */ void execsigs __P((struct proc *p)); void gsignal __P((int pgid, int sig)); int issig __P((struct proc *p)); int issignal __P((struct proc *p)); void killproc __P((struct proc *, char *)); void pgsignal __P((struct pgrp *pgrp, int sig, int checkctty)); void postsig __P((int sig)); void psignal __P((struct proc *p, int sig)); void setsigvec __P((struct proc *, int, struct sigaction *)); void sigexit __P((struct proc *, int)); void siginit __P((struct proc *p)); void trapsignal __P((struct proc *p, int sig, unsigned code)); /* * Machine-dependent functions: */ void sendsig __P((sig_t action, int sig, int returnmask, unsigned code)); #endif /* KERNEL */ #endif /* !_SYS_SIGNALVAR_H_ */ diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 7c44d5b211b8..262a7d9defa8 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -1,67 +1,74 @@ /*- * Copyright (c) 1982, 1988, 1991 The Regents of the University of California. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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: sysent.h,v 1.5 1995/09/19 13:31:04 bde Exp $ + * $Id: sysent.h,v 1.6 1995/11/21 12:55:14 bde Exp $ */ #ifndef _SYS_SYSENT_H_ #define _SYS_SYSENT_H_ 1 typedef int sy_call_t __P((struct proc *, void *, int *)); struct sysent { /* system call table */ int sy_narg; /* number of arguments */ sy_call_t *sy_call; /* implementing function */ }; struct image_params; +struct trapframe; struct sysentvec { int sv_size; /* number of entries */ struct sysent *sv_table; /* pointer to sysent */ unsigned int sv_mask; /* optional mask to index */ int sv_sigsize; /* size of signal translation table */ int *sv_sigtbl; /* signal translation table */ int sv_errsize; /* size of signal translation table */ int *sv_errtbl; /* errno translation table */ int (*sv_fixup) __P((int **, struct image_params *)); /* stack fixup function */ + void (*sv_sendsig) __P((sig_t, int, int, unsigned)); + /* send signal */ + char *sv_sigcode; /* start of sigtramp code */ + int *sv_szsigcode; /* size of sigtramp code */ + void (*sv_prepsyscall) __P((struct trapframe *, int *, + u_int *, caddr_t *)); }; #ifdef KERNEL extern struct sysentvec aout_sysvec; extern struct sysent sysent[]; #endif #endif /* _SYS_SYSENT_H_ */