From 0ae8dceaebe3659ee0c3352c08125f403e77ebca Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 28 Sep 1999 22:25:29 +0000 Subject: Merge with 2.3.10. --- arch/mips/Makefile | 3 +- arch/mips/boot/elf2ecoff.c | 1 - arch/mips/config.in | 4 +- arch/mips/defconfig | 31 ++- arch/mips/defconfig-ip22 | 297 ++++++++++++++++++++++++++++ arch/mips/kernel/irixelf.c | 75 +++---- arch/mips/kernel/irixioctl.c | 19 +- arch/mips/kernel/irixsig.c | 40 ++-- arch/mips/kernel/irq.c | 6 +- arch/mips/kernel/process.c | 18 +- arch/mips/kernel/ptrace.c | 233 ++-------------------- arch/mips/kernel/r2300_fpu.S | 13 +- arch/mips/kernel/r4k_fpu.S | 16 +- arch/mips/kernel/r4k_misc.S | 6 +- arch/mips/kernel/setup.c | 12 +- arch/mips/kernel/signal.c | 438 ++++++++++++++++++++++++++--------------- arch/mips/kernel/syscalls.h | 8 +- arch/mips/mm/fault.c | 30 ++- arch/mips/mm/r4xx0.c | 6 +- arch/mips/sgi/kernel/indy_sc.c | 3 +- arch/mips/tools/offset.c | 16 +- 21 files changed, 747 insertions(+), 528 deletions(-) create mode 100644 arch/mips/defconfig-ip22 (limited to 'arch/mips') diff --git a/arch/mips/Makefile b/arch/mips/Makefile index e6e83b34a..f839b134f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.19 1999/08/18 23:37:42 ralf Exp $ +# $Id: Makefile,v 1.20 1999/08/20 21:59:01 ralf Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive @@ -117,7 +117,6 @@ SUBDIRS += arch/mips/sgi/kernel arch/mips/arc # 8kb aligned or the handling of the current variable will break. # LOADADDR += 0x88002000 -HOSTCC = cc endif # diff --git a/arch/mips/boot/elf2ecoff.c b/arch/mips/boot/elf2ecoff.c index 55f5896c5..dc8e981e6 100644 --- a/arch/mips/boot/elf2ecoff.c +++ b/arch/mips/boot/elf2ecoff.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/arch/mips/config.in b/arch/mips/config.in index f7fb7b2e9..9a1d95025 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.29 1999/08/18 23:37:42 ralf Exp $ +# $Id: config.in,v 1.30 1999/08/20 21:59:01 ralf Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -123,7 +123,7 @@ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_SGI_IP22" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then - tristate 'Parallel port support' CONFIG_PARPORT + source drivers/misc/Config.in fi endmenu diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 828f2477e..3aa72b746 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -28,6 +28,9 @@ CONFIG_CPU_R4X00=y # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_WB is not set # # General setup @@ -62,11 +65,6 @@ CONFIG_KMOD=y # CONFIG_I2O_SCSI is not set # CONFIG_I2O_PROC is not set -# -# Plug and Play support -# -# CONFIG_PNP is not set - # # Block devices # @@ -87,6 +85,7 @@ CONFIG_BLK_DEV_IDECD=m # CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_IDEPCI is not set # CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_CPQ_DA is not set # # Additional Block Devices @@ -202,9 +201,17 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set @@ -217,7 +224,6 @@ CONFIG_PCNET32=y # CONFIG_CS89x0 is not set # CONFIG_DE4X5 is not set # CONFIG_DEC_ELCP is not set -# CONFIG_DEC_ELCP is not set # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set # CONFIG_NE2K_PCI is not set @@ -225,14 +231,22 @@ CONFIG_PCNET32=y # CONFIG_VIA_RHINE is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set -# CONFIG_DLCI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set + +# +# Token ring devices +# # CONFIG_TR is not set + +# +# Wan interfaces +# # CONFIG_HOSTESS_SV11 is not set # CONFIG_COSA is not set -# CONFIG_RCPCI is not set +# CONFIG_SEALEVEL_4021 is not set +# CONFIG_DLCI is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set @@ -387,5 +401,4 @@ CONFIG_VGA_CONSOLE=y # # CONFIG_CROSSCOMPILE is not set # CONFIG_MIPS_FPE_MODULE is not set -# CONFIG_REMOTE_DEBUG is not set # CONFIG_MAGIC_SYSRQ is not set diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 new file mode 100644 index 000000000..6658c84ea --- /dev/null +++ b/arch/mips/defconfig-ip22 @@ -0,0 +1,297 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_ALGOR_P4032 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_OLIVETTI_M700 is not set +CONFIG_SGI_IP22=y +# CONFIG_SNI_RM200_PCI is not set + +# +# CPU selection +# +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_WB is not set + +# +# General setup +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_ELF_KERNEL=y +CONFIG_BINFMT_IRIX=y +CONFIG_FORWARD_KEYBOARD=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y +# CONFIG_FB is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_CPQ_DA is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE_PARPORT=m +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_NETLINK is not set +# CONFIG_FIREWALL is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_IP_ROUTER is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set +# CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# +# CONFIG_INET_RARP is not set +# CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set +# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CDrom) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y + +# +# SCSI low-level drivers +# +CONFIG_SCSI_SGIWD93=y + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_SLIP is not set +# CONFIG_PPP is not set +CONFIG_SGISEEQ=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set +CONFIG_MOUSE=y + +# +# Mice +# +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# USB drivers - not for the faint of heart +# +# CONFIG_USB is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +CONFIG_NFSD=y +# CONFIG_NFSD_SUN is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set + +# +# Partition Types +# +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_SMD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +CONFIG_SGI_DISKLABEL=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_SGI_NEWPORT_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# SGI devices +# +CONFIG_SGI_SERIAL=y +CONFIG_SERIAL=y +CONFIG_SGI_DS1286=y +# CONFIG_SGI_NEWPORT_GFX is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set +# CONFIG_REMOTE_DEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 4b512e14b..3eadd1832 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -1,4 +1,4 @@ -/* $Id: irixelf.c,v 1.19 1999/08/04 05:28:51 ulfc Exp $ +/* $Id: irixelf.c,v 1.20 1999/08/04 14:54:04 ulfc Exp $ * * irixelf.c: Code to load IRIX ELF executables which conform to * the MIPS ABI. @@ -624,9 +624,10 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, has_interp = has_ephdr = 0; elf_ihdr = elf_ephdr = 0; elf_ex = *((struct elfhdr *) bprm->buf); - - if(verify_binary(&elf_ex, bprm)) - return -ENOEXEC; + retval = -ENOEXEC; + + if (verify_binary(&elf_ex, bprm)) + goto out; #ifdef DEBUG_ELF print_elfhdr(&elf_ex); @@ -634,15 +635,19 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, /* Now read in all of the header information */ size = elf_ex.e_phentsize * elf_ex.e_phnum; + if (size > 65536) + goto out; elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); - if (elf_phdata == NULL) - return -ENOMEM; - + if (elf_phdata == NULL) { + retval = -ENOMEM; + goto out; + } + retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata, size, 1); if (retval < 0) - goto out_phdata; - + goto out_free_ph; + #ifdef DEBUG_ELF dump_phdrs(elf_phdata, elf_ex.e_phnum); #endif @@ -668,39 +673,39 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, elf_brk = 0; retval = open_dentry(bprm->dentry, O_RDONLY); if (retval < 0) - goto out_phdata; + goto out_free_ph; file = fget(elf_exec_fileno = retval); - + elf_stack = 0xffffffff; elf_interpreter = NULL; start_code = 0xffffffff; end_code = 0; end_data = 0; - + retval = look_for_irix_interpreter(&elf_interpreter, &interpreter_dentry, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); if(retval) - goto out_file; - + goto out_free_file; + if(elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); if(retval) - goto out_interp; + goto out_free_interp; } - + /* OK, we are done with that, now set up the arg stuff, * and then start this sucker up. */ retval = -E2BIG; if (!bprm->sh_bang && !bprm->p) - goto out_interp; - + goto out_free_interp; + /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) - goto out_interp; + goto out_free_dentry; /* OK, This is the point of no return */ current->mm->end_data = 0; @@ -715,15 +720,16 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, current->mm->rss = 0; setup_arg_pages(bprm); current->mm->start_stack = bprm->p; - + /* At this point, we assume that the image should be loaded at * fixed address, not at a variable address. */ old_fs = get_fs(); set_fs(get_ds()); - - map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr, - &start_code, &elf_bss, &end_code, &end_data, &elf_brk); + + map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, + &load_addr, &start_code, &elf_bss, &end_code, + &end_data, &elf_brk); if(elf_interpreter) { retval = map_interpreter(elf_phdata, &interp_elf_ex, @@ -740,7 +746,7 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, } set_fs(old_fs); - + kfree(elf_phdata); fput(file); sys_close(elf_exec_fileno); @@ -805,17 +811,20 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; +out: + return retval; -out_interp: - if(elf_interpreter) { - kfree(elf_interpreter); - } -out_file: +out_free_dentry: + dput(interpreter_dentry); +out_free_interp: + if (elf_interpreter) + kfree(elf_interpreter); +out_free_file: fput(file); sys_close(elf_exec_fileno); -out_phdata: +out_free_ph: kfree (elf_phdata); - return retval; + goto out; } static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) @@ -1069,11 +1078,11 @@ struct memelfnote static int notesize(struct memelfnote *en) { int sz; - + sz = sizeof(struct elf_note); sz += roundup(strlen(en->name), 4); sz += roundup(en->datasz, 4); - + return sz; } diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c index c05c6609a..10ca5b15e 100644 --- a/arch/mips/kernel/irixioctl.c +++ b/arch/mips/kernel/irixioctl.c @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.5 1999/02/01 01:28:55 ralf Exp $ +/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -29,20 +29,21 @@ extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count); extern void start_tty(struct tty_struct *tty); - static struct tty_struct *get_tty(int fd) { struct file *filp; + struct tty_struct *ttyp = NULL; - if(!(filp = fcheck(fd))) - return ((struct tty_struct *) 0); - if(filp->private_data) { - struct tty_struct *ttyp = (struct tty_struct *) filp->private_data; + read_lock(¤t->files->file_lock); + filp = fcheck(fd); + if(filp && filp->private_data) { + ttyp = (struct tty_struct *) filp->private_data; - if(ttyp->magic == TTY_MAGIC) - return ttyp; + if(ttyp->magic != TTY_MAGIC) + ttyp =NULL; } - return ((struct tty_struct *) 0); + read_unlock(¤t->files->file_lock); + return ttyp; } static struct tty_struct *get_real_tty(struct tty_struct *tp) diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 693d72110..7ec7b175c 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: irixsig.c,v 1.10 1999/01/03 17:50:50 ralf Exp $ + * $Id: irixsig.c,v 1.11 1999/06/17 13:25:46 ralf Exp $ */ #include @@ -114,17 +114,17 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, dump_irix5_sigctx(ctx); #endif - regs->regs[5] = 0; /* XXX sigcode XXX */ regs->regs[4] = (unsigned long) signr; + regs->regs[5] = 0; /* XXX sigcode XXX */ regs->regs[6] = regs->regs[29] = sp; regs->regs[7] = (unsigned long) ka->sa.sa_handler; - regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline; + regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa.sa_restorer; return; segv_and_exit: - lock_kernel(); - do_exit(SIGSEGV); - unlock_kernel(); + if (signr == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void inline @@ -300,11 +300,12 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) return 0; } -asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) +asmlinkage void +irix_sigreturn(struct pt_regs *regs) { struct sigctx_irix5 *context, *magic; unsigned long umask, mask; - u64 *fregs, res; + u64 *fregs; int sig, i, base = 0; sigset_t blocked; @@ -365,11 +366,7 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) /* Unreached */ badframe: - lock_kernel(); - do_exit(SIGSEGV); - unlock_kernel(); - - return res; + force_sig(SIGSEGV, current); } struct sigact_irix5 { @@ -390,7 +387,7 @@ static inline void dump_sigact_irix5(struct sigact_irix5 *p) asmlinkage int irix_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact, unsigned long trampoline) + struct sigaction *oact, void *trampoline) { struct k_sigaction new_ka, old_ka; int ret; @@ -410,15 +407,14 @@ irix_sigaction(int sig, const struct sigaction *act, return -EFAULT; __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); - new_ka.ka_restorer = NULL; - } - /* - * Hmmm... methinks IRIX libc always passes a valid trampoline - * value for all invocations of sigaction. Will have to - * investigate. POSIX POSIX, die die die... - */ - current->tss.irix_trampoline = trampoline; + /* + * Hmmm... methinks IRIX libc always passes a valid trampoline + * value for all invocations of sigaction. Will have to + * investigate. POSIX POSIX, die die die... + */ + new_ka.sa.sa_restorer = trampoline; + } /* XXX Implement SIG_SETMASK32 for IRIX compatibility */ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c index 1b99fa99f..b083e3686 100644 --- a/arch/mips/kernel/irq.c +++ b/arch/mips/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.14 1999/02/15 02:16:50 ralf Exp $ +/* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -356,7 +356,7 @@ static int i8259_irq_cannonicalize(int irq) return ((irq == 2) ? 9 : irq); } -__initfunc(static void i8259_init(void)) +static void __init i8259_init(void) { /* Init master interrupt controller */ outb(0x11, 0x20); /* Start init sequence */ @@ -376,7 +376,7 @@ __initfunc(static void i8259_init(void)) outb(cached_21, 0x21); } -__initfunc(void init_IRQ(void)) +void __init init_IRQ(void) { irq_cannonicalize = i8259_irq_cannonicalize; /* i8259_init(); */ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index a8c59ff78..8e1afd78f 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.12 1999/06/17 13:25:46 ralf Exp $ +/* $Id: process.c,v 1.14 1999/08/09 19:43:14 harald Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -34,18 +34,6 @@ struct task_struct *last_task_used_math = NULL; asmlinkage void ret_from_sys_call(void); -/* - * Do necessary setup to start up a newly executed thread. - */ -void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) -{ - /* New thread looses kernel privileges. */ - regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|KU_MASK)) | KU_USER; - regs->cp0_epc = pc; - regs->regs[29] = sp; - current->tss.current_ds = USER_DS; -} - void exit_thread(void) { /* Forget lazy fpu state */ @@ -66,10 +54,6 @@ void flush_thread(void) } } -void release_thread(struct task_struct *dead_task) -{ -} - int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index c8e3d23b6..68084ab3d 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.15 1999/08/09 19:43:14 harald Exp $ +/* $Id: ptrace.c,v 1.16 1999/08/18 23:37:43 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -25,218 +25,6 @@ #include #include -/* - * This routine gets a long from any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - */ -static unsigned long get_long(struct task_struct * tsk, - struct vm_area_struct * vma, unsigned long addr) -{ - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page, retval; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (pgd_none(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return 0; - } - pgmiddle = pmd_offset(pgdir, addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return 0; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 0); - goto repeat; - } - page = pte_page(*pgtable); - /* This is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) >= MAP_NR(high_memory)) - return 0; - page += addr & ~PAGE_MASK; - /* We can't use flush_page_to_ram() since we're running in - * another context ... - */ - flush_cache_all(); - retval = *(unsigned long *) page; - flush_cache_all(); /* VCED avoidance */ - return retval; -} - -/* - * This routine puts a long into any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - * Now keeps R/W state of page so that a text page stays readonly - * even if a debugger scribbles breakpoints into it. -M.U- - */ -static void put_long(struct task_struct *tsk, - struct vm_area_struct * vma, unsigned long addr, - unsigned long data) -{ - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return; - } - pgmiddle = pmd_offset(pgdir, addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - page = pte_page(*pgtable); - if (!pte_write(*pgtable)) { - handle_mm_fault(tsk, vma, addr, 1); - goto repeat; - } - /* This is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) < MAP_NR(high_memory)) - flush_cache_all(); - *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data; - if (MAP_NR(page) < MAP_NR(high_memory)) - flush_cache_all(); - /* - * We're bypassing pagetables, so we have to set the dirty bit - * ourselves this should also re-instate whatever read-only mode - * there was before - */ - set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); - flush_tlb_page(vma, addr); -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls get_long() to read a long. - */ -static int read_long(struct task_struct * tsk, unsigned long addr, - unsigned long * result) -{ - struct vm_area_struct * vma = find_extend_vma(tsk, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_high = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_high = vma->vm_next; - if (!vma_high || vma_high->vm_start != vma->vm_end) - return -EIO; - } - low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); - high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 1: - low >>= 8; - low |= high << 24; - break; - case 2: - low >>= 16; - low |= high << 16; - break; - case 3: - low >>= 24; - low |= high << 8; - break; - } - *result = low; - } else - *result = get_long(tsk, vma, addr); - return 0; -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls put_long() to write a long. - */ -static int write_long(struct task_struct * tsk, unsigned long addr, - unsigned long data) -{ - struct vm_area_struct * vma = find_extend_vma(tsk, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_high = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_high = vma->vm_next; - if (!vma_high || vma_high->vm_start != vma->vm_end) - return -EIO; - } - low = get_long(tsk, vma, addr & ~(sizeof(long)-1)); - high = get_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 0: /* shouldn't happen, but safety first */ - low = data; - break; - case 1: - low &= 0x000000ff; - low |= data << 8; - high &= ~0xff; - high |= data >> 24; - break; - case 2: - low &= 0x0000ffff; - low |= data << 16; - high &= ~0xffff; - high |= data >> 16; - break; - case 3: - low &= 0x00ffffff; - low |= data << 24; - high &= ~0xffffff; - high |= data >> 8; - break; - } - put_long(tsk, vma, addr & ~(sizeof(long)-1),low); - put_long(tsk, vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high); - } else - put_long(tsk, vma, addr, data); - return 0; -} - asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -323,15 +111,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; + int copied; - down(&child->mm->mmap_sem); - res = read_long(child, addr, &tmp); - up(&child->mm->mmap_sem); - if (res < 0) + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + res = -EIO; + if (copied != sizeof(tmp)) goto out; res = put_user(tmp,(unsigned long *) data); + goto out; - } + } /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { @@ -397,9 +186,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - down(&child->mm->mmap_sem); - res = write_long(child,addr,data); - up(&child->mm->mmap_sem); + res = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) + == sizeof(data)) + goto out; + res = -EIO; goto out; case PTRACE_POKEUSR: { diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index 74671f58c..efb00dce1 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S @@ -1,4 +1,5 @@ -/* $Id: r2300_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $ +/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $ + * * r2300_fpu.S: Save/restore floating point context for signal handlers. * * This file is subject to the terms and conditions of the GNU General Public @@ -14,6 +15,7 @@ * Copyright (c) 1998 Harald Koerfgen */ #include +#include #include #include #include @@ -29,7 +31,7 @@ .set mips1 /* Save floating point context */ LEAF(save_fp_context) - + li v0, 0 # assume success cfc1 t1,fcr31 EX(swc1 $f0,(SC_FPREGS+0)(a0)) EX(swc1 $f1,(SC_FPREGS+8)(a0)) @@ -81,6 +83,7 @@ LEAF(save_fp_context) * stack frame which might have been changed by the user. */ LEAF(restore_fp_context) + li v0, 0 # assume success EX(lw t0,SC_FPC_CSR(a0)) EX(lwc1 $f0,(SC_FPREGS+0)(a0)) EX(lwc1 $f1,(SC_FPREGS+8)(a0)) @@ -117,3 +120,9 @@ LEAF(restore_fp_context) jr ra ctc1 t0,fcr31 END(restore_fp_context) + + .type fault@function + .ent fault +fault: li v0, -EFAULT + jr ra + .end fault diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 39ec93b57..4624416e7 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S @@ -1,4 +1,5 @@ -/* +/* $Id: r4k_fpu.S,v 1.7 1999/08/18 23:37:44 ralf Exp $ + * * r4k_fpu.S: Save/restore floating point context for signal handlers. * * This file is subject to the terms and conditions of the GNU General Public @@ -9,10 +10,9 @@ * * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: r4k_fpu.S,v 1.6 1999/08/09 19:43:15 harald Exp $ */ #include +#include #include #include #include @@ -21,13 +21,14 @@ #define EX(a,b) \ 9: a,##b; \ .section __ex_table,"a"; \ - PTR 9b,bad_stack; \ + PTR 9b, fault; \ .previous .set noreorder .set mips3 /* Save floating point context */ LEAF(save_fp_context) + li v0, 0 # assume success cfc1 t1,fcr31 /* Store the 16 even double precision registers */ @@ -67,6 +68,7 @@ LEAF(save_fp_context) * stack frame which might have been changed by the user. */ LEAF(restore_fp_context) + li v0, 0 # assume success EX(lw t0,SC_FPC_CSR(a0)) /* @@ -92,3 +94,9 @@ LEAF(restore_fp_context) jr ra ctc1 t0,fcr31 END(restore_fp_context) + + .type fault@function + .ent fault +fault: li v0, -EFAULT + jr ra + .end fault diff --git a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S index c791f3275..d83f85b81 100644 --- a/arch/mips/kernel/r4k_misc.S +++ b/arch/mips/kernel/r4k_misc.S @@ -1,19 +1,17 @@ -/* +/* $Id: r4k_misc.S,v 1.6 1999/08/18 23:37:44 ralf Exp $ + * * r4k_misc.S: Misc. exception handling code for r4k. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse * * Multi-cpu abstraction and reworking: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: r4k_misc.S,v 1.5 1999/08/09 19:43:15 harald Exp $ */ #include #include #include #include #include -#include #include #include #include diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index b8a2b4303..fd6650b1c 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.17 1999/08/20 21:59:02 ralf Exp $ +/* $Id: setup.c,v 1.18 1999/09/18 20:48:03 harald Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -30,7 +30,6 @@ #endif #include #ifdef CONFIG_RTC -#include #include #endif @@ -67,15 +66,6 @@ char cyclecounter_available; */ int EISA_bus = 0; -/* - * Milo passes some information to the kernel that looks like as if it - * had been returned by a Intel PC BIOS. Milo doesn't fill the passed - * drive_info and Linux can find out about this anyway, so I'm going to - * remove this sometime. screen_info contains information about the - * resolution of the text screen. For VGA graphics based machine this - * information is being use to continue the screen output just below - * the BIOS printed text and with the same text resolution. - */ struct screen_info screen_info; #ifdef CONFIG_BLK_DEV_FD diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 6c63bea25..0a7190412 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -1,11 +1,12 @@ -/* $Id: signal.c,v 1.20 1999/08/09 19:43:15 harald Exp $ +/* $Id: signal.c,v 1.21 1999/08/24 22:54:21 ralf Exp $ * - * linux/arch/mips/kernel/signal.c + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle - * - * XXX Handle lazy fp context switches correctly. + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1994 - 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include #include @@ -24,16 +25,17 @@ #include #include #include +#include #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, +extern asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage void save_fp_context(struct sigcontext *sc); -extern asmlinkage void restore_fp_context(struct sigcontext *sc); +extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); +extern asmlinkage int save_fp_context(struct sigcontext *sc); +extern asmlinkage int restore_fp_context(struct sigcontext *sc); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -52,6 +54,7 @@ sys_sigsuspend(struct pt_regs regs) spin_lock_irq(¤t->sigmask_lock); saveset = current->blocked; current->blocked = newset; + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs.regs[2] = EINTR; @@ -67,17 +70,25 @@ sys_sigsuspend(struct pt_regs regs) asmlinkage int sys_rt_sigsuspend(struct pt_regs regs) { - sigset_t *uset, saveset, newset; + sigset_t *unewset, saveset, newset; + size_t sigsetsize; save_static(®s); - uset = (sigset_t *) regs.regs[4]; - if (copy_from_user(&newset, uset, sizeof(sigset_t))) + + /* XXX Don't preclude handling different sized sigset_t's. */ + sigsetsize = regs.regs[5]; + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + unewset = (sigset_t *) regs.regs[4]; + if (copy_from_user(&newset, unewset, sizeof(newset))) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); saveset = current->blocked; current->blocked = newset; + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs.regs[2] = EINTR; @@ -91,65 +102,74 @@ sys_rt_sigsuspend(struct pt_regs regs) } asmlinkage int -sys_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) +sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { struct k_sigaction new_ka, old_ka; int ret; + int err = 0; if (act) { - sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + old_sigset_t mask; + + if (!access_ok(VERIFY_READ, act, sizeof(*act))) + return -EFAULT; + err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); + err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); + err |= __get_user(mask, &act->sa_mask.sig[0]); + err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer); + if (err) return -EFAULT; - __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); - new_ka.ka_restorer = NULL; + siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) + return -EFAULT; + err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); + err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); + err |= __put_user(0, &oact->sa_mask.sig[1]); + err |= __put_user(0, &oact->sa_mask.sig[2]); + err |= __put_user(0, &oact->sa_mask.sig[3]); + err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer); + if (err) return -EFAULT; - __copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, - sizeof(sigset_t)); } return ret; } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss) +sys_sigaltstack(struct pt_regs regs) { - struct pt_regs *regs = (struct pt_regs *) &uss; + const stack_t *uss = (const stack_t *) regs.regs[4]; + stack_t *uoss = (stack_t *) regs.regs[5]; + unsigned long usp = regs.regs[29]; - return do_sigaltstack(uss, uoss, regs->regs[29]); + return do_sigaltstack(uss, uoss, usp); } -/* - * To do: this entire function should be accessed over a function pointer - * such that we can handle stack frames for different ABIs. - */ - -asmlinkage void -restore_sigcontext(struct pt_regs *regs, struct sigcontext *context) +asmlinkage int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - long long reg; int owned_fp; + int err = 0; + u64 reg; - __get_user(regs->cp0_epc, &context->sc_pc); + err |= __get_user(regs->cp0_epc, &sc->sc_pc); - __get_user(reg, &context->sc_mdhi); + err |= __get_user(reg, &sc->sc_mdhi); regs->hi = (int) reg; - __get_user(reg, &context->sc_mdlo); + err |= __get_user(reg, &sc->sc_mdlo); regs->lo = (int) reg; -#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \ - regs->regs[i] = (int) reg; +#define restore_gp_reg(i) do { \ + err |= __get_user(reg, &sc->sc_regs[i]); \ + regs->regs[i] = reg; \ +} while(0); restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); @@ -163,55 +183,40 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *context) restore_gp_reg(31); #undef restore_gp_reg - /* FP depends on what FPU in what mode we have. */ - __get_user(owned_fp, &context->sc_ownedfp); -#if 0 + err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { - restore_fp_context(context); + err |= restore_fp_context(sc); last_task_used_math = current; } -#endif -restore_fp_context(context); + + return err; } -/* - * The structure sc describes the stackframe on the userstack. The frames - * are identical for normal and realtime signal stackframes with the - * exception of the additional struct ucontext for rt frames. - */ struct sigframe { - unsigned long ass[4]; /* argument save space for o32 */ - unsigned int code[4]; /* signal trampoline */ - struct sigcontext scc; + u32 sf_ass[4]; /* argument save space for o32 */ + u32 sf_code[2]; /* signal trampoline */ + struct sigcontext sf_sc; + sigset_t sf_mask; }; struct rt_sigframe { - unsigned long ass[4]; - unsigned int code[4]; - struct sigcontext scc; - // struct ucontext uc; + u32 rs_ass[4]; /* argument save space for o32 */ + u32 rs_code[2]; /* signal trampoline */ + struct siginfo rs_info; + struct ucontext rs_uc; }; -asmlinkage int sys_sigreturn(struct pt_regs regs) +asmlinkage void +sys_sigreturn(struct pt_regs regs) { - struct sigcontext *context; + struct sigframe *frame; sigset_t blocked; - context = (struct sigcontext *)(long) regs.regs[29]; - if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || - (regs.regs[29] & (SZREG - 1))) - goto badframe; - -#if 1 - if (__get_user(blocked.sig[0], &context->sc_sigset[0]) || - __get_user(blocked.sig[1], &context->sc_sigset[1]) || - __get_user(blocked.sig[2], &context->sc_sigset[2]) || - __get_user(blocked.sig[3], &context->sc_sigset[3])) + frame = (struct sigframe *) regs.regs[29]; + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; -#else - if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked))) + if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) goto badframe; -#endif sigdelsetmask(&blocked, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); @@ -219,63 +224,79 @@ asmlinkage int sys_sigreturn(struct pt_regs regs) recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - restore_sigcontext(®s, context); + if (restore_sigcontext(®s, &frame->sf_sc)) + goto badframe; /* * Don't let your children do this ... */ __asm__ __volatile__( - "move\t$29,%0\n\t" + "move\t$29, %0\n\t" "j\tret_from_sys_call" :/* no outputs */ :"r" (®s)); /* Unreached */ badframe: - lock_kernel(); - do_exit(SIGSEGV); - unlock_kernel(); + force_sig(SIGSEGV, current); } -/* same as sys_sigreturn for now */ -asmlinkage int sys_rt_sigreturn(struct pt_regs regs) +asmlinkage void +sys_rt_sigreturn(struct pt_regs regs) { - return -ENOSYS; -} + struct rt_sigframe *frame; + sigset_t set; + stack_t st; -#define scc_offset ((size_t)&((struct sigframe *)0)->scc) + frame = (struct rt_sigframe *) regs.regs[29]; + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) + goto badframe; -/* - * Set up the return code ... - * - * .set noreorder - * addiu sp,0x20 - * li v0,__NR_sigreturn - * syscall - * .set reorder - */ -static void inline -setup_trampoline(unsigned int *code) -{ - __put_user(0x27bd0000 + scc_offset , code + 0); - __put_user(0x24020000 + __NR_sigreturn, code + 1); - __put_user(0x0000000c , code + 2); + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) + goto badframe; + + if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, regs.regs[29]); /* - * Flush caches so that the instructions will be correctly executed. + * Don't let your children do this ... */ - flush_cache_sigtramp((unsigned long) code); + __asm__ __volatile__( + "move\t$29, %0\n\t" + "j\tret_from_sys_call" + :/* no outputs */ + :"r" (®s)); + /* Unreached */ + +badframe: + force_sig(SIGSEGV, current); } -static void inline -setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set) +static int inline +setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { int owned_fp; + int err = 0; + u64 reg; - __put_user(regs->cp0_epc, &sc->sc_pc); - __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ + err |= __put_user(regs->cp0_epc, &sc->sc_pc); + err |= __put_user(regs->cp0_status, &sc->sc_status); -#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)]) +#define save_gp_reg(i) { \ + reg = regs->regs[i]; \ + err |= __put_user(reg, &sc->sc_regs[i]); \ +} while(0) __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); @@ -287,57 +308,93 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set) save_gp_reg(31); #undef save_gp_reg - __put_user(regs->hi, &sc->sc_mdhi); - __put_user(regs->lo, &sc->sc_mdlo); - __put_user(regs->cp0_cause, &sc->sc_cause); + err |= __put_user(regs->hi, &sc->sc_mdhi); + err |= __put_user(regs->lo, &sc->sc_mdlo); + err |= __put_user(regs->cp0_cause, &sc->sc_cause); + err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); owned_fp = (current == last_task_used_math); - __put_user(owned_fp, &sc->sc_ownedfp); + err |= __put_user(owned_fp, &sc->sc_ownedfp); -#if 0 if (current->used_math) { /* fp is active. */ set_cp0_status(ST0_CU1, ST0_CU1); - save_fp_context(sc); /* CPU-dependent */ + err |= save_fp_context(sc); last_task_used_math = NULL; regs->cp0_status &= ~ST0_CU1; current->used_math = 0; } -#endif -set_cp0_status(ST0_CU1, ST0_CU1); -save_fp_context(sc); /* CPU-dependent */ - __put_user(set->sig[0], &sc->sc_sigset[0]); - __put_user(set->sig[1], &sc->sc_sigset[1]); - __put_user(set->sig[2], &sc->sc_sigset[2]); - __put_user(set->sig[3], &sc->sc_sigset[3]); + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + unsigned long sp; + + /* Default to using normal stack */ + sp = regs->regs[29]; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *)((sp - frame_size) & ALMASK); } static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *oldmask) + int signr, sigset_t *set) { struct sigframe *frame; - struct sigcontext *sc; - - /* Align the stackframe to an adequate boundary for the architecture. */ - frame = (struct sigframe *) (long) regs->regs[29]; - frame--; - frame = (struct sigframe *)((unsigned long)frame & ALMASK); - - if (verify_area(VERIFY_WRITE, frame, sizeof (*frame))) - goto segv_and_exit; - sc = &frame->scc; + int err = 0; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + goto give_sigsegv; + + /* Set up to return from userspace. If provided, use a stub already + in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) + regs->regs[31] = (unsigned long) ka->sa.sa_restorer; + else { + /* + * Set up the return code ... + * + * li v0, __NR_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_sigreturn, + frame->sf_code + 0); + err |= __put_user(0x0000000c , + frame->sf_code + 1); + flush_cache_sigtramp((unsigned long) frame->sf_code); + } - setup_trampoline(frame->code); - setup_sigcontext(regs, &frame->scc, oldmask); + err |= setup_sigcontext(regs, &frame->sf_sc); + err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); + if (err) + goto give_sigsegv; - regs->regs[4] = signr; /* arguments */ - regs->regs[5] = 0; /* should be cause */ - regs->regs[6] = (long) frame; /* ptr to sigcontext */ - regs->regs[29] = (unsigned long) frame; /* Stack pointer */ - regs->regs[31] = (unsigned long) frame->code; /* Return address */ - regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */ - regs->regs[25] = regs->cp0_epc; /* PIC shit... */ + /* + * Arguments to signal handler: + * + * a0 = signal number + * a1 = 0 (should be cause) + * a2 = pointer to struct sigcontext + * + * $25 and c0_epc point to the signal handler, $29 points to the + * struct sigframe. + */ + regs->regs[ 4] = signr; + regs->regs[ 5] = 0; + regs->regs[ 6] = (unsigned long) &frame->sf_sc; + regs->regs[29] = (unsigned long) frame; + regs->regs[31] = (unsigned long) frame->sf_code; + regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", @@ -345,22 +402,90 @@ setup_frame(struct k_sigaction * ka, struct pt_regs *regs, #endif return; -segv_and_exit: - lock_kernel(); - do_exit(SIGSEGV); - unlock_kernel(); +give_sigsegv: + if (signr == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *oldmask, siginfo_t *info) + int signr, sigset_t *set, siginfo_t *info) { - printk("Aiee: setup_tr_frame wants to be written"); -} + struct rt_sigframe *frame; + int err = 0; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) + goto give_sigsegv; + + /* Set up to return from userspace. If provided, use a stub already + in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) + regs->regs[31] = (unsigned long) ka->sa.sa_restorer; + else { + /* + * Set up the return code ... + * + * li v0, __NR_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_sigreturn, + frame->rs_code + 0); + err |= __put_user(0x0000000c , + frame->rs_code + 1); + flush_cache_sigtramp((unsigned long) frame->rs_code); + } -/* ------------------------------------------------------------------------- */ + /* Create siginfo. */ + err |= __copy_to_user(&frame->rs_info, info, sizeof(*info)); -static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + /* Create the ucontext. */ + err |= __put_user(0, &frame->rs_uc.uc_flags); + err |= __put_user(0, &frame->rs_uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->rs_uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->regs[29]), + &frame->rs_uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, + &frame->rs_uc.uc_stack.ss_size); + err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); + err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); + + if (err) + goto give_sigsegv; + + /* + * Arguments to signal handler: + * + * a0 = signal number + * a1 = 0 (should be cause) + * a2 = pointer to ucontext + * + * $25 and c0_epc point to the signal handler, $29 points to + * the struct rt_sigframe. + */ + regs->regs[ 4] = signr; + regs->regs[ 5] = (unsigned long) &frame->rs_info; + regs->regs[ 6] = (unsigned long) &frame->rs_uc; + regs->regs[29] = (unsigned long) frame; + regs->regs[31] = (unsigned long) frame->rs_code; + regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", + current->comm, current->pid, frame, regs->cp0_epc, frame->code); +#endif + return; + +give_sigsegv: + if (signr == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +static inline void +handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { if (ka->sa.sa_flags & SA_SIGINFO) @@ -379,7 +504,8 @@ static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, } } -static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +static inline void +syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { switch(regs->regs[0]) { case ERESTARTNOHAND: @@ -407,7 +533,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) siginfo_t info; #ifdef CONFIG_BINFMT_IRIX - if (current->personality != PER_LINUX) /* XXX */ + if (current->personality != PER_LINUX) return do_irix_signal(oldset, regs); #endif @@ -533,13 +659,3 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) } return 0; } - -/* - * Compatibility syscall. Can be replaced in libc. - */ -asmlinkage int sys_pause(void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h index 07a49ee8b..ef593845e 100644 --- a/arch/mips/kernel/syscalls.h +++ b/arch/mips/kernel/syscalls.h @@ -1,4 +1,4 @@ -/* $Id: syscalls.h,v 1.15 1998/09/19 19:16:17 ralf Exp $ +/* $Id: syscalls.h,v 1.16 1999/07/11 23:56:29 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -44,7 +44,7 @@ SYS(sys_stime, 1) /* 4025 */ SYS(sys_ptrace, 4) SYS(sys_alarm, 1) SYS(sys_fstat, 2) -SYS(sys_pause, 0) +SYS(sys_ni_syscall, 0) SYS(sys_utime, 2) /* 4030 */ SYS(sys_ni_syscall, 0) SYS(sys_ni_syscall, 0) @@ -214,14 +214,14 @@ SYS(sys_rt_sigprocmask, 4) /* 4195 */ SYS(sys_rt_sigpending, 2) SYS(sys_rt_sigtimedwait, 4) SYS(sys_rt_sigqueueinfo, 3) -SYS(sys_rt_sigsuspend, 2) +SYS(sys_rt_sigsuspend, 0) SYS(sys_pread, 6) /* 4200 */ SYS(sys_pwrite, 6) SYS(sys_chown, 3) SYS(sys_getcwd, 2) SYS(sys_capget, 2) SYS(sys_capset, 2) /* 4205 */ -SYS(sys_sigaltstack, 2) +SYS(sys_sigaltstack, 0) SYS(sys_sendfile, 3) SYS(sys_ni_syscall, 0) SYS(sys_ni_syscall, 0) diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index cacb97115..f7cbbfc71 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.10 1999/08/09 19:43:16 harald Exp $ +/* $Id: fault.c,v 1.11 1999/08/18 23:37:45 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -43,7 +43,7 @@ unsigned long asid_cache = ASID_FIRST_VERSION; * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { struct vm_area_struct * vma; @@ -59,7 +59,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, goto no_context; #if 0 printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, - address, writeaccess, regs->cp0_epc); + address, write, regs->cp0_epc); #endif down(&mm->mmap_sem); vma = find_vma(mm, address); @@ -76,7 +76,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, * we can handle it.. */ good_area: - if (writeaccess) { + if (write) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { @@ -89,8 +89,13 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ - if (!handle_mm_fault(tsk, vma, address, writeaccess)) - goto do_sigbus; + { + int fault = handle_mm_fault(tsk, vma, address, write); + if (fault < 0) + goto out_of_memory; + if (!fault) + goto do_sigbus; + } up(&mm->mmap_sem); return; @@ -104,12 +109,12 @@ bad_area: if (user_mode(regs)) { tsk->tss.cp0_badvaddr = address; - tsk->tss.error_code = writeaccess; + tsk->tss.error_code = write; #if 0 printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n" "%08lx (epc == %08lx, ra == %08lx)\n", tsk->comm, - writeaccess ? "writeaccess to" : "readaccess from", + write ? "write access to" : "read access from", address, (unsigned long) regs->cp0_epc, (unsigned long) regs->regs[31]); @@ -140,13 +145,20 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request at virtual " "address %08lx, epc == %08lx, ra == %08lx\n", address, regs->cp0_epc, regs->regs[31]); - die("Oops", regs, writeaccess); + die("Oops", regs, write); do_exit(SIGKILL); /* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ +out_of_memory: + up(&mm->mmap_sem); + printk("VM: killing process %s\n", tsk->comm); + if (user_mode(regs)) + do_exit(SIGKILL); + goto no_context; + do_sigbus: up(&mm->mmap_sem); diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c index be843351e..e1c3251f8 100644 --- a/arch/mips/mm/r4xx0.c +++ b/arch/mips/mm/r4xx0.c @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.22 1999/06/17 13:25:51 ralf Exp $ +/* $Id: r4xx0.c,v 1.23 1999/08/09 19:43:16 harald Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -2202,7 +2202,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr) unsigned int flags; daddr = addr & ~(dc_lsize - 1); - save_and_cli(flags); + __save_and_cli(flags); /* Clear internal cache refill buffer */ *(volatile unsigned int *)KSEG1; @@ -2212,7 +2212,7 @@ static void r4600v20k_flush_cache_sigtramp(unsigned long addr) iaddr = addr & ~(ic_lsize - 1); protected_flush_icache_line(iaddr); protected_flush_icache_line(iaddr + ic_lsize); - restore_flags(flags); + __restore_flags(flags); } #undef DEBUG_TLB diff --git a/arch/mips/sgi/kernel/indy_sc.c b/arch/mips/sgi/kernel/indy_sc.c index 2aff56637..1fecee23f 100644 --- a/arch/mips/sgi/kernel/indy_sc.c +++ b/arch/mips/sgi/kernel/indy_sc.c @@ -1,4 +1,4 @@ -/* $Id: indy_sc.c,v 1.8 1999/05/10 17:40:16 ulfc Exp $ +/* $Id: indy_sc.c,v 1.9 1999/05/12 21:57:49 ulfc Exp $ * * indy_sc.c: Indy cache managment functions. * @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c index f32f3e76e..ede1d5f93 100644 --- a/arch/mips/tools/offset.c +++ b/arch/mips/tools/offset.c @@ -1,9 +1,10 @@ -/* $Id: offset.c,v 1.9 1998/08/25 09:14:52 ralf Exp $ +/* $Id: offset.c,v 1.10 1999/08/18 23:37:46 ralf Exp $ * * offset.c: Calculate pt_regs and task_struct offsets. * * Copyright (C) 1996 David S. Miller - * Made portable by Ralf Baechle + * Copyright (C) 1997, 1998, 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include @@ -126,20 +127,17 @@ void output_mm_defines(void) void output_sc_defines(void) { text("/* Linux sigcontext offsets. */"); - offset("#define SC_REGMASK ", struct sigcontext, sc_regmask); - offset("#define SC_STATUS ", struct sigcontext, sc_status); - offset("#define SC_PC ", struct sigcontext, sc_pc); offset("#define SC_REGS ", struct sigcontext, sc_regs); offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); + offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); + offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); + offset("#define SC_PC ", struct sigcontext, sc_pc); + offset("#define SC_STATUS ", struct sigcontext, sc_status); offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp); offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); - offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags); - offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); - offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); offset("#define SC_CAUSE ", struct sigcontext, sc_cause); offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); - offset("#define SC_SIGSET ", struct sigcontext, sc_sigset); linefeed; } -- cgit v1.2.3